summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorAndrew Morton <akpm@osdl.org>2003-10-01 10:58:24 -0700
committerLinus Torvalds <torvalds@home.osdl.org>2003-10-01 10:58:24 -0700
commitdc5f46be739c2290275f0034a3ed53312cc17843 (patch)
tree296a1fc6d07e8acaac8c61f2cc20d3985754dbc9 /kernel
parent206a70f22b5fc94e58a7e75f1d4bce1215c24ad7 (diff)
[PATCH] check permission in ->open for /proc/sys/
From: Christoph Hellwig <hch@lst.de> It's the only abuse of proc_iops left (except the totally b0rked comx driver). The patch is from Al, I just forward-ported it from 2.4. Background: struct proc_dir_entry has a struct inode_operations *proc_iops member, it's from Linux's stoneage and used internally by procfs to assign either the link or directory inode ops. Unfortunately some drivers started to abuse it do do bad things like create on lookup (that's the comx thingy which relies on unexported symbols and thus is broken for modular builds since mid-2.3) or various ->permission tricks (all gone by now). After this patch is gone I have another one that kills proc_iops and just uses a normal conditional inside procfs to assign the right one directly.
Diffstat (limited to 'kernel')
-rw-r--r--kernel/sysctl.c30
1 files changed, 17 insertions, 13 deletions
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 678bbd6f0d69..126da64b9c3b 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -137,17 +137,14 @@ extern ctl_table random_table[];
static ssize_t proc_readsys(struct file *, char __user *, size_t, loff_t *);
static ssize_t proc_writesys(struct file *, const char __user *, size_t, loff_t *);
-static int proc_sys_permission(struct inode *, int, struct nameidata *);
+static int proc_opensys(struct inode *, struct file *);
struct file_operations proc_sys_file_operations = {
+ .open = proc_opensys,
.read = proc_readsys,
.write = proc_writesys,
};
-static struct inode_operations proc_sys_inode_operations = {
- .permission = proc_sys_permission,
-};
-
extern struct proc_dir_entry *proc_sys_root;
static void register_proc_table(ctl_table *, struct proc_dir_entry *);
@@ -1141,10 +1138,8 @@ static void register_proc_table(ctl_table * table, struct proc_dir_entry *root)
if (!de)
continue;
de->data = (void *) table;
- if (table->proc_handler) {
+ if (table->proc_handler)
de->proc_fops = &proc_sys_file_operations;
- de->proc_iops = &proc_sys_inode_operations;
- }
}
table->de = de;
if (de->mode & S_IFDIR)
@@ -1213,6 +1208,20 @@ static ssize_t do_rw_proc(int write, struct file * file, char __user * buf,
return res;
}
+static int proc_opensys(struct inode *inode, struct file *file)
+{
+ if (file->f_mode & FMODE_WRITE) {
+ /*
+ * sysctl entries that are not writable,
+ * are _NOT_ writable, capabilities or not.
+ */
+ if (!(inode->i_mode & S_IWUSR))
+ return -EPERM;
+ }
+
+ return 0;
+}
+
static ssize_t proc_readsys(struct file * file, char __user * buf,
size_t count, loff_t *ppos)
{
@@ -1225,11 +1234,6 @@ static ssize_t proc_writesys(struct file * file, const char __user * buf,
return do_rw_proc(1, file, (char __user *) buf, count, ppos);
}
-static int proc_sys_permission(struct inode *inode, int op, struct nameidata *nd)
-{
- return test_perm(inode->i_mode, op);
-}
-
/**
* proc_dostring - read a string sysctl
* @table: the sysctl table