Merge tag 'trace-v5.2-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt...
[sfrench/cifs-2.6.git] / ipc / ipc_sysctl.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  *  Copyright (C) 2007
4  *
5  *  Author: Eric Biederman <ebiederm@xmision.com>
6  */
7
8 #include <linux/module.h>
9 #include <linux/ipc.h>
10 #include <linux/nsproxy.h>
11 #include <linux/sysctl.h>
12 #include <linux/uaccess.h>
13 #include <linux/ipc_namespace.h>
14 #include <linux/msg.h>
15 #include "util.h"
16
17 static void *get_ipc(struct ctl_table *table)
18 {
19         char *which = table->data;
20         struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns;
21         which = (which - (char *)&init_ipc_ns) + (char *)ipc_ns;
22         return which;
23 }
24
25 #ifdef CONFIG_PROC_SYSCTL
26 static int proc_ipc_dointvec(struct ctl_table *table, int write,
27         void __user *buffer, size_t *lenp, loff_t *ppos)
28 {
29         struct ctl_table ipc_table;
30
31         memcpy(&ipc_table, table, sizeof(ipc_table));
32         ipc_table.data = get_ipc(table);
33
34         return proc_dointvec(&ipc_table, write, buffer, lenp, ppos);
35 }
36
37 static int proc_ipc_dointvec_minmax(struct ctl_table *table, int write,
38         void __user *buffer, size_t *lenp, loff_t *ppos)
39 {
40         struct ctl_table ipc_table;
41
42         memcpy(&ipc_table, table, sizeof(ipc_table));
43         ipc_table.data = get_ipc(table);
44
45         return proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos);
46 }
47
48 static int proc_ipc_dointvec_minmax_orphans(struct ctl_table *table, int write,
49         void __user *buffer, size_t *lenp, loff_t *ppos)
50 {
51         struct ipc_namespace *ns = current->nsproxy->ipc_ns;
52         int err = proc_ipc_dointvec_minmax(table, write, buffer, lenp, ppos);
53
54         if (err < 0)
55                 return err;
56         if (ns->shm_rmid_forced)
57                 shm_destroy_orphaned(ns);
58         return err;
59 }
60
61 static int proc_ipc_doulongvec_minmax(struct ctl_table *table, int write,
62         void __user *buffer, size_t *lenp, loff_t *ppos)
63 {
64         struct ctl_table ipc_table;
65         memcpy(&ipc_table, table, sizeof(ipc_table));
66         ipc_table.data = get_ipc(table);
67
68         return proc_doulongvec_minmax(&ipc_table, write, buffer,
69                                         lenp, ppos);
70 }
71
72 static int proc_ipc_auto_msgmni(struct ctl_table *table, int write,
73         void __user *buffer, size_t *lenp, loff_t *ppos)
74 {
75         struct ctl_table ipc_table;
76         int dummy = 0;
77
78         memcpy(&ipc_table, table, sizeof(ipc_table));
79         ipc_table.data = &dummy;
80
81         if (write)
82                 pr_info_once("writing to auto_msgmni has no effect");
83
84         return proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos);
85 }
86
87 static int proc_ipc_sem_dointvec(struct ctl_table *table, int write,
88         void __user *buffer, size_t *lenp, loff_t *ppos)
89 {
90         int ret, semmni;
91         struct ipc_namespace *ns = current->nsproxy->ipc_ns;
92
93         semmni = ns->sem_ctls[3];
94         ret = proc_ipc_dointvec(table, write, buffer, lenp, ppos);
95
96         if (!ret)
97                 ret = sem_check_semmni(current->nsproxy->ipc_ns);
98
99         /*
100          * Reset the semmni value if an error happens.
101          */
102         if (ret)
103                 ns->sem_ctls[3] = semmni;
104         return ret;
105 }
106
107 #else
108 #define proc_ipc_doulongvec_minmax NULL
109 #define proc_ipc_dointvec          NULL
110 #define proc_ipc_dointvec_minmax   NULL
111 #define proc_ipc_dointvec_minmax_orphans   NULL
112 #define proc_ipc_auto_msgmni       NULL
113 #define proc_ipc_sem_dointvec      NULL
114 #endif
115
116 static int zero;
117 static int one = 1;
118 static int int_max = INT_MAX;
119 int ipc_mni = IPCMNI;
120 int ipc_mni_shift = IPCMNI_SHIFT;
121 int ipc_min_cycle = RADIX_TREE_MAP_SIZE;
122
123 static struct ctl_table ipc_kern_table[] = {
124         {
125                 .procname       = "shmmax",
126                 .data           = &init_ipc_ns.shm_ctlmax,
127                 .maxlen         = sizeof(init_ipc_ns.shm_ctlmax),
128                 .mode           = 0644,
129                 .proc_handler   = proc_ipc_doulongvec_minmax,
130         },
131         {
132                 .procname       = "shmall",
133                 .data           = &init_ipc_ns.shm_ctlall,
134                 .maxlen         = sizeof(init_ipc_ns.shm_ctlall),
135                 .mode           = 0644,
136                 .proc_handler   = proc_ipc_doulongvec_minmax,
137         },
138         {
139                 .procname       = "shmmni",
140                 .data           = &init_ipc_ns.shm_ctlmni,
141                 .maxlen         = sizeof(init_ipc_ns.shm_ctlmni),
142                 .mode           = 0644,
143                 .proc_handler   = proc_ipc_dointvec_minmax,
144                 .extra1         = &zero,
145                 .extra2         = &ipc_mni,
146         },
147         {
148                 .procname       = "shm_rmid_forced",
149                 .data           = &init_ipc_ns.shm_rmid_forced,
150                 .maxlen         = sizeof(init_ipc_ns.shm_rmid_forced),
151                 .mode           = 0644,
152                 .proc_handler   = proc_ipc_dointvec_minmax_orphans,
153                 .extra1         = &zero,
154                 .extra2         = &one,
155         },
156         {
157                 .procname       = "msgmax",
158                 .data           = &init_ipc_ns.msg_ctlmax,
159                 .maxlen         = sizeof(init_ipc_ns.msg_ctlmax),
160                 .mode           = 0644,
161                 .proc_handler   = proc_ipc_dointvec_minmax,
162                 .extra1         = &zero,
163                 .extra2         = &int_max,
164         },
165         {
166                 .procname       = "msgmni",
167                 .data           = &init_ipc_ns.msg_ctlmni,
168                 .maxlen         = sizeof(init_ipc_ns.msg_ctlmni),
169                 .mode           = 0644,
170                 .proc_handler   = proc_ipc_dointvec_minmax,
171                 .extra1         = &zero,
172                 .extra2         = &ipc_mni,
173         },
174         {
175                 .procname       = "auto_msgmni",
176                 .data           = NULL,
177                 .maxlen         = sizeof(int),
178                 .mode           = 0644,
179                 .proc_handler   = proc_ipc_auto_msgmni,
180                 .extra1         = &zero,
181                 .extra2         = &one,
182         },
183         {
184                 .procname       =  "msgmnb",
185                 .data           = &init_ipc_ns.msg_ctlmnb,
186                 .maxlen         = sizeof(init_ipc_ns.msg_ctlmnb),
187                 .mode           = 0644,
188                 .proc_handler   = proc_ipc_dointvec_minmax,
189                 .extra1         = &zero,
190                 .extra2         = &int_max,
191         },
192         {
193                 .procname       = "sem",
194                 .data           = &init_ipc_ns.sem_ctls,
195                 .maxlen         = 4*sizeof(int),
196                 .mode           = 0644,
197                 .proc_handler   = proc_ipc_sem_dointvec,
198         },
199 #ifdef CONFIG_CHECKPOINT_RESTORE
200         {
201                 .procname       = "sem_next_id",
202                 .data           = &init_ipc_ns.ids[IPC_SEM_IDS].next_id,
203                 .maxlen         = sizeof(init_ipc_ns.ids[IPC_SEM_IDS].next_id),
204                 .mode           = 0644,
205                 .proc_handler   = proc_ipc_dointvec_minmax,
206                 .extra1         = &zero,
207                 .extra2         = &int_max,
208         },
209         {
210                 .procname       = "msg_next_id",
211                 .data           = &init_ipc_ns.ids[IPC_MSG_IDS].next_id,
212                 .maxlen         = sizeof(init_ipc_ns.ids[IPC_MSG_IDS].next_id),
213                 .mode           = 0644,
214                 .proc_handler   = proc_ipc_dointvec_minmax,
215                 .extra1         = &zero,
216                 .extra2         = &int_max,
217         },
218         {
219                 .procname       = "shm_next_id",
220                 .data           = &init_ipc_ns.ids[IPC_SHM_IDS].next_id,
221                 .maxlen         = sizeof(init_ipc_ns.ids[IPC_SHM_IDS].next_id),
222                 .mode           = 0644,
223                 .proc_handler   = proc_ipc_dointvec_minmax,
224                 .extra1         = &zero,
225                 .extra2         = &int_max,
226         },
227 #endif
228         {}
229 };
230
231 static struct ctl_table ipc_root_table[] = {
232         {
233                 .procname       = "kernel",
234                 .mode           = 0555,
235                 .child          = ipc_kern_table,
236         },
237         {}
238 };
239
240 static int __init ipc_sysctl_init(void)
241 {
242         register_sysctl_table(ipc_root_table);
243         return 0;
244 }
245
246 device_initcall(ipc_sysctl_init);
247
248 static int __init ipc_mni_extend(char *str)
249 {
250         ipc_mni = IPCMNI_EXTEND;
251         ipc_mni_shift = IPCMNI_EXTEND_SHIFT;
252         ipc_min_cycle = IPCMNI_EXTEND_MIN_CYCLE;
253         pr_info("IPCMNI extended to %d.\n", ipc_mni);
254         return 0;
255 }
256 early_param("ipcmni_extend", ipc_mni_extend);