|
@@ -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);
|
|
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,
|
|
static int proc_ipc_doulongvec_minmax(ctl_table *table, int write,
|
|
struct file *filp, void __user *buffer, size_t *lenp, loff_t *ppos)
|
|
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
|
|
#else
|
|
#define proc_ipc_doulongvec_minmax NULL
|
|
#define proc_ipc_doulongvec_minmax NULL
|
|
#define proc_ipc_dointvec NULL
|
|
#define proc_ipc_dointvec NULL
|
|
|
|
+#define proc_ipc_callback_dointvec NULL
|
|
#endif
|
|
#endif
|
|
|
|
|
|
#ifdef CONFIG_SYSCTL_SYSCALL
|
|
#ifdef CONFIG_SYSCTL_SYSCALL
|
|
@@ -90,8 +109,28 @@ static int sysctl_ipc_data(ctl_table *table, int __user *name, int nlen,
|
|
}
|
|
}
|
|
return 1;
|
|
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
|
|
#else
|
|
#define sysctl_ipc_data NULL
|
|
#define sysctl_ipc_data NULL
|
|
|
|
+#define sysctl_ipc_registered_data NULL
|
|
#endif
|
|
#endif
|
|
|
|
|
|
static struct ctl_table ipc_kern_table[] = {
|
|
static struct ctl_table ipc_kern_table[] = {
|
|
@@ -137,8 +176,8 @@ static struct ctl_table ipc_kern_table[] = {
|
|
.data = &init_ipc_ns.msg_ctlmni,
|
|
.data = &init_ipc_ns.msg_ctlmni,
|
|
.maxlen = sizeof (init_ipc_ns.msg_ctlmni),
|
|
.maxlen = sizeof (init_ipc_ns.msg_ctlmni),
|
|
.mode = 0644,
|
|
.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,
|
|
.ctl_name = KERN_MSGMNB,
|