blob: 345e4d673e61eba3028522628fd48da444d5a137 [file] [log] [blame]
Thomas Gleixnerb886d83c2019-06-01 10:08:55 +02001// SPDX-License-Identifier: GPL-2.0-only
Eric W. Biedermana5494dc2007-02-14 00:34:06 -08002/*
3 * Copyright (C) 2007
4 *
5 * Author: Eric Biederman <ebiederm@xmision.com>
Eric W. Biedermana5494dc2007-02-14 00:34:06 -08006 */
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>
Michal Clapinski5563cab2021-11-08 18:35:59 -080013#include <linux/capability.h>
Pavel Emelyanovae5e1b22008-02-08 04:18:22 -080014#include <linux/ipc_namespace.h>
Nadia Derbey6546bc42008-04-29 01:00:45 -070015#include <linux/msg.h>
16#include "util.h"
Eric W. Biedermana5494dc2007-02-14 00:34:06 -080017
Joe Perchesa5c59282014-06-06 14:38:07 -070018static void *get_ipc(struct ctl_table *table)
Eric W. Biedermana5494dc2007-02-14 00:34:06 -080019{
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}
Eric W. Biedermana5494dc2007-02-14 00:34:06 -080025
Serge E. Hallyn11dea192009-04-02 16:58:27 -070026#ifdef CONFIG_PROC_SYSCTL
Joe Perchesa5c59282014-06-06 14:38:07 -070027static int proc_ipc_dointvec(struct ctl_table *table, int write,
Christoph Hellwig32927392020-04-24 08:43:38 +020028 void *buffer, size_t *lenp, loff_t *ppos)
Eric W. Biedermana5494dc2007-02-14 00:34:06 -080029{
30 struct ctl_table ipc_table;
Vasiliy Kulikovb34a6b12011-07-26 16:08:48 -070031
Eric W. Biedermana5494dc2007-02-14 00:34:06 -080032 memcpy(&ipc_table, table, sizeof(ipc_table));
33 ipc_table.data = get_ipc(table);
34
Alexey Dobriyan8d65af72009-09-23 15:57:19 -070035 return proc_dointvec(&ipc_table, write, buffer, lenp, ppos);
Eric W. Biedermana5494dc2007-02-14 00:34:06 -080036}
37
Joe Perchesa5c59282014-06-06 14:38:07 -070038static int proc_ipc_dointvec_minmax(struct ctl_table *table, int write,
Christoph Hellwig32927392020-04-24 08:43:38 +020039 void *buffer, size_t *lenp, loff_t *ppos)
Vasiliy Kulikovb34a6b12011-07-26 16:08:48 -070040{
41 struct ctl_table ipc_table;
42
43 memcpy(&ipc_table, table, sizeof(ipc_table));
44 ipc_table.data = get_ipc(table);
45
46 return proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos);
47}
48
Joe Perchesa5c59282014-06-06 14:38:07 -070049static int proc_ipc_dointvec_minmax_orphans(struct ctl_table *table, int write,
Christoph Hellwig32927392020-04-24 08:43:38 +020050 void *buffer, size_t *lenp, loff_t *ppos)
Vasiliy Kulikovb34a6b12011-07-26 16:08:48 -070051{
52 struct ipc_namespace *ns = current->nsproxy->ipc_ns;
53 int err = proc_ipc_dointvec_minmax(table, write, buffer, lenp, ppos);
54
55 if (err < 0)
56 return err;
57 if (ns->shm_rmid_forced)
58 shm_destroy_orphaned(ns);
59 return err;
60}
61
Joe Perchesa5c59282014-06-06 14:38:07 -070062static int proc_ipc_doulongvec_minmax(struct ctl_table *table, int write,
Christoph Hellwig32927392020-04-24 08:43:38 +020063 void *buffer, size_t *lenp, loff_t *ppos)
Eric W. Biedermana5494dc2007-02-14 00:34:06 -080064{
65 struct ctl_table ipc_table;
66 memcpy(&ipc_table, table, sizeof(ipc_table));
67 ipc_table.data = get_ipc(table);
68
Alexey Dobriyan8d65af72009-09-23 15:57:19 -070069 return proc_doulongvec_minmax(&ipc_table, write, buffer,
Eric W. Biedermana5494dc2007-02-14 00:34:06 -080070 lenp, ppos);
71}
72
Manfred Spraul0050ee02014-12-12 16:58:17 -080073static int proc_ipc_auto_msgmni(struct ctl_table *table, int write,
Christoph Hellwig32927392020-04-24 08:43:38 +020074 void *buffer, size_t *lenp, loff_t *ppos)
Nadia Derbey9eefe522008-07-25 01:48:08 -070075{
76 struct ctl_table ipc_table;
Manfred Spraul0050ee02014-12-12 16:58:17 -080077 int dummy = 0;
Nadia Derbey9eefe522008-07-25 01:48:08 -070078
79 memcpy(&ipc_table, table, sizeof(ipc_table));
Manfred Spraul0050ee02014-12-12 16:58:17 -080080 ipc_table.data = &dummy;
Nadia Derbey9eefe522008-07-25 01:48:08 -070081
Manfred Spraul0050ee02014-12-12 16:58:17 -080082 if (write)
83 pr_info_once("writing to auto_msgmni has no effect");
Nadia Derbey9eefe522008-07-25 01:48:08 -070084
Manfred Spraul0050ee02014-12-12 16:58:17 -080085 return proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos);
Nadia Derbey9eefe522008-07-25 01:48:08 -070086}
87
Waiman Long8c81ddd2018-10-30 15:07:24 -070088static int proc_ipc_sem_dointvec(struct ctl_table *table, int write,
Tobias Klauserfff16622020-09-04 16:35:46 -070089 void *buffer, size_t *lenp, loff_t *ppos)
Waiman Long8c81ddd2018-10-30 15:07:24 -070090{
91 int ret, semmni;
92 struct ipc_namespace *ns = current->nsproxy->ipc_ns;
93
94 semmni = ns->sem_ctls[3];
95 ret = proc_ipc_dointvec(table, write, buffer, lenp, ppos);
96
97 if (!ret)
98 ret = sem_check_semmni(current->nsproxy->ipc_ns);
99
100 /*
101 * Reset the semmni value if an error happens.
102 */
103 if (ret)
104 ns->sem_ctls[3] = semmni;
105 return ret;
106}
107
Michal Clapinski5563cab2021-11-08 18:35:59 -0800108#ifdef CONFIG_CHECKPOINT_RESTORE
109static int proc_ipc_dointvec_minmax_checkpoint_restore(struct ctl_table *table,
110 int write, void *buffer, size_t *lenp, loff_t *ppos)
111{
112 struct user_namespace *user_ns = current->nsproxy->ipc_ns->user_ns;
113
114 if (write && !checkpoint_restore_ns_capable(user_ns))
115 return -EPERM;
116
117 return proc_ipc_dointvec_minmax(table, write, buffer, lenp, ppos);
118}
119#endif
120
Eric W. Biedermana5494dc2007-02-14 00:34:06 -0800121#else
122#define proc_ipc_doulongvec_minmax NULL
123#define proc_ipc_dointvec NULL
Vasiliy Kulikovb34a6b12011-07-26 16:08:48 -0700124#define proc_ipc_dointvec_minmax NULL
125#define proc_ipc_dointvec_minmax_orphans NULL
Manfred Spraul0050ee02014-12-12 16:58:17 -0800126#define proc_ipc_auto_msgmni NULL
Waiman Long8c81ddd2018-10-30 15:07:24 -0700127#define proc_ipc_sem_dointvec NULL
Michal Clapinski5563cab2021-11-08 18:35:59 -0800128#ifdef CONFIG_CHECKPOINT_RESTORE
129#define proc_ipc_dointvec_minmax_checkpoint_restore NULL
130#endif /* CONFIG_CHECKPOINT_RESTORE */
Eric W. Biedermana5494dc2007-02-14 00:34:06 -0800131#endif
132
Waiman Long5ac893b2019-05-14 15:46:29 -0700133int ipc_mni = IPCMNI;
134int ipc_mni_shift = IPCMNI_SHIFT;
Manfred Spraul99db46e2019-05-14 15:46:36 -0700135int ipc_min_cycle = RADIX_TREE_MAP_SIZE;
Nadia Derbey9eefe522008-07-25 01:48:08 -0700136
Eric W. Biedermana5494dc2007-02-14 00:34:06 -0800137static struct ctl_table ipc_kern_table[] = {
138 {
Eric W. Biedermana5494dc2007-02-14 00:34:06 -0800139 .procname = "shmmax",
140 .data = &init_ipc_ns.shm_ctlmax,
Manfred Spraul239521f2014-01-27 17:07:04 -0800141 .maxlen = sizeof(init_ipc_ns.shm_ctlmax),
Eric W. Biedermana5494dc2007-02-14 00:34:06 -0800142 .mode = 0644,
143 .proc_handler = proc_ipc_doulongvec_minmax,
Eric W. Biedermana5494dc2007-02-14 00:34:06 -0800144 },
145 {
Eric W. Biedermana5494dc2007-02-14 00:34:06 -0800146 .procname = "shmall",
147 .data = &init_ipc_ns.shm_ctlall,
Manfred Spraul239521f2014-01-27 17:07:04 -0800148 .maxlen = sizeof(init_ipc_ns.shm_ctlall),
Eric W. Biedermana5494dc2007-02-14 00:34:06 -0800149 .mode = 0644,
150 .proc_handler = proc_ipc_doulongvec_minmax,
Eric W. Biedermana5494dc2007-02-14 00:34:06 -0800151 },
152 {
Eric W. Biedermana5494dc2007-02-14 00:34:06 -0800153 .procname = "shmmni",
154 .data = &init_ipc_ns.shm_ctlmni,
Manfred Spraul239521f2014-01-27 17:07:04 -0800155 .maxlen = sizeof(init_ipc_ns.shm_ctlmni),
Eric W. Biedermana5494dc2007-02-14 00:34:06 -0800156 .mode = 0644,
Waiman Long6730e652018-10-30 15:07:20 -0700157 .proc_handler = proc_ipc_dointvec_minmax,
Matteo Croceeec48442019-07-18 15:58:50 -0700158 .extra1 = SYSCTL_ZERO,
Waiman Long6730e652018-10-30 15:07:20 -0700159 .extra2 = &ipc_mni,
Eric W. Biedermana5494dc2007-02-14 00:34:06 -0800160 },
161 {
Vasiliy Kulikovb34a6b12011-07-26 16:08:48 -0700162 .procname = "shm_rmid_forced",
163 .data = &init_ipc_ns.shm_rmid_forced,
164 .maxlen = sizeof(init_ipc_ns.shm_rmid_forced),
165 .mode = 0644,
166 .proc_handler = proc_ipc_dointvec_minmax_orphans,
Matteo Croceeec48442019-07-18 15:58:50 -0700167 .extra1 = SYSCTL_ZERO,
168 .extra2 = SYSCTL_ONE,
Vasiliy Kulikovb34a6b12011-07-26 16:08:48 -0700169 },
170 {
Eric W. Biedermana5494dc2007-02-14 00:34:06 -0800171 .procname = "msgmax",
172 .data = &init_ipc_ns.msg_ctlmax,
Manfred Spraul239521f2014-01-27 17:07:04 -0800173 .maxlen = sizeof(init_ipc_ns.msg_ctlmax),
Eric W. Biedermana5494dc2007-02-14 00:34:06 -0800174 .mode = 0644,
Mathias Krause9bf76ca2013-11-03 12:36:28 +0100175 .proc_handler = proc_ipc_dointvec_minmax,
Matteo Croceeec48442019-07-18 15:58:50 -0700176 .extra1 = SYSCTL_ZERO,
177 .extra2 = SYSCTL_INT_MAX,
Eric W. Biedermana5494dc2007-02-14 00:34:06 -0800178 },
179 {
Eric W. Biedermana5494dc2007-02-14 00:34:06 -0800180 .procname = "msgmni",
181 .data = &init_ipc_ns.msg_ctlmni,
Manfred Spraul239521f2014-01-27 17:07:04 -0800182 .maxlen = sizeof(init_ipc_ns.msg_ctlmni),
Eric W. Biedermana5494dc2007-02-14 00:34:06 -0800183 .mode = 0644,
Manfred Spraul0050ee02014-12-12 16:58:17 -0800184 .proc_handler = proc_ipc_dointvec_minmax,
Matteo Croceeec48442019-07-18 15:58:50 -0700185 .extra1 = SYSCTL_ZERO,
Waiman Long6730e652018-10-30 15:07:20 -0700186 .extra2 = &ipc_mni,
Eric W. Biedermana5494dc2007-02-14 00:34:06 -0800187 },
188 {
Manfred Spraul0050ee02014-12-12 16:58:17 -0800189 .procname = "auto_msgmni",
190 .data = NULL,
191 .maxlen = sizeof(int),
192 .mode = 0644,
193 .proc_handler = proc_ipc_auto_msgmni,
Matteo Croceeec48442019-07-18 15:58:50 -0700194 .extra1 = SYSCTL_ZERO,
195 .extra2 = SYSCTL_ONE,
Manfred Spraul0050ee02014-12-12 16:58:17 -0800196 },
197 {
Eric W. Biedermana5494dc2007-02-14 00:34:06 -0800198 .procname = "msgmnb",
199 .data = &init_ipc_ns.msg_ctlmnb,
Manfred Spraul239521f2014-01-27 17:07:04 -0800200 .maxlen = sizeof(init_ipc_ns.msg_ctlmnb),
Eric W. Biedermana5494dc2007-02-14 00:34:06 -0800201 .mode = 0644,
Mathias Krause9bf76ca2013-11-03 12:36:28 +0100202 .proc_handler = proc_ipc_dointvec_minmax,
Matteo Croceeec48442019-07-18 15:58:50 -0700203 .extra1 = SYSCTL_ZERO,
204 .extra2 = SYSCTL_INT_MAX,
Eric W. Biedermana5494dc2007-02-14 00:34:06 -0800205 },
206 {
Eric W. Biedermana5494dc2007-02-14 00:34:06 -0800207 .procname = "sem",
208 .data = &init_ipc_ns.sem_ctls,
Manfred Spraul239521f2014-01-27 17:07:04 -0800209 .maxlen = 4*sizeof(int),
Eric W. Biedermana5494dc2007-02-14 00:34:06 -0800210 .mode = 0644,
Waiman Long8c81ddd2018-10-30 15:07:24 -0700211 .proc_handler = proc_ipc_sem_dointvec,
Eric W. Biedermana5494dc2007-02-14 00:34:06 -0800212 },
Stanislav Kinsbursky03f59562013-01-04 15:34:50 -0800213#ifdef CONFIG_CHECKPOINT_RESTORE
214 {
215 .procname = "sem_next_id",
216 .data = &init_ipc_ns.ids[IPC_SEM_IDS].next_id,
217 .maxlen = sizeof(init_ipc_ns.ids[IPC_SEM_IDS].next_id),
Michal Clapinski5563cab2021-11-08 18:35:59 -0800218 .mode = 0666,
219 .proc_handler = proc_ipc_dointvec_minmax_checkpoint_restore,
Matteo Croceeec48442019-07-18 15:58:50 -0700220 .extra1 = SYSCTL_ZERO,
221 .extra2 = SYSCTL_INT_MAX,
Stanislav Kinsbursky03f59562013-01-04 15:34:50 -0800222 },
223 {
224 .procname = "msg_next_id",
225 .data = &init_ipc_ns.ids[IPC_MSG_IDS].next_id,
226 .maxlen = sizeof(init_ipc_ns.ids[IPC_MSG_IDS].next_id),
Michal Clapinski5563cab2021-11-08 18:35:59 -0800227 .mode = 0666,
228 .proc_handler = proc_ipc_dointvec_minmax_checkpoint_restore,
Matteo Croceeec48442019-07-18 15:58:50 -0700229 .extra1 = SYSCTL_ZERO,
230 .extra2 = SYSCTL_INT_MAX,
Stanislav Kinsbursky03f59562013-01-04 15:34:50 -0800231 },
232 {
233 .procname = "shm_next_id",
234 .data = &init_ipc_ns.ids[IPC_SHM_IDS].next_id,
235 .maxlen = sizeof(init_ipc_ns.ids[IPC_SHM_IDS].next_id),
Michal Clapinski5563cab2021-11-08 18:35:59 -0800236 .mode = 0666,
237 .proc_handler = proc_ipc_dointvec_minmax_checkpoint_restore,
Matteo Croceeec48442019-07-18 15:58:50 -0700238 .extra1 = SYSCTL_ZERO,
239 .extra2 = SYSCTL_INT_MAX,
Stanislav Kinsbursky03f59562013-01-04 15:34:50 -0800240 },
241#endif
Eric W. Biedermana5494dc2007-02-14 00:34:06 -0800242 {}
243};
244
245static struct ctl_table ipc_root_table[] = {
246 {
Eric W. Biedermana5494dc2007-02-14 00:34:06 -0800247 .procname = "kernel",
248 .mode = 0555,
249 .child = ipc_kern_table,
250 },
251 {}
252};
253
254static int __init ipc_sysctl_init(void)
255{
Eric W. Biederman0b4d4142007-02-14 00:34:09 -0800256 register_sysctl_table(ipc_root_table);
Eric W. Biedermana5494dc2007-02-14 00:34:06 -0800257 return 0;
258}
259
Davidlohr Bueso6d08a252014-04-07 15:39:18 -0700260device_initcall(ipc_sysctl_init);
Waiman Long5ac893b2019-05-14 15:46:29 -0700261
262static int __init ipc_mni_extend(char *str)
263{
264 ipc_mni = IPCMNI_EXTEND;
265 ipc_mni_shift = IPCMNI_EXTEND_SHIFT;
Manfred Spraul99db46e2019-05-14 15:46:36 -0700266 ipc_min_cycle = IPCMNI_EXTEND_MIN_CYCLE;
Waiman Long5ac893b2019-05-14 15:46:29 -0700267 pr_info("IPCMNI extended to %d.\n", ipc_mni);
268 return 0;
269}
270early_param("ipcmni_extend", ipc_mni_extend);