xref: /openbmc/linux/ipc/ipc_sysctl.c (revision 32927393dc1ccd60fb2bdc05b9e8e88753761469)
1b886d83cSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2a5494dcdSEric W. Biederman /*
3a5494dcdSEric W. Biederman  *  Copyright (C) 2007
4a5494dcdSEric W. Biederman  *
5a5494dcdSEric W. Biederman  *  Author: Eric Biederman <ebiederm@xmision.com>
6a5494dcdSEric W. Biederman  */
7a5494dcdSEric W. Biederman 
8a5494dcdSEric W. Biederman #include <linux/module.h>
9a5494dcdSEric W. Biederman #include <linux/ipc.h>
10a5494dcdSEric W. Biederman #include <linux/nsproxy.h>
11a5494dcdSEric W. Biederman #include <linux/sysctl.h>
12a5494dcdSEric W. Biederman #include <linux/uaccess.h>
13ae5e1b22SPavel Emelyanov #include <linux/ipc_namespace.h>
146546bc42SNadia Derbey #include <linux/msg.h>
156546bc42SNadia Derbey #include "util.h"
16a5494dcdSEric W. Biederman 
17a5c5928bSJoe Perches static void *get_ipc(struct ctl_table *table)
18a5494dcdSEric W. Biederman {
19a5494dcdSEric W. Biederman 	char *which = table->data;
20a5494dcdSEric W. Biederman 	struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns;
21a5494dcdSEric W. Biederman 	which = (which - (char *)&init_ipc_ns) + (char *)ipc_ns;
22a5494dcdSEric W. Biederman 	return which;
23a5494dcdSEric W. Biederman }
24a5494dcdSEric W. Biederman 
2511dea190SSerge E. Hallyn #ifdef CONFIG_PROC_SYSCTL
26a5c5928bSJoe Perches static int proc_ipc_dointvec(struct ctl_table *table, int write,
27*32927393SChristoph Hellwig 		void *buffer, size_t *lenp, loff_t *ppos)
28a5494dcdSEric W. Biederman {
29a5494dcdSEric W. Biederman 	struct ctl_table ipc_table;
30b34a6b1dSVasiliy Kulikov 
31a5494dcdSEric W. Biederman 	memcpy(&ipc_table, table, sizeof(ipc_table));
32a5494dcdSEric W. Biederman 	ipc_table.data = get_ipc(table);
33a5494dcdSEric W. Biederman 
348d65af78SAlexey Dobriyan 	return proc_dointvec(&ipc_table, write, buffer, lenp, ppos);
35a5494dcdSEric W. Biederman }
36a5494dcdSEric W. Biederman 
37a5c5928bSJoe Perches static int proc_ipc_dointvec_minmax(struct ctl_table *table, int write,
38*32927393SChristoph Hellwig 		void *buffer, size_t *lenp, loff_t *ppos)
39b34a6b1dSVasiliy Kulikov {
40b34a6b1dSVasiliy Kulikov 	struct ctl_table ipc_table;
41b34a6b1dSVasiliy Kulikov 
42b34a6b1dSVasiliy Kulikov 	memcpy(&ipc_table, table, sizeof(ipc_table));
43b34a6b1dSVasiliy Kulikov 	ipc_table.data = get_ipc(table);
44b34a6b1dSVasiliy Kulikov 
45b34a6b1dSVasiliy Kulikov 	return proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos);
46b34a6b1dSVasiliy Kulikov }
47b34a6b1dSVasiliy Kulikov 
48a5c5928bSJoe Perches static int proc_ipc_dointvec_minmax_orphans(struct ctl_table *table, int write,
49*32927393SChristoph Hellwig 		void *buffer, size_t *lenp, loff_t *ppos)
50b34a6b1dSVasiliy Kulikov {
51b34a6b1dSVasiliy Kulikov 	struct ipc_namespace *ns = current->nsproxy->ipc_ns;
52b34a6b1dSVasiliy Kulikov 	int err = proc_ipc_dointvec_minmax(table, write, buffer, lenp, ppos);
53b34a6b1dSVasiliy Kulikov 
54b34a6b1dSVasiliy Kulikov 	if (err < 0)
55b34a6b1dSVasiliy Kulikov 		return err;
56b34a6b1dSVasiliy Kulikov 	if (ns->shm_rmid_forced)
57b34a6b1dSVasiliy Kulikov 		shm_destroy_orphaned(ns);
58b34a6b1dSVasiliy Kulikov 	return err;
59b34a6b1dSVasiliy Kulikov }
60b34a6b1dSVasiliy Kulikov 
61a5c5928bSJoe Perches static int proc_ipc_doulongvec_minmax(struct ctl_table *table, int write,
62*32927393SChristoph Hellwig 		void *buffer, size_t *lenp, loff_t *ppos)
63a5494dcdSEric W. Biederman {
64a5494dcdSEric W. Biederman 	struct ctl_table ipc_table;
65a5494dcdSEric W. Biederman 	memcpy(&ipc_table, table, sizeof(ipc_table));
66a5494dcdSEric W. Biederman 	ipc_table.data = get_ipc(table);
67a5494dcdSEric W. Biederman 
688d65af78SAlexey Dobriyan 	return proc_doulongvec_minmax(&ipc_table, write, buffer,
69a5494dcdSEric W. Biederman 					lenp, ppos);
70a5494dcdSEric W. Biederman }
71a5494dcdSEric W. Biederman 
720050ee05SManfred Spraul static int proc_ipc_auto_msgmni(struct ctl_table *table, int write,
73*32927393SChristoph Hellwig 		void *buffer, size_t *lenp, loff_t *ppos)
749eefe520SNadia Derbey {
759eefe520SNadia Derbey 	struct ctl_table ipc_table;
760050ee05SManfred Spraul 	int dummy = 0;
779eefe520SNadia Derbey 
789eefe520SNadia Derbey 	memcpy(&ipc_table, table, sizeof(ipc_table));
790050ee05SManfred Spraul 	ipc_table.data = &dummy;
809eefe520SNadia Derbey 
810050ee05SManfred Spraul 	if (write)
820050ee05SManfred Spraul 		pr_info_once("writing to auto_msgmni has no effect");
839eefe520SNadia Derbey 
840050ee05SManfred Spraul 	return proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos);
859eefe520SNadia Derbey }
869eefe520SNadia Derbey 
878c81ddd2SWaiman Long static int proc_ipc_sem_dointvec(struct ctl_table *table, int write,
888c81ddd2SWaiman Long 	void __user *buffer, size_t *lenp, loff_t *ppos)
898c81ddd2SWaiman Long {
908c81ddd2SWaiman Long 	int ret, semmni;
918c81ddd2SWaiman Long 	struct ipc_namespace *ns = current->nsproxy->ipc_ns;
928c81ddd2SWaiman Long 
938c81ddd2SWaiman Long 	semmni = ns->sem_ctls[3];
948c81ddd2SWaiman Long 	ret = proc_ipc_dointvec(table, write, buffer, lenp, ppos);
958c81ddd2SWaiman Long 
968c81ddd2SWaiman Long 	if (!ret)
978c81ddd2SWaiman Long 		ret = sem_check_semmni(current->nsproxy->ipc_ns);
988c81ddd2SWaiman Long 
998c81ddd2SWaiman Long 	/*
1008c81ddd2SWaiman Long 	 * Reset the semmni value if an error happens.
1018c81ddd2SWaiman Long 	 */
1028c81ddd2SWaiman Long 	if (ret)
1038c81ddd2SWaiman Long 		ns->sem_ctls[3] = semmni;
1048c81ddd2SWaiman Long 	return ret;
1058c81ddd2SWaiman Long }
1068c81ddd2SWaiman Long 
107a5494dcdSEric W. Biederman #else
108a5494dcdSEric W. Biederman #define proc_ipc_doulongvec_minmax NULL
109a5494dcdSEric W. Biederman #define proc_ipc_dointvec	   NULL
110b34a6b1dSVasiliy Kulikov #define proc_ipc_dointvec_minmax   NULL
111b34a6b1dSVasiliy Kulikov #define proc_ipc_dointvec_minmax_orphans   NULL
1120050ee05SManfred Spraul #define proc_ipc_auto_msgmni	   NULL
1138c81ddd2SWaiman Long #define proc_ipc_sem_dointvec	   NULL
114a5494dcdSEric W. Biederman #endif
115a5494dcdSEric W. Biederman 
1165ac893b8SWaiman Long int ipc_mni = IPCMNI;
1175ac893b8SWaiman Long int ipc_mni_shift = IPCMNI_SHIFT;
11899db46eaSManfred Spraul int ipc_min_cycle = RADIX_TREE_MAP_SIZE;
1199eefe520SNadia Derbey 
120a5494dcdSEric W. Biederman static struct ctl_table ipc_kern_table[] = {
121a5494dcdSEric W. Biederman 	{
122a5494dcdSEric W. Biederman 		.procname	= "shmmax",
123a5494dcdSEric W. Biederman 		.data		= &init_ipc_ns.shm_ctlmax,
124a5494dcdSEric W. Biederman 		.maxlen		= sizeof(init_ipc_ns.shm_ctlmax),
125a5494dcdSEric W. Biederman 		.mode		= 0644,
126a5494dcdSEric W. Biederman 		.proc_handler	= proc_ipc_doulongvec_minmax,
127a5494dcdSEric W. Biederman 	},
128a5494dcdSEric W. Biederman 	{
129a5494dcdSEric W. Biederman 		.procname	= "shmall",
130a5494dcdSEric W. Biederman 		.data		= &init_ipc_ns.shm_ctlall,
131a5494dcdSEric W. Biederman 		.maxlen		= sizeof(init_ipc_ns.shm_ctlall),
132a5494dcdSEric W. Biederman 		.mode		= 0644,
133a5494dcdSEric W. Biederman 		.proc_handler	= proc_ipc_doulongvec_minmax,
134a5494dcdSEric W. Biederman 	},
135a5494dcdSEric W. Biederman 	{
136a5494dcdSEric W. Biederman 		.procname	= "shmmni",
137a5494dcdSEric W. Biederman 		.data		= &init_ipc_ns.shm_ctlmni,
138a5494dcdSEric W. Biederman 		.maxlen		= sizeof(init_ipc_ns.shm_ctlmni),
139a5494dcdSEric W. Biederman 		.mode		= 0644,
1406730e658SWaiman Long 		.proc_handler	= proc_ipc_dointvec_minmax,
141eec4844fSMatteo Croce 		.extra1		= SYSCTL_ZERO,
1426730e658SWaiman Long 		.extra2		= &ipc_mni,
143a5494dcdSEric W. Biederman 	},
144a5494dcdSEric W. Biederman 	{
145b34a6b1dSVasiliy Kulikov 		.procname	= "shm_rmid_forced",
146b34a6b1dSVasiliy Kulikov 		.data		= &init_ipc_ns.shm_rmid_forced,
147b34a6b1dSVasiliy Kulikov 		.maxlen		= sizeof(init_ipc_ns.shm_rmid_forced),
148b34a6b1dSVasiliy Kulikov 		.mode		= 0644,
149b34a6b1dSVasiliy Kulikov 		.proc_handler	= proc_ipc_dointvec_minmax_orphans,
150eec4844fSMatteo Croce 		.extra1		= SYSCTL_ZERO,
151eec4844fSMatteo Croce 		.extra2		= SYSCTL_ONE,
152b34a6b1dSVasiliy Kulikov 	},
153b34a6b1dSVasiliy Kulikov 	{
154a5494dcdSEric W. Biederman 		.procname	= "msgmax",
155a5494dcdSEric W. Biederman 		.data		= &init_ipc_ns.msg_ctlmax,
156a5494dcdSEric W. Biederman 		.maxlen		= sizeof(init_ipc_ns.msg_ctlmax),
157a5494dcdSEric W. Biederman 		.mode		= 0644,
1589bf76ca3SMathias Krause 		.proc_handler	= proc_ipc_dointvec_minmax,
159eec4844fSMatteo Croce 		.extra1		= SYSCTL_ZERO,
160eec4844fSMatteo Croce 		.extra2		= SYSCTL_INT_MAX,
161a5494dcdSEric W. Biederman 	},
162a5494dcdSEric W. Biederman 	{
163a5494dcdSEric W. Biederman 		.procname	= "msgmni",
164a5494dcdSEric W. Biederman 		.data		= &init_ipc_ns.msg_ctlmni,
165a5494dcdSEric W. Biederman 		.maxlen		= sizeof(init_ipc_ns.msg_ctlmni),
166a5494dcdSEric W. Biederman 		.mode		= 0644,
1670050ee05SManfred Spraul 		.proc_handler	= proc_ipc_dointvec_minmax,
168eec4844fSMatteo Croce 		.extra1		= SYSCTL_ZERO,
1696730e658SWaiman Long 		.extra2		= &ipc_mni,
170a5494dcdSEric W. Biederman 	},
171a5494dcdSEric W. Biederman 	{
1720050ee05SManfred Spraul 		.procname	= "auto_msgmni",
1730050ee05SManfred Spraul 		.data		= NULL,
1740050ee05SManfred Spraul 		.maxlen		= sizeof(int),
1750050ee05SManfred Spraul 		.mode		= 0644,
1760050ee05SManfred Spraul 		.proc_handler	= proc_ipc_auto_msgmni,
177eec4844fSMatteo Croce 		.extra1		= SYSCTL_ZERO,
178eec4844fSMatteo Croce 		.extra2		= SYSCTL_ONE,
1790050ee05SManfred Spraul 	},
1800050ee05SManfred Spraul 	{
181a5494dcdSEric W. Biederman 		.procname	=  "msgmnb",
182a5494dcdSEric W. Biederman 		.data		= &init_ipc_ns.msg_ctlmnb,
183a5494dcdSEric W. Biederman 		.maxlen		= sizeof(init_ipc_ns.msg_ctlmnb),
184a5494dcdSEric W. Biederman 		.mode		= 0644,
1859bf76ca3SMathias Krause 		.proc_handler	= proc_ipc_dointvec_minmax,
186eec4844fSMatteo Croce 		.extra1		= SYSCTL_ZERO,
187eec4844fSMatteo Croce 		.extra2		= SYSCTL_INT_MAX,
188a5494dcdSEric W. Biederman 	},
189a5494dcdSEric W. Biederman 	{
190a5494dcdSEric W. Biederman 		.procname	= "sem",
191a5494dcdSEric W. Biederman 		.data		= &init_ipc_ns.sem_ctls,
192a5494dcdSEric W. Biederman 		.maxlen		= 4*sizeof(int),
193a5494dcdSEric W. Biederman 		.mode		= 0644,
1948c81ddd2SWaiman Long 		.proc_handler	= proc_ipc_sem_dointvec,
195a5494dcdSEric W. Biederman 	},
19603f59566SStanislav Kinsbursky #ifdef CONFIG_CHECKPOINT_RESTORE
19703f59566SStanislav Kinsbursky 	{
19803f59566SStanislav Kinsbursky 		.procname	= "sem_next_id",
19903f59566SStanislav Kinsbursky 		.data		= &init_ipc_ns.ids[IPC_SEM_IDS].next_id,
20003f59566SStanislav Kinsbursky 		.maxlen		= sizeof(init_ipc_ns.ids[IPC_SEM_IDS].next_id),
20103f59566SStanislav Kinsbursky 		.mode		= 0644,
20203f59566SStanislav Kinsbursky 		.proc_handler	= proc_ipc_dointvec_minmax,
203eec4844fSMatteo Croce 		.extra1		= SYSCTL_ZERO,
204eec4844fSMatteo Croce 		.extra2		= SYSCTL_INT_MAX,
20503f59566SStanislav Kinsbursky 	},
20603f59566SStanislav Kinsbursky 	{
20703f59566SStanislav Kinsbursky 		.procname	= "msg_next_id",
20803f59566SStanislav Kinsbursky 		.data		= &init_ipc_ns.ids[IPC_MSG_IDS].next_id,
20903f59566SStanislav Kinsbursky 		.maxlen		= sizeof(init_ipc_ns.ids[IPC_MSG_IDS].next_id),
21003f59566SStanislav Kinsbursky 		.mode		= 0644,
21103f59566SStanislav Kinsbursky 		.proc_handler	= proc_ipc_dointvec_minmax,
212eec4844fSMatteo Croce 		.extra1		= SYSCTL_ZERO,
213eec4844fSMatteo Croce 		.extra2		= SYSCTL_INT_MAX,
21403f59566SStanislav Kinsbursky 	},
21503f59566SStanislav Kinsbursky 	{
21603f59566SStanislav Kinsbursky 		.procname	= "shm_next_id",
21703f59566SStanislav Kinsbursky 		.data		= &init_ipc_ns.ids[IPC_SHM_IDS].next_id,
21803f59566SStanislav Kinsbursky 		.maxlen		= sizeof(init_ipc_ns.ids[IPC_SHM_IDS].next_id),
21903f59566SStanislav Kinsbursky 		.mode		= 0644,
22003f59566SStanislav Kinsbursky 		.proc_handler	= proc_ipc_dointvec_minmax,
221eec4844fSMatteo Croce 		.extra1		= SYSCTL_ZERO,
222eec4844fSMatteo Croce 		.extra2		= SYSCTL_INT_MAX,
22303f59566SStanislav Kinsbursky 	},
22403f59566SStanislav Kinsbursky #endif
225a5494dcdSEric W. Biederman 	{}
226a5494dcdSEric W. Biederman };
227a5494dcdSEric W. Biederman 
228a5494dcdSEric W. Biederman static struct ctl_table ipc_root_table[] = {
229a5494dcdSEric W. Biederman 	{
230a5494dcdSEric W. Biederman 		.procname	= "kernel",
231a5494dcdSEric W. Biederman 		.mode		= 0555,
232a5494dcdSEric W. Biederman 		.child		= ipc_kern_table,
233a5494dcdSEric W. Biederman 	},
234a5494dcdSEric W. Biederman 	{}
235a5494dcdSEric W. Biederman };
236a5494dcdSEric W. Biederman 
237a5494dcdSEric W. Biederman static int __init ipc_sysctl_init(void)
238a5494dcdSEric W. Biederman {
2390b4d4147SEric W. Biederman 	register_sysctl_table(ipc_root_table);
240a5494dcdSEric W. Biederman 	return 0;
241a5494dcdSEric W. Biederman }
242a5494dcdSEric W. Biederman 
2436d08a256SDavidlohr Bueso device_initcall(ipc_sysctl_init);
2445ac893b8SWaiman Long 
2455ac893b8SWaiman Long static int __init ipc_mni_extend(char *str)
2465ac893b8SWaiman Long {
2475ac893b8SWaiman Long 	ipc_mni = IPCMNI_EXTEND;
2485ac893b8SWaiman Long 	ipc_mni_shift = IPCMNI_EXTEND_SHIFT;
24999db46eaSManfred Spraul 	ipc_min_cycle = IPCMNI_EXTEND_MIN_CYCLE;
2505ac893b8SWaiman Long 	pr_info("IPCMNI extended to %d.\n", ipc_mni);
2515ac893b8SWaiman Long 	return 0;
2525ac893b8SWaiman Long }
2535ac893b8SWaiman Long early_param("ipcmni_extend", ipc_mni_extend);
254