Re: /proc and chroot, again

Patrick Schaaf (phbof@bof.de)
Fri, 25 Jun 1999 22:57:33 +0200 (MEST)


s/works/looks_better/

> inspired by the recent discussion on chroot and /proc, I made the appended
> patch to 2.3.8.

Patch against 2.3.8. As far as I can see, it should also work for 2.2.x.

--- linux-2.3.8/fs/proc/base.c Sat Jun 19 20:45:28 1999
+++ linux-2.3.8-bof/fs/proc/base.c Fri Jun 25 12:18:40 1999
@@ -50,7 +50,7 @@
NULL, /* writepage */
NULL, /* flushpage */
NULL, /* truncate */
- NULL, /* permission */
+ proc_permission, /* permission */
NULL, /* smap */
NULL /* revalidate */
};
--- linux-2.3.8/fs/proc/root.c Sat Jun 19 20:45:29 1999
+++ linux-2.3.8-bof/fs/proc/root.c Fri Jun 25 22:03:45 1999
@@ -945,6 +945,8 @@
#define PROC_NUMBUF 10
#define PROC_MAXPIDS 20

+extern int proc_down_under(struct task_struct *);
+
/*
* Get a few pid's to return for filldir - we need to hold the
* tasklist lock while doing this, and we must release it before
@@ -960,6 +962,8 @@
for_each_task(p) {
int pid = p->pid;
if (!pid)
+ continue;
+ if (0 != proc_down_under(p))
continue;
if (--index >= 0)
continue;
--- linux-2.3.8/fs/proc/inode.c Tue Jun 8 19:47:58 1999
+++ linux-2.3.8-bof/fs/proc/inode.c Fri Jun 25 22:21:02 1999
@@ -175,65 +175,44 @@
*
* Jeremy Fitzhardinge <jeremy@zip.com.au>
*/
-int proc_permission(struct inode *inode, int mask)
-{
- struct task_struct *p;
- unsigned long ino = inode->i_ino;
- unsigned long pid;
- struct dentry *de, *base;
-
- if (standard_permission(inode, mask) != 0)
- return -EACCES;
-
- /*
- * Find the root of the processes being examined (if any).
- * XXX Surely there's a better way of doing this?
- */
- if (ino >= PROC_OPENPROM_FIRST &&
- ino < PROC_OPENPROM_FIRST + PROC_NOPENPROM)
- return 0; /* already allowed */
-
- pid = ino >> 16;
- if (pid == 0)
- return 0; /* already allowed */
-
- de = NULL;
- base = current->fs->root;

- read_lock(&tasklist_lock);
- p = find_task_by_pid(pid);
+/* callers do read_lock(&tasklist_lock) - sufficient? */
+int proc_down_under(struct task_struct *p)
+{
+ struct dentry *base = current->fs ? current->fs->root : NULL;
+ struct dentry *de = (p && p->fs) ? p->fs->root : NULL;

- if (p && p->fs)
- de = p->fs->root;
- read_unlock(&tasklist_lock); /* FIXME! */
-
- if (p == NULL)
- return -EACCES; /* ENOENT? */
-
- if (de == NULL)
- {
- /* kswapd and bdflush don't have proper root or cwd... */
- return -EACCES;
- }
-
- /* XXX locking? */
- for(;;)
- {
+ if (base && de) for(;;) {
struct dentry *parent;
-
if (de == base)
- return 0; /* already allowed */
-
+ return 0;
de = de->d_covers;
parent = de->d_parent;
-
if (de == parent)
break;
-
de = parent;
}
+ return -ENOENT;
+}
+
+int proc_permission(struct inode *inode, int mask)
+{
+ unsigned long ino = inode->i_ino;
+ unsigned long pid = ino >> 16;
+ int res;
+
+ if (standard_permission(inode, mask) != 0) return -EACCES;
+
+ /* allow everything except /proc/<pid>/ */
+ if ((ino>=PROC_OPENPROM_FIRST&&ino<PROC_OPENPROM_FIRST+PROC_NOPENPROM)
+ ||(pid==0))
+ return 0;
+
+ read_lock(&tasklist_lock);
+ res = proc_down_under(find_task_by_pid(pid));
+ read_unlock(&tasklist_lock); /* FIXME!? */

- return -EACCES; /* incompatible roots */
+ return res;
}

struct inode * proc_get_inode(struct super_block * sb, int ino,

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/