From 91cfb2b4b57816de0c96de417b3238249f0b125f Mon Sep 17 00:00:00 2001 From: Nadia Derbey Date: Tue, 29 Apr 2008 01:00:44 -0700 Subject: ipc: do not recompute msgmni anymore if explicitly set by user Make msgmni not recomputed anymore upon ipc namespace creation / removal or memory add/remove, as soon as it has been set from userland. As soon as msgmni is explicitly set via procfs or sysctl(), the associated callback routine is unregistered from the ipc namespace notifier chain. Signed-off-by: Nadia Derbey Cc: Yasunori Goto Cc: Matt Helsley Cc: Mingming Cao Cc: Pierre Peiffer Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- ipc/ipc_sysctl.c | 43 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/ipc/ipc_sysctl.c b/ipc/ipc_sysctl.c index 7f4235bed51b..d12ff5cd2a0b 100644 --- a/ipc/ipc_sysctl.c +++ b/ipc/ipc_sysctl.c @@ -35,6 +35,24 @@ static int proc_ipc_dointvec(ctl_table *table, int write, struct file *filp, return proc_dointvec(&ipc_table, write, filp, buffer, lenp, ppos); } +static int proc_ipc_callback_dointvec(ctl_table *table, int write, + struct file *filp, void __user *buffer, size_t *lenp, loff_t *ppos) +{ + size_t lenp_bef = *lenp; + int rc; + + rc = proc_ipc_dointvec(table, write, filp, buffer, lenp, ppos); + + if (write && !rc && lenp_bef == *lenp) + /* + * Tunable has successfully been changed from userland: + * disable its automatic recomputing. + */ + unregister_ipcns_notifier(current->nsproxy->ipc_ns); + + return rc; +} + static int proc_ipc_doulongvec_minmax(ctl_table *table, int write, struct file *filp, void __user *buffer, size_t *lenp, loff_t *ppos) { @@ -49,6 +67,7 @@ static int proc_ipc_doulongvec_minmax(ctl_table *table, int write, #else #define proc_ipc_doulongvec_minmax NULL #define proc_ipc_dointvec NULL +#define proc_ipc_callback_dointvec NULL #endif #ifdef CONFIG_SYSCTL_SYSCALL @@ -90,8 +109,28 @@ static int sysctl_ipc_data(ctl_table *table, int __user *name, int nlen, } return 1; } + +static int sysctl_ipc_registered_data(ctl_table *table, int __user *name, + int nlen, void __user *oldval, size_t __user *oldlenp, + void __user *newval, size_t newlen) +{ + int rc; + + rc = sysctl_ipc_data(table, name, nlen, oldval, oldlenp, newval, + newlen); + + if (newval && newlen && rc > 0) + /* + * Tunable has successfully been changed from userland: + * disable its automatic recomputing. + */ + unregister_ipcns_notifier(current->nsproxy->ipc_ns); + + return rc; +} #else #define sysctl_ipc_data NULL +#define sysctl_ipc_registered_data NULL #endif static struct ctl_table ipc_kern_table[] = { @@ -137,8 +176,8 @@ static struct ctl_table ipc_kern_table[] = { .data = &init_ipc_ns.msg_ctlmni, .maxlen = sizeof (init_ipc_ns.msg_ctlmni), .mode = 0644, - .proc_handler = proc_ipc_dointvec, - .strategy = sysctl_ipc_data, + .proc_handler = proc_ipc_callback_dointvec, + .strategy = sysctl_ipc_registered_data, }, { .ctl_name = KERN_MSGMNB, -- cgit v1.2.3