Re: /proc paranoia patch (1.2.13)

Ian Jackson (iwj10@cus.cam.ac.uk)
Thu, 28 Sep 95 03:07 BST


I wrote:
> I've been worried about security holes in the procfs - both real and
> potential - for some time. It seems, for example, sometimes to forget
> to change the ownerships of files like /proc/<pid>/fd when processes
> become undumpable (eg, by exec'ing setuid programs), and there have
> been reports of a security hole involving /proc/<pid>/mem and mmap.
>
> I therefore wrote the patch below. [...]

Unfortunately the patch was mangled - tabs were replaced by spaces,
and this section of the kernel code is full of tabs.

Here is another copy.

Ian.

diff -ru --exclude=*.o --exclude=.depend linux-1.2.13/fs/proc/base.c linux-1.2.13-procpar/fs/proc/base.c
--- linux-1.2.13/fs/proc/base.c Sat Oct 22 15:41:18 1994
+++ linux-1.2.13-procpar/fs/proc/base.c Wed Sep 27 21:35:29 1995
@@ -67,6 +67,13 @@

#define NR_BASE_DIRENTRY ((sizeof (base_dir))/(sizeof (base_dir[0])))

+int proc_paranoid(struct inode *i) {
+ if (i->i_sb->s_mounted->i_mode & S_ISVTX)
+ return 1;
+ else
+ return 0;
+}
+
int proc_match(int len,const char * name,struct proc_dir_entry * de)
{
if (!de || !de->low_ino)
diff -ru --exclude=*.o --exclude=.depend linux-1.2.13/fs/proc/inode.c linux-1.2.13-procpar/fs/proc/inode.c
--- linux-1.2.13/fs/proc/inode.c Tue Aug 1 11:06:57 1995
+++ linux-1.2.13-procpar/fs/proc/inode.c Thu Sep 28 01:52:26 1995
@@ -45,7 +45,7 @@
};


-static int parse_options(char *options,uid_t *uid,gid_t *gid)
+static int parse_options(char *options,uid_t *uid,gid_t *gid,mode_t *mode)
{
char *this_char,*value;

@@ -69,6 +69,11 @@
if (*value)
return 0;
}
+ else if (!strcmp(this_char,"paranoid")) {
+ if (value)
+ return 0;
+ *mode |= S_ISVTX; /* sticky bit represents paranoia */
+ }
else return 0;
}
return 1;
@@ -89,7 +94,8 @@
printk("get root inode failed\n");
return NULL;
}
- parse_options(data, &s->s_mounted->i_uid, &s->s_mounted->i_gid);
+ parse_options(data, &s->s_mounted->i_uid, &s->s_mounted->i_gid,
+ &s->s_mounted->i_mode);
return s;
}

@@ -206,22 +212,34 @@
return;
case PROC_PID_MEM:
inode->i_op = &proc_mem_inode_operations;
- inode->i_mode = S_IFREG | S_IRUSR | S_IWUSR;
+ if (proc_paranoid(inode))
+ inode->i_mode = S_IFREG;
+ else
+ inode->i_mode = S_IFREG | S_IRUSR | S_IWUSR;
return;
case PROC_PID_CWD:
case PROC_PID_ROOT:
case PROC_PID_EXE:
inode->i_op = &proc_link_inode_operations;
inode->i_size = 64;
- inode->i_mode = S_IFLNK | S_IRWXU;
+ if (proc_paranoid(inode))
+ inode->i_mode = S_IFLNK;
+ else
+ inode->i_mode = S_IFLNK | S_IRWXU;
return;
case PROC_PID_FD:
- inode->i_mode = S_IFDIR | S_IRUSR | S_IXUSR;
+ if (proc_paranoid(inode))
+ inode->i_mode = S_IFDIR;
+ else
+ inode->i_mode = S_IFDIR | S_IRUSR | S_IXUSR;
inode->i_op = &proc_fd_inode_operations;
inode->i_nlink = 2;
return;
case PROC_PID_ENVIRON:
- inode->i_mode = S_IFREG | S_IRUSR;
+ if (proc_paranoid(inode))
+ inode->i_mode = S_IFREG;
+ else
+ inode->i_mode = S_IFREG | S_IRUSR;
inode->i_op = &proc_array_inode_operations;
return;
case PROC_PID_CMDLINE:
@@ -243,10 +261,12 @@
inode->i_op = &proc_link_inode_operations;
inode->i_size = 64;
inode->i_mode = S_IFLNK;
- if (p->files->fd[ino]->f_mode & 1)
- inode->i_mode |= S_IRUSR | S_IXUSR;
- if (p->files->fd[ino]->f_mode & 2)
- inode->i_mode |= S_IWUSR | S_IXUSR;
+ if (!proc_paranoid(inode)) {
+ if (p->files->fd[ino]->f_mode & 1)
+ inode->i_mode |= S_IRUSR | S_IXUSR;
+ if (p->files->fd[ino]->f_mode & 2)
+ inode->i_mode |= S_IWUSR | S_IXUSR;
+ }
return;
}
return;
diff -ru --exclude=*.o --exclude=.depend linux-1.2.13/fs/proc/link.c linux-1.2.13-procpar/fs/proc/link.c
--- linux-1.2.13/fs/proc/link.c Mon Jan 23 21:04:10 1995
+++ linux-1.2.13-procpar/fs/proc/link.c Wed Sep 27 20:29:52 1995
@@ -76,6 +76,10 @@
if (fd>=NR_OPEN)
return -ENOENT; /* should never happen */

+ if (proc_paranoid(inode) && !suser()) {
+ return -EPERM;
+ }
+
ino = inode->i_ino;
pid = ino >> 16;
ino &= 0x0000ffff;
diff -ru --exclude=*.o --exclude=.depend linux-1.2.13/include/linux/proc_fs.h linux-1.2.13-procpar/include/linux/proc_fs.h
--- linux-1.2.13/include/linux/proc_fs.h Sun Feb 12 19:11:02 1995
+++ linux-1.2.13-procpar/include/linux/proc_fs.h Wed Sep 27 21:35:29 1995
@@ -129,4 +129,6 @@
extern struct inode_operations proc_link_inode_operations;
extern struct inode_operations proc_fd_inode_operations;

+extern int proc_paranoid(struct inode *i);
+
#endif