Re: /proc/pid/fd && anon_inode_fops

From: Linus Torvalds
Date: Sun Aug 25 2013 - 14:51:33 EST


On Sat, Aug 24, 2013 at 11:50 PM, Willy Tarreau <w@xxxxxx> wrote:
>
> Thanks for explaining Al, that really helps me understand. However
> there's still a difference between /proc/pid called from the process
> itself (=/proc/self) and called from other processes that seems to
> suit the situation :

/proc/self has magic special properties, as you noticed.

> Thus I'm wondering if something like this could help, the idea would be
> that a with the appropriate mount option, a task could only look at its
> own descriptors unless it's running with privileges :

I'd much rather try to do it in general, and use "file->f_cred" more
aggressively for /proc/<pid>/fd/ security.

We don't use f_cred at all in /proc, but that's because /proc predates
that whole thing. So instead we use the credentials of the task when
we want to look at credentials of the file, because that was the
closest approximation we used to have.

Look at the code that creates the fd stat information, for example.
It's in tid_fd_revalidate(), and it really doesn't make much sense to
use the task credentials for it. I wonder if we should do something
like the appended (whitespace-damaged and totally untested) patch.

Linus

---
diff --git a/fs/proc/fd.c b/fs/proc/fd.c
index 75f2890abbd8..2a5a53cc7a0a 100644
--- a/fs/proc/fd.c
+++ b/fs/proc/fd.c
@@ -74,7 +74,6 @@ static int tid_fd_revalidate(struct dentry
*dentry, unsigned int flags)
{
struct files_struct *files;
struct task_struct *task;
- const struct cred *cred;
struct inode *inode;
int fd;

@@ -95,19 +94,17 @@ static int tid_fd_revalidate(struct dentry
*dentry, unsigned int flags)
if (file) {
unsigned f_mode = file->f_mode;

- rcu_read_unlock();
- put_files_struct(files);
-
if (task_dumpable(task)) {
- rcu_read_lock();
- cred = __task_cred(task);
+ const struct cred *cred =
file->f_cred;
inode->i_uid = cred->euid;
inode->i_gid = cred->egid;
- rcu_read_unlock();
} else {
inode->i_uid = GLOBAL_ROOT_UID;
inode->i_gid = GLOBAL_ROOT_GID;
}
+ rcu_read_unlock();
+ put_files_struct(files);
+

if (S_ISLNK(inode->i_mode)) {
unsigned i_mode = S_IFLNK;
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/