diff options
-rw-r--r-- | ipc/ipc_sysctl.c | 43 |
1 files 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, | |||
35 | return proc_dointvec(&ipc_table, write, filp, buffer, lenp, ppos); | 35 | return proc_dointvec(&ipc_table, write, filp, buffer, lenp, ppos); |
36 | } | 36 | } |
37 | 37 | ||
38 | static int proc_ipc_callback_dointvec(ctl_table *table, int write, | ||
39 | struct file *filp, void __user *buffer, size_t *lenp, loff_t *ppos) | ||
40 | { | ||
41 | size_t lenp_bef = *lenp; | ||
42 | int rc; | ||
43 | |||
44 | rc = proc_ipc_dointvec(table, write, filp, buffer, lenp, ppos); | ||
45 | |||
46 | if (write && !rc && lenp_bef == *lenp) | ||
47 | /* | ||
48 | * Tunable has successfully been changed from userland: | ||
49 | * disable its automatic recomputing. | ||
50 | */ | ||
51 | unregister_ipcns_notifier(current->nsproxy->ipc_ns); | ||
52 | |||
53 | return rc; | ||
54 | } | ||
55 | |||
38 | static int proc_ipc_doulongvec_minmax(ctl_table *table, int write, | 56 | static int proc_ipc_doulongvec_minmax(ctl_table *table, int write, |
39 | struct file *filp, void __user *buffer, size_t *lenp, loff_t *ppos) | 57 | struct file *filp, void __user *buffer, size_t *lenp, loff_t *ppos) |
40 | { | 58 | { |
@@ -49,6 +67,7 @@ static int proc_ipc_doulongvec_minmax(ctl_table *table, int write, | |||
49 | #else | 67 | #else |
50 | #define proc_ipc_doulongvec_minmax NULL | 68 | #define proc_ipc_doulongvec_minmax NULL |
51 | #define proc_ipc_dointvec NULL | 69 | #define proc_ipc_dointvec NULL |
70 | #define proc_ipc_callback_dointvec NULL | ||
52 | #endif | 71 | #endif |
53 | 72 | ||
54 | #ifdef CONFIG_SYSCTL_SYSCALL | 73 | #ifdef CONFIG_SYSCTL_SYSCALL |
@@ -90,8 +109,28 @@ static int sysctl_ipc_data(ctl_table *table, int __user *name, int nlen, | |||
90 | } | 109 | } |
91 | return 1; | 110 | return 1; |
92 | } | 111 | } |
112 | |||
113 | static int sysctl_ipc_registered_data(ctl_table *table, int __user *name, | ||
114 | int nlen, void __user *oldval, size_t __user *oldlenp, | ||
115 | void __user *newval, size_t newlen) | ||
116 | { | ||
117 | int rc; | ||
118 | |||
119 | rc = sysctl_ipc_data(table, name, nlen, oldval, oldlenp, newval, | ||
120 | newlen); | ||
121 | |||
122 | if (newval && newlen && rc > 0) | ||
123 | /* | ||
124 | * Tunable has successfully been changed from userland: | ||
125 | * disable its automatic recomputing. | ||
126 | */ | ||
127 | unregister_ipcns_notifier(current->nsproxy->ipc_ns); | ||
128 | |||
129 | return rc; | ||
130 | } | ||
93 | #else | 131 | #else |
94 | #define sysctl_ipc_data NULL | 132 | #define sysctl_ipc_data NULL |
133 | #define sysctl_ipc_registered_data NULL | ||
95 | #endif | 134 | #endif |
96 | 135 | ||
97 | static struct ctl_table ipc_kern_table[] = { | 136 | static struct ctl_table ipc_kern_table[] = { |
@@ -137,8 +176,8 @@ static struct ctl_table ipc_kern_table[] = { | |||
137 | .data = &init_ipc_ns.msg_ctlmni, | 176 | .data = &init_ipc_ns.msg_ctlmni, |
138 | .maxlen = sizeof (init_ipc_ns.msg_ctlmni), | 177 | .maxlen = sizeof (init_ipc_ns.msg_ctlmni), |
139 | .mode = 0644, | 178 | .mode = 0644, |
140 | .proc_handler = proc_ipc_dointvec, | 179 | .proc_handler = proc_ipc_callback_dointvec, |
141 | .strategy = sysctl_ipc_data, | 180 | .strategy = sysctl_ipc_registered_data, |
142 | }, | 181 | }, |
143 | { | 182 | { |
144 | .ctl_name = KERN_MSGMNB, | 183 | .ctl_name = KERN_MSGMNB, |