web-dev-qa-db-ja.com

Linuxユーザー名前空間では、なぜclone()は/ procをマウントできますが、unshare()はマウントできませんか?

Linuxユーザーの名前空間に_/proc_をマウントするためにroot以外のユーザーを取得しようとしています。

clone()を介して名前空間を作成すると、_/proc_をマウントできます。

ただし、unshare()を介して名前空間を作成すると、mount()の呼び出しは_Operation not permitted_で失敗します。

名前空間がmount()ではなくclone()で作成された場合、unshare()の動作が異なるのはなぜですか。

以下のコードは違いを示しています。

_#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;

}
_

出力:

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

カーネル_Linux 4.15.0-20-generic_を使用してUbuntu18.04で実行しています。私は上記のコードを非ルートとして実行しています。

3
mpb

あなたはまだ「間違った」PID名前空間にいると思います。つまり、procfsインスタンスをマウントする権限がありません。

CLONE_NEWPID [...]呼び出しプロセスは新しい名前空間に移動されません。呼び出し元のプロセスによって作成された最初の子は、プロセスID 1を持ち、新しい名前空間でinit(1)の役割を引き受けます。

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

比較する

CLONE_NEWPID [...] CLONE_NEWPIDが設定されている場合は、新しいPID名前空間にプロセスを作成します。

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

4
sourcejedi