sysctl: merge equal proc_sys_read and proc_sys_write
Many (most of) sysctls do not have a per-container sense. E.g. kernel.print_fatal_signals, vm.panic_on_oom, net.core.netdev_budget and so on and so forth. Besides, tuning then from inside a container is not even secure. On the other hand, hiding them completely from the container's tasks sometimes causes user-space to stop working. When developing net sysctl, the common practice was to duplicate a table and drop the write bits in table->mode, but this approach was not very elegant, lead to excessive memory consumption and was not suitable in general. Here's the alternative solution. To facilitate the per-container sysctls ctl_table_root-s were introduced. Each root contains a list of ctl_table_header-s that are visible to different namespaces. The idea of this set is to add the permissions() callback on the ctl_table_root to allow ctl root limit permissions to the same ctl_table-s. The main user of this functionality is the net-namespaces code, but later this will (should) be used by more and more namespaces, containers and control groups. Actually, this idea's core is in a single hunk in the third patch. First two patches are cleanups for sysctl code, while the third one mostly extends the arguments set of some sysctl functions. This patch: These ->read and ->write callbacks act in a very similar way, so merge these paths to reduce the number of places to patch later and shrink the .text size (a bit). Signed-off-by: Pavel Emelyanov <xemul@openvz.org> Acked-by: "David S. Miller" <davem@davemloft.net> Cc: "Eric W. Biederman" <ebiederm@xmission.com> Cc: Alexey Dobriyan <adobriyan@sw.ru> Cc: Denis V. Lunev <den@openvz.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
1a46674b99
commit
7708bfb1c8
|
@ -165,8 +165,8 @@ out:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t proc_sys_read(struct file *filp, char __user *buf,
|
static ssize_t proc_sys_call_handler(struct file *filp, void __user *buf,
|
||||||
size_t count, loff_t *ppos)
|
size_t count, loff_t *ppos, int write)
|
||||||
{
|
{
|
||||||
struct dentry *dentry = filp->f_dentry;
|
struct dentry *dentry = filp->f_dentry;
|
||||||
struct ctl_table_header *head;
|
struct ctl_table_header *head;
|
||||||
|
@ -190,12 +190,12 @@ static ssize_t proc_sys_read(struct file *filp, char __user *buf,
|
||||||
* and won't be until we finish.
|
* and won't be until we finish.
|
||||||
*/
|
*/
|
||||||
error = -EPERM;
|
error = -EPERM;
|
||||||
if (sysctl_perm(table, MAY_READ))
|
if (sysctl_perm(table, write ? MAY_WRITE : MAY_READ))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
/* careful: calling conventions are nasty here */
|
/* careful: calling conventions are nasty here */
|
||||||
res = count;
|
res = count;
|
||||||
error = table->proc_handler(table, 0, filp, buf, &res, ppos);
|
error = table->proc_handler(table, write, filp, buf, &res, ppos);
|
||||||
if (!error)
|
if (!error)
|
||||||
error = res;
|
error = res;
|
||||||
out:
|
out:
|
||||||
|
@ -204,44 +204,16 @@ out:
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ssize_t proc_sys_read(struct file *filp, char __user *buf,
|
||||||
|
size_t count, loff_t *ppos)
|
||||||
|
{
|
||||||
|
return proc_sys_call_handler(filp, (void __user *)buf, count, ppos, 0);
|
||||||
|
}
|
||||||
|
|
||||||
static ssize_t proc_sys_write(struct file *filp, const char __user *buf,
|
static ssize_t proc_sys_write(struct file *filp, const char __user *buf,
|
||||||
size_t count, loff_t *ppos)
|
size_t count, loff_t *ppos)
|
||||||
{
|
{
|
||||||
struct dentry *dentry = filp->f_dentry;
|
return proc_sys_call_handler(filp, (void __user *)buf, count, ppos, 1);
|
||||||
struct ctl_table_header *head;
|
|
||||||
struct ctl_table *table;
|
|
||||||
ssize_t error;
|
|
||||||
size_t res;
|
|
||||||
|
|
||||||
table = do_proc_sys_lookup(dentry->d_parent, &dentry->d_name, &head);
|
|
||||||
/* Has the sysctl entry disappeared on us? */
|
|
||||||
error = -ENOENT;
|
|
||||||
if (!table)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
/* Has the sysctl entry been replaced by a directory? */
|
|
||||||
error = -EISDIR;
|
|
||||||
if (!table->proc_handler)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* At this point we know that the sysctl was not unregistered
|
|
||||||
* and won't be until we finish.
|
|
||||||
*/
|
|
||||||
error = -EPERM;
|
|
||||||
if (sysctl_perm(table, MAY_WRITE))
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
/* careful: calling conventions are nasty here */
|
|
||||||
res = count;
|
|
||||||
error = table->proc_handler(table, 1, filp, (char __user *)buf,
|
|
||||||
&res, ppos);
|
|
||||||
if (!error)
|
|
||||||
error = res;
|
|
||||||
out:
|
|
||||||
sysctl_head_finish(head);
|
|
||||||
|
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue