1

I am trying to get a non-root user to mount /proc in a Linux user namespace.

If I create a namespace via clone(), then I can mount /proc.

However, if I create a namespace via unshare(), then the call to mount() fails with Operation not permitted.

Why does mount() behave differently when the namespace is created with clone() as opposed to unshare()?

The below code demonstrates the difference.

#define   _GNU_SOURCE
#include  <errno.h>
#include  <sched.h>
#include  <stdio.h>
#include  <stdlib.h>
#include  <string.h>
#include  <unistd.h>
#include  <sys/syscall.h>
#include  <sys/mount.h>
#include  <sys/types.h>
#include  <sys/stat.h>
#include  <sys/wait.h>
#include  <fcntl.h>


#define STACK_SIZE (1024 * 1024)

static char child_stack[STACK_SIZE];    /* Space for child's stack */


void  try  ( const char * msg, int rv )  {
  printf ( "%-8s  %6d  %s\n", msg, rv, strerror ( rv < 0 ? errno : 0 ) );
}


int  child  ( void * arg )  {
  try(  "mount_1",   mount   (  "PROC", "/proc", "proc", 0, NULL  ));
  try(  "umount_1",  umount  (  "/proc"                           ));
  return  0;
}


int  main  ()  {

  int  clone_flags  =  0;

  clone_flags  |=  CLONE_NEWNET;
  clone_flags  |=  CLONE_NEWNS;
  clone_flags  |=  CLONE_NEWPID;
  clone_flags  |=  CLONE_NEWUSER;

  try(  "clone",    clone    (  child, child_stack + STACK_SIZE,
                                clone_flags | SIGCHLD, NULL       ));
  try(  "wait",     wait     (  NULL                              ));
  try(  "unshare",  unshare  (  clone_flags                       ));
  try(  "mount_2",  mount    (  "PROC", "/proc", "proc", 0, NULL  ));

  return  0;

}

Output:

clone      31478  Success
mount_1        0  Success
umount_1       0  Success
wait       31478  Success
unshare        0  Success
mount_2       -1  Operation not permitted

I am running on Ubuntu 18.04 with kernel Linux 4.15.0-20-generic. I am running the above code as non-root.

3

I think you're still in the "wrong" PID namespace, and that means you don't have permission to mount the procfs instance.

CLONE_NEWPID [...] The calling process is not moved into the new namespace. The first child created by the calling process will have the process ID 1 and will assume the role of init(1) in the new namespace.

http://man7.org/linux/man-pages/man2/unshare.2.html

Compare

CLONE_NEWPID [...] If CLONE_NEWPID is set, then create the process in a new PID namespace.

http://man7.org/linux/man-pages/man2/clone.2.html

  • It certainly appears you are correct. If I unshare() followed by a fork(), then the child process can mount /proc. Thanks! – mpb Nov 10 '18 at 3:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.