From 0097875bd41528922fb3bb5f348c53f17e00e2fd Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Thu, 31 Jul 2014 03:10:50 -0700 Subject: proc: Implement /proc/thread-self to point at the directory of the current thread /proc/thread-self is derived from /proc/self. /proc/thread-self points to the directory in proc containing information about the current thread. This funtionality has been missing for a long time, and is tricky to implement in userspace as gettid() is not exported by glibc. More importantly this allows fixing defects in /proc/mounts and /proc/net where in a threaded application today they wind up being empty files when only the initial pthread has exited, causing problems for other threads. Signed-off-by: "Eric W. Biederman" --- fs/proc/root.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'fs/proc/root.c') diff --git a/fs/proc/root.c b/fs/proc/root.c index 5dbadecb234..48f1c03bc7e 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c @@ -149,6 +149,8 @@ static void proc_kill_sb(struct super_block *sb) ns = (struct pid_namespace *)sb->s_fs_info; if (ns->proc_self) dput(ns->proc_self); + if (ns->proc_thread_self) + dput(ns->proc_thread_self); kill_anon_super(sb); put_pid_ns(ns); } @@ -170,6 +172,7 @@ void __init proc_root_init(void) return; proc_self_init(); + proc_thread_self_init(); proc_symlink("mounts", NULL, "self/mounts"); proc_net_init(); -- cgit v1.2.3-70-g09d2 From 344470cac42e887e68cfb5bdfa6171baf27f1eb5 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Thu, 31 Jul 2014 15:41:15 -0700 Subject: proc: Point /proc/mounts at /proc/thread-self/mounts instead of /proc/self/mounts In oddball cases where the thread has a different mount namespace than the thread group leader or more likely in cases where the thread remains and the thread group leader has exited this ensures that /proc/mounts continues to work. This should not cause any problems but if it does this patch can just be reverted. Signed-off-by: "Eric W. Biederman" --- fs/proc/root.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/proc/root.c') diff --git a/fs/proc/root.c b/fs/proc/root.c index 48f1c03bc7e..92c12c243ce 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c @@ -173,7 +173,7 @@ void __init proc_root_init(void) proc_self_init(); proc_thread_self_init(); - proc_symlink("mounts", NULL, "self/mounts"); + proc_symlink("mounts", NULL, "thread-self/mounts"); proc_net_init(); -- cgit v1.2.3-70-g09d2 From 335eb53158466a4c4d018fa53ceb8c8ba1067fa3 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Fri, 8 Aug 2014 14:21:27 -0700 Subject: proc: faster /proc/$PID lookup Currently lookup for /proc/$PID first goes through spinlock and whole list of misc /proc entries only to confirm that, yes, /proc/42 can not possibly match random proc entry. List is is several dozens entries long (52 entries on my setup). None of this is necessary. Try to convert dentry name to integer first. If it works, it must be /proc/$PID. If it doesn't, it must be random proc entry. Based on patch from Al Viro. Signed-off-by: Alexey Dobriyan Cc: Al Viro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/proc/base.c | 2 +- fs/proc/root.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'fs/proc/root.c') diff --git a/fs/proc/base.c b/fs/proc/base.c index 11375216b49..35afb2eb4a6 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -2780,7 +2780,7 @@ out: struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, unsigned int flags) { - int result = 0; + int result = -ENOENT; struct task_struct *task; unsigned tgid; struct pid_namespace *ns; diff --git a/fs/proc/root.c b/fs/proc/root.c index 5dbadecb234..574bafc41f0 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c @@ -199,10 +199,10 @@ static int proc_root_getattr(struct vfsmount *mnt, struct dentry *dentry, struct static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentry, unsigned int flags) { - if (!proc_lookup(dir, dentry, flags)) + if (!proc_pid_lookup(dir, dentry, flags)) return NULL; - return proc_pid_lookup(dir, dentry, flags); + return proc_lookup(dir, dentry, flags); } static int proc_root_readdir(struct file *file, struct dir_context *ctx) -- cgit v1.2.3-70-g09d2 From 155134fef2b6c7426c3f25ffe84fb3043167c860 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 10 Aug 2014 21:24:59 -0700 Subject: Revert "proc: Point /proc/{mounts,net} at /proc/thread-self/{mounts,net} instead of /proc/self/{mounts,net}" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commits 344470cac42e and e81324407269. It turns out that the exact path in the symlink matters, if for somewhat unfortunate reasons: some apparmor configurations don't allow dhclient access to the per-thread /proc files. As reported by Jörg Otte: audit: type=1400 audit(1407684227.003:28): apparmor="DENIED" operation="open" profile="/sbin/dhclient" name="/proc/1540/task/1540/net/dev" pid=1540 comm="dhclient" requested_mask="r" denied_mask="r" fsuid=0 ouid=0 so we had better revert this for now. We might be able to work around this in practice by only using the per-thread symlinks if the thread isn't the thread group leader, and if the namespaces differ between threads (which basically never happens). We'll see. In the meantime, the revert was made to be intentionally easy. Reported-by: Jörg Otte Acked-by: Eric W. Biederman Signed-off-by: Linus Torvalds --- fs/proc/proc_net.c | 2 +- fs/proc/root.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'fs/proc/root.c') diff --git a/fs/proc/proc_net.c b/fs/proc/proc_net.c index 39481028ec0..a63af3e0a61 100644 --- a/fs/proc/proc_net.c +++ b/fs/proc/proc_net.c @@ -226,7 +226,7 @@ static struct pernet_operations __net_initdata proc_net_ns_ops = { int __init proc_net_init(void) { - proc_symlink("net", NULL, "thread-self/net"); + proc_symlink("net", NULL, "self/net"); return register_pernet_subsys(&proc_net_ns_ops); } diff --git a/fs/proc/root.c b/fs/proc/root.c index 6296c762696..094e44d4a6b 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c @@ -173,7 +173,7 @@ void __init proc_root_init(void) proc_self_init(); proc_thread_self_init(); - proc_symlink("mounts", NULL, "thread-self/mounts"); + proc_symlink("mounts", NULL, "self/mounts"); proc_net_init(); -- cgit v1.2.3-70-g09d2