web-dev-qa-db-ja.com

ユーザーがrootでない場合、hidepid = 2を使用すると、実行権限のみを持つバイナリのプロセスが「ps」で非表示のままになるのはなぜですか?

私はhidepid = 2を使用して/ procをマウントしているので、ユーザーは自分のプロセスしか見ることができません。使用したい特定のバイナリはrwx--x--x権限に制限されているため、その所有者(root)のみが読み取ることができ、他のユーザーは実行できます。通常のユーザーは問題なく実行できますが、「ps」でプロセスを表示することはできません。ユーザーが読み取れるようにバイナリの権限が変更されている場合、プロセスは再び「ps」に表示されます。

再現可能な例:

Sudo mount -o remount,hidepid=2 /proc
Sudo cp $(which yes) /tmp
Sudo chmod 0711 /tmp/yes
/tmp/yes >/dev/null &
ps aux | grep yes # The process is hidden
Sudo ps aux | grep yes # The process can be seen by root
kill %1
Sudo chmod og+r /tmp/yes
/tmp/yes >/dev/null &
ps aux | grep yes # The process appears in the list

なんでこんなことが起こっているの?明らかにファイルのアクセス許可と何らかの関係がありますが、そうすべきではありません。プロセスがユーザーに属している場合、バイナリが制限されている場合でも、ユーザーはそれを表示できるはずです。

私の推測では、/ proc/PID内のリンク「exe」は実行中のバイナリを指しているため、カーネルはバイナリ自体に加えてディレクトリへのすべてのアクセスを禁止しています。しかし、これが本当なのか、それとも他のことが起こった結果なのかを知りたいのです。

前もって感謝します!

4
rsuarez

答えは(または少なくともstarts)in _fs/proc/base.c_ (少なくともカーネル3.12から4.2に変更なし)

_742 static int proc_pid_permission(struct inode *inode, int mask)
743 {
744         struct pid_namespace *pid = inode->i_sb->s_fs_info;
745         struct task_struct *task;
746         bool has_perms;
747 
748         task = get_proc_task(inode);
749         if (!task)
750                 return -ESRCH;
751         has_perms = has_pid_permissions(pid, task, 1);
752         put_task_struct(task);
753 
754         if (!has_perms) {
755                 if (pid->hide_pid == 2) {
756                         /*
757                          * Let's make getdents(), stat(), and open()
758                          * consistent with each other.  If a process
759                          * may not stat() a file, it shouldn't be    seen
760                          * in procfs at all.
761                          */
762                         return -ENOENT;
763                 }
764 
765                 return -EPERM;
766         }
767         return generic_permission(inode, mask);
768 }
_

上記のコードは、特定の_/proc/PID_エントリが存在するかどうかを判断するための開始点です。 _hide_pid_が2に設定されている場合、必要な権限がない場合は_-ENOENT_を返します。権限は次の方法でチェックされます。

has_pid_permissions()ptrace_may_access()__ptrace_may_access()

__ptrace_may_access()は、プロセスの作成中に決定された読み取り不可能な実行可能イメージから作成されたため、プロセスが「ダンプ可能」ではないため、アクセスを拒否します。

setup_new_exec()would_dump()

_1118 void would_dump(struct linux_binprm *bprm, struct file *file)
1119 {
1120         if (inode_permission(file_inode(file), MAY_READ) < 0)
1121                 bprm->interp_flags |= BINPRM_FLAGS_ENFORCE_NONDUMP;
1122 }
_
4
mr.spuratic