Merge tag 'platform-drivers-x86-v5.18-1' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-microblaze.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/capability.h>
14 #include <linux/ipc_namespace.h>
15 #include <linux/msg.h>
16 #include "util.h"
17
18 static void *get_ipc(struct ctl_table *table)
19 {
20         char *which = table->data;
21         struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns;
22         which = (which - (char *)&init_ipc_ns) + (char *)ipc_ns;
23         return which;
24 }
25
26 static int proc_ipc_dointvec(struct ctl_table *table, int write,
27                 void *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 *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 *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 *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 *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 *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 #ifdef CONFIG_CHECKPOINT_RESTORE
108 static int proc_ipc_dointvec_minmax_checkpoint_restore(struct ctl_table *table,
109                 int write, void *buffer, size_t *lenp, loff_t *ppos)
110 {
111         struct user_namespace *user_ns = current->nsproxy->ipc_ns->user_ns;
112
113         if (write && !checkpoint_restore_ns_capable(user_ns))
114                 return -EPERM;
115
116         return proc_ipc_dointvec_minmax(table, write, buffer, lenp, ppos);
117 }
118 #endif
119
120 int ipc_mni = IPCMNI;
121 int ipc_mni_shift = IPCMNI_SHIFT;
122 int ipc_min_cycle = RADIX_TREE_MAP_SIZE;
123
124 static struct ctl_table ipc_kern_table[] = {
125         {
126                 .procname       = "shmmax",
127                 .data           = &init_ipc_ns.shm_ctlmax,
128                 .maxlen         = sizeof(init_ipc_ns.shm_ctlmax),
129                 .mode           = 0644,
130                 .proc_handler   = proc_ipc_doulongvec_minmax,
131         },
132         {
133                 .procname       = "shmall",
134                 .data           = &init_ipc_ns.shm_ctlall,
135                 .maxlen         = sizeof(init_ipc_ns.shm_ctlall),
136                 .mode           = 0644,
137                 .proc_handler   = proc_ipc_doulongvec_minmax,
138         },
139         {
140                 .procname       = "shmmni",
141                 .data           = &init_ipc_ns.shm_ctlmni,
142                 .maxlen         = sizeof(init_ipc_ns.shm_ctlmni),
143                 .mode           = 0644,
144                 .proc_handler   = proc_ipc_dointvec_minmax,
145                 .extra1         = SYSCTL_ZERO,
146                 .extra2         = &ipc_mni,
147         },
148         {
149                 .procname       = "shm_rmid_forced",
150                 .data           = &init_ipc_ns.shm_rmid_forced,
151                 .maxlen         = sizeof(init_ipc_ns.shm_rmid_forced),
152                 .mode           = 0644,
153                 .proc_handler   = proc_ipc_dointvec_minmax_orphans,
154                 .extra1         = SYSCTL_ZERO,
155                 .extra2         = SYSCTL_ONE,
156         },
157         {
158                 .procname       = "msgmax",
159                 .data           = &init_ipc_ns.msg_ctlmax,
160                 .maxlen         = sizeof(init_ipc_ns.msg_ctlmax),
161                 .mode           = 0644,
162                 .proc_handler   = proc_ipc_dointvec_minmax,
163                 .extra1         = SYSCTL_ZERO,
164                 .extra2         = SYSCTL_INT_MAX,
165         },
166         {
167                 .procname       = "msgmni",
168                 .data           = &init_ipc_ns.msg_ctlmni,
169                 .maxlen         = sizeof(init_ipc_ns.msg_ctlmni),
170                 .mode           = 0644,
171                 .proc_handler   = proc_ipc_dointvec_minmax,
172                 .extra1         = SYSCTL_ZERO,
173                 .extra2         = &ipc_mni,
174         },
175         {
176                 .procname       = "auto_msgmni",
177                 .data           = NULL,
178                 .maxlen         = sizeof(int),
179                 .mode           = 0644,
180                 .proc_handler   = proc_ipc_auto_msgmni,
181                 .extra1         = SYSCTL_ZERO,
182                 .extra2         = SYSCTL_ONE,
183         },
184         {
185                 .procname       =  "msgmnb",
186                 .data           = &init_ipc_ns.msg_ctlmnb,
187                 .maxlen         = sizeof(init_ipc_ns.msg_ctlmnb),
188                 .mode           = 0644,
189                 .proc_handler   = proc_ipc_dointvec_minmax,
190                 .extra1         = SYSCTL_ZERO,
191                 .extra2         = SYSCTL_INT_MAX,
192         },
193         {
194                 .procname       = "sem",
195                 .data           = &init_ipc_ns.sem_ctls,
196                 .maxlen         = 4*sizeof(int),
197                 .mode           = 0644,
198                 .proc_handler   = proc_ipc_sem_dointvec,
199         },
200 #ifdef CONFIG_CHECKPOINT_RESTORE
201         {
202                 .procname       = "sem_next_id",
203                 .data           = &init_ipc_ns.ids[IPC_SEM_IDS].next_id,
204                 .maxlen         = sizeof(init_ipc_ns.ids[IPC_SEM_IDS].next_id),
205                 .mode           = 0666,
206                 .proc_handler   = proc_ipc_dointvec_minmax_checkpoint_restore,
207                 .extra1         = SYSCTL_ZERO,
208                 .extra2         = SYSCTL_INT_MAX,
209         },
210         {
211                 .procname       = "msg_next_id",
212                 .data           = &init_ipc_ns.ids[IPC_MSG_IDS].next_id,
213                 .maxlen         = sizeof(init_ipc_ns.ids[IPC_MSG_IDS].next_id),
214                 .mode           = 0666,
215                 .proc_handler   = proc_ipc_dointvec_minmax_checkpoint_restore,
216                 .extra1         = SYSCTL_ZERO,
217                 .extra2         = SYSCTL_INT_MAX,
218         },
219         {
220                 .procname       = "shm_next_id",
221                 .data           = &init_ipc_ns.ids[IPC_SHM_IDS].next_id,
222                 .maxlen         = sizeof(init_ipc_ns.ids[IPC_SHM_IDS].next_id),
223                 .mode           = 0666,
224                 .proc_handler   = proc_ipc_dointvec_minmax_checkpoint_restore,
225                 .extra1         = SYSCTL_ZERO,
226                 .extra2         = SYSCTL_INT_MAX,
227         },
228 #endif
229         {}
230 };
231
232 static struct ctl_table ipc_root_table[] = {
233         {
234                 .procname       = "kernel",
235                 .mode           = 0555,
236                 .child          = ipc_kern_table,
237         },
238         {}
239 };
240
241 static int __init ipc_sysctl_init(void)
242 {
243         register_sysctl_table(ipc_root_table);
244         return 0;
245 }
246
247 device_initcall(ipc_sysctl_init);
248
249 static int __init ipc_mni_extend(char *str)
250 {
251         ipc_mni = IPCMNI_EXTEND;
252         ipc_mni_shift = IPCMNI_EXTEND_SHIFT;
253         ipc_min_cycle = IPCMNI_EXTEND_MIN_CYCLE;
254         pr_info("IPCMNI extended to %d.\n", ipc_mni);
255         return 0;
256 }
257 early_param("ipcmni_extend", ipc_mni_extend);