procのhidepidオプション


/procをlsすると、動作している全プロセスpidでディレクトリが作成されますが、procfsをマウントする時、hidepid=1でマウントすると、プロセスIDは表示されますが、カレントPID以外は参照できません。hidepid=2でマウントすると他のpidのディレクトリそのものが表示されません。デフォルトはオプション0でマウントされています。
[kitamura@localhost proc]$ ls -l | sort -k 3
合計 0
dr-xr-xr-x  8 apache   apache            0  7月 24 03:48 1151
dr-xr-xr-x  8 apache   apache            0  7月 24 03:48 1152
dr-xr-xr-x  8 apache   apache            0  7月 24 03:48 1153
dr-xr-xr-x  8 apache   apache            0  7月 24 03:48 1154
dr-xr-xr-x  8 apache   apache            0  7月 24 03:48 1155
dr-xr-xr-x  8 apache   apache            0  7月 24 03:48 1156
dr-xr-xr-x  8 apache   apache            0  7月 24 03:48 1157
dr-xr-xr-x  8 apache   apache            0  7月 24 03:48 1158
dr-xr-xr-x  8 avahi    avahi             0  7月 24 03:48 843
dr-xr-xr-x  8 avahi    avahi             0  7月 24 03:48 865
dr-xr-xr-x  8 dbus     dbus              0  7月 24 03:48 866
dr-xr-xr-x  8 kitamura kitamura          0  7月 24 03:48 1405
dr-xr-xr-x  8 kitamura kitamura          0  7月 24 04:03 2012
dr-xr-xr-x  8 kitamura kitamura          0  7月 24 04:03 2013
dr-xr-xr-x  8 mysql    mysql             0  7月 24 03:48 1139
dr-xr-xr-x  8 mysql    mysql             0  7月 24 03:48 965
dr-xr-xr-x  8 root     root              0  7月 24 01:54 1
-r--------  1 root     root              0  7月 24 01:54 kmsg
-r--r--r--  1 root     root              0  7月 24 01:54 swaps
dr-xr-xr-x  1 root     root              0  7月 24 01:54 sys
dr-xr-xr-x  8 root     root              0  7月 24 03:48 10
dr-xr-xr-x  8 root     root              0  7月 24 03:48 11
 :
 :
リンク先は参照できませんが、1151ホルダ(apache)等は参照できます。
[kitamura@localhost proc]$ ls 1151/
ls: シンボリックリンク 1151/cwd を読み込めません: 許可がありません
ls: シンボリックリンク 1151/root を読み込めません: 許可がありません
ls: シンボリックリンク 1151/exe を読み込めません: 許可がありません
attr        cmdline          environ  latency   mountinfo   oom_adj        root       stack    task
autogroup   comm             exe      limits    mounts      oom_score      sched      stat     wchan
auxv        coredump_filter  fd       loginuid  mountstats  oom_score_adj  schedstat  statm
cgroup      cpuset           fdinfo   maps      net         pagemap        sessionid  status
clear_refs  cwd              io       mem       ns          personality    smaps      syscall
hidepid=1でマウントすると、1151ホルダ(apache)等は表示されますが、その中は参照できません。
[root@localhost ~]# mount /proc -o remount,hidepid=1
[kitamura@localhost proc]$ ls -l | sort -k 3
合計 0
dr-xr-xr-x  8 apache   apache            0  7月 24 03:48 1151
dr-xr-xr-x  8 apache   apache            0  7月 24 03:48 1152
dr-xr-xr-x  8 apache   apache            0  7月 24 03:48 1153
dr-xr-xr-x  8 apache   apache            0  7月 24 03:48 1154
dr-xr-xr-x  8 apache   apache            0  7月 24 03:48 1155
dr-xr-xr-x  8 apache   apache            0  7月 24 03:48 1156
dr-xr-xr-x  8 apache   apache            0  7月 24 03:48 1157
dr-xr-xr-x  8 apache   apache            0  7月 24 03:48 1158
dr-xr-xr-x  8 avahi    avahi             0  7月 24 03:48 843
dr-xr-xr-x  8 avahi    avahi             0  7月 24 03:48 865
dr-xr-xr-x  8 dbus     dbus              0  7月 24 03:48 866
dr-xr-xr-x  8 kitamura kitamura          0  7月 24 03:48 1405
dr-xr-xr-x  8 kitamura kitamura          0  7月 24 04:03 2012
dr-xr-xr-x  8 kitamura kitamura          0  7月 24 04:03 2013
dr-xr-xr-x  8 mysql    mysql             0  7月 24 03:48 1139
dr-xr-xr-x  8 mysql    mysql             0  7月 24 03:48 965
dr-xr-xr-x  8 root     root              0  7月 24 01:54 1
-r--------  1 root     root              0  7月 24 01:54 kmsg
-r--r--r--  1 root     root              0  7月 24 01:54 swaps
dr-xr-xr-x  1 root     root              0  7月 24 01:54 sys
dr-xr-xr-x  8 root     root              0  7月 24 03:48 10
dr-xr-xr-x  8 root     root              0  7月 24 03:48 11
 :
 :
[kitamura@localhost proc]$ ls 1151/
ls: ディレクトリ 1151/ を開くことが出来ません: 許可されていない操作です
hidepid=2でマウントすると、proc下のkitamura以外のプロセスファイル自身が表示されません。
[root@localhost ~]# mount /proc -o remount,hidepid=2

[kitamura@localhost proc]$ ls -l | sort -k 3
合計 0
dr-xr-xr-x  8 kitamura kitamura          0  7月 24 04:07 1405
dr-xr-xr-x  8 kitamura kitamura          0  7月 24 04:07 2040
dr-xr-xr-x  8 kitamura kitamura          0  7月 24 04:07 2041
-r--------  1 root     root              0  7月 24 01:54 kmsg
-r--r--r--  1 root     root              0  7月 24 01:54 swaps
dr-xr-xr-x  1 root     root              0  7月 24 01:54 sys
dr-xr-xr-x  2 root     root              0  7月 24 04:07 acpi
dr-xr-xr-x  5 root     root              0  7月 24 04:07 asound
procfsのinode_operationsの.permissionコールバック関数proc_pid_permission()は、ディレクトリ参照コールされ、hidepidのチェックが行われます。has_pid_permissions()は第三引数の1より小さいパーミッションを有しているかどうのかチェックを行います。従って1より小さいと言うことで、hidepidが0のパーミッションを有しているかどうかのチェックとなります。

has_perms==FALSEと言うことは、hidepidは0のパーミッションを有していない。と言うことで、結果的にパーミッションを有しているということです。(まどろっこしい実装してます。)

で、pid->hide_pid == 1ならEPERM、pid->hide_pid == 2ならENOENTと言うことです。
#define EPERM            1      /* Operation not permitted */
#define ENOENT           2      /* No such file or directory */

static int proc_pid_permission(struct inode *inode, int mask)
{
       struct pid_namespace *pid = inode->i_sb->s_fs_info;
       struct task_struct *task;
       bool has_perms;

       task = get_proc_task(inode);
       if (!task)
               return -ESRCH;
       has_perms = has_pid_permissions(pid, task, 1);
       put_task_struct(task);

       if (!has_perms) {
               if (pid->hide_pid == 2) {
                       return -ENOENT;
               }

               return -EPERM;
       }
       return generic_permission(inode, mask);
}
file_operationsの.readdirコールバック関数のproc_pid_readdir()でprocfsディレクトリを取得します。最初のforループでproc_base_stuff[]のディレクトリをとりあえずfilldirに取得し、if (has_pid_permissions(ns, iter.task, 2))でhidepidが0,1の時は、ディレクトリをdirentに設定しています。
int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir)
{
       unsigned int nr;
       struct task_struct *reaper;
       struct tgid_iter iter;
       struct pid_namespace *ns;
       filldir_t __filldir;

       if (filp->f_pos >= PID_MAX_LIMIT + TGID_OFFSET)
               goto out_no_task;
       nr = filp->f_pos - FIRST_PROCESS_ENTRY;

       reaper = get_proc_task(filp->f_path.dentry->d_inode);
       if (!reaper)
               goto out_no_task;

       for (; nr < ARRAY_SIZE(proc_base_stuff); filp->f_pos++, nr++) {
               const struct pid_entry *p = &proc_base_stuff[nr];
               if (proc_base_fill_cache(filp, dirent, filldir, reaper, p) < 0)
                       goto out;
       }

       ns = filp->f_dentry->d_sb->s_fs_info;
       iter.task = NULL;
       iter.tgid = filp->f_pos - TGID_OFFSET;
       for (iter = next_tgid(ns, iter); iter.task; iter.tgid += 1, iter = next_tgid(ns, iter)) {
               if (has_pid_permissions(ns, iter.task, 2))
                       __filldir = filldir;
               else
                       __filldir = fake_filldir;

               filp->f_pos = iter.tgid + TGID_OFFSET;
               if (proc_pid_fill_cache(filp, dirent, __filldir, iter) < 0) {
                       put_task_struct(iter.task);
                       goto out;
               }
       }
       filp->f_pos = PID_MAX_LIMIT + TGID_OFFSET;
out:
       put_task_struct(reaper);
out_no_task:
       return 0;
}
has_pid_permissions()でpid->hide_pidがhide_pid_minより小さい場合、その権限までのペーミッションを有していると言うことです。もし有していないならpid->pid_gidにかかるチェック等を行った結果を返します。
static bool has_pid_permissions(struct pid_namespace *pid,
                                struct task_struct *task,
                                int hide_pid_min)
{
       if (pid->hide_pid < hide_pid_min)
               return true;
       if (in_group_p(pid->pid_gid))
               return true;
       return ptrace_may_access(task, PTRACE_MODE_READ);
}

proc_fs_typeのmountコールバック関数proc_mount()から、proc_parse_options()がコールされ、gid/hidepidオプションの設定を行います。
static struct file_system_type proc_fs_type = {
       .name           = "proc",
       .mount          = proc_mount,
       .kill_sb        = proc_kill_sb,
};

static const match_table_t tokens = {
       {Opt_hidepid, "hidepid=%u"},
       {Opt_gid, "gid=%u"},
       {Opt_err, NULL},
};

static int proc_parse_options(char *options, struct pid_namespace *pid)
{
       char *p;
       substring_t args[MAX_OPT_ARGS];
       int option;

       if (!options)
               return 1;

       while ((p = strsep(&options, ",")) != NULL) {
               int token;
               if (!*p)
                       continue;

               args[0].to = args[0].from = 0;
               token = match_token(p, tokens, args);
               switch (token) {
               case Opt_gid:
                       if (match_int(&args[0], &option))
                               return 0;
                       pid->pid_gid = option;
                       break;
               case Opt_hidepid:
                       if (match_int(&args[0], &option))
                               return 0;
                       if (option < 0 || option > 2) {
                               pr_err("proc: hidepid value must be between 0 and 2.\n");
                               return 0;
                       }
                       pid->hide_pid = option;
                       break;
               default:
                       pr_err("proc: unrecognized mount option \"%s\" "
                              "or missing value\n", p);
                       return 0;
               }
       }

       return 1;
}

最終更新 2013/07/24 14:36:30 - north
(2013/07/24 14:36:30 作成)


検索

アクセス数
3697965
最近のコメント
コアダンプファイル - sakaia
list_head構造体 - yocto_no_yomikata
勧告ロックと強制ロック - wataash
LKMからのファイル出力 - 重松 宏昌
kprobe - ななし
ksetの実装 - スーパーコピー
カーネルスレッドとは - ノース
カーネルスレッドとは - nbyst
asmlinkageってなに? - ノース
asmlinkageってなに? - よろしく
Adsense
広告情報が設定されていません。