xref: /openbmc/linux/ipc/ipc_sysctl.c (revision 5563cabdde7ee53c34ec7e5e0283bfcc9a1bc893)
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>
13*5563cabdSMichal Clapinski #include <linux/capability.h>
14ae5e1b22SPavel Emelyanov #include <linux/ipc_namespace.h>
156546bc42SNadia Derbey #include <linux/msg.h>
166546bc42SNadia Derbey #include "util.h"
17a5494dcdSEric W. Biederman 
18a5c5928bSJoe Perches static void *get_ipc(struct ctl_table *table)
19a5494dcdSEric W. Biederman {
20a5494dcdSEric W. Biederman 	char *which = table->data;
21a5494dcdSEric W. Biederman 	struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns;
22a5494dcdSEric W. Biederman 	which = (which - (char *)&init_ipc_ns) + (char *)ipc_ns;
23a5494dcdSEric W. Biederman 	return which;
24a5494dcdSEric W. Biederman }
25a5494dcdSEric W. Biederman 
2611dea190SSerge E. Hallyn #ifdef CONFIG_PROC_SYSCTL
27a5c5928bSJoe Perches static int proc_ipc_dointvec(struct ctl_table *table, int write,
2832927393SChristoph Hellwig 		void *buffer, size_t *lenp, loff_t *ppos)
29a5494dcdSEric W. Biederman {
30a5494dcdSEric W. Biederman 	struct ctl_table ipc_table;
31b34a6b1dSVasiliy Kulikov 
32a5494dcdSEric W. Biederman 	memcpy(&ipc_table, table, sizeof(ipc_table));
33a5494dcdSEric W. Biederman 	ipc_table.data = get_ipc(table);
34a5494dcdSEric W. Biederman 
358d65af78SAlexey Dobriyan 	return proc_dointvec(&ipc_table, write, buffer, lenp, ppos);
36a5494dcdSEric W. Biederman }
37a5494dcdSEric W. Biederman 
38a5c5928bSJoe Perches static int proc_ipc_dointvec_minmax(struct ctl_table *table, int write,
3932927393SChristoph Hellwig 		void *buffer, size_t *lenp, loff_t *ppos)
40b34a6b1dSVasiliy Kulikov {
41b34a6b1dSVasiliy Kulikov 	struct ctl_table ipc_table;
42b34a6b1dSVasiliy Kulikov 
43b34a6b1dSVasiliy Kulikov 	memcpy(&ipc_table, table, sizeof(ipc_table));
44b34a6b1dSVasiliy Kulikov 	ipc_table.data = get_ipc(table);
45b34a6b1dSVasiliy Kulikov 
46b34a6b1dSVasiliy Kulikov 	return proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos);
47b34a6b1dSVasiliy Kulikov }
48b34a6b1dSVasiliy Kulikov 
49a5c5928bSJoe Perches static int proc_ipc_dointvec_minmax_orphans(struct ctl_table *table, int write,
5032927393SChristoph Hellwig 		void *buffer, size_t *lenp, loff_t *ppos)
51b34a6b1dSVasiliy Kulikov {
52b34a6b1dSVasiliy Kulikov 	struct ipc_namespace *ns = current->nsproxy->ipc_ns;
53b34a6b1dSVasiliy Kulikov 	int err = proc_ipc_dointvec_minmax(table, write, buffer, lenp, ppos);
54b34a6b1dSVasiliy Kulikov 
55b34a6b1dSVasiliy Kulikov 	if (err < 0)
56b34a6b1dSVasiliy Kulikov 		return err;
57b34a6b1dSVasiliy Kulikov 	if (ns->shm_rmid_forced)
58b34a6b1dSVasiliy Kulikov 		shm_destroy_orphaned(ns);
59b34a6b1dSVasiliy Kulikov 	return err;
60b34a6b1dSVasiliy Kulikov }
61b34a6b1dSVasiliy Kulikov 
62a5c5928bSJoe Perches static int proc_ipc_doulongvec_minmax(struct ctl_table *table, int write,
6332927393SChristoph Hellwig 		void *buffer, size_t *lenp, loff_t *ppos)
64a5494dcdSEric W. Biederman {
65a5494dcdSEric W. Biederman 	struct ctl_table ipc_table;
66a5494dcdSEric W. Biederman 	memcpy(&ipc_table, table, sizeof(ipc_table));
67a5494dcdSEric W. Biederman 	ipc_table.data = get_ipc(table);
68a5494dcdSEric W. Biederman 
698d65af78SAlexey Dobriyan 	return proc_doulongvec_minmax(&ipc_table, write, buffer,
70a5494dcdSEric W. Biederman 					lenp, ppos);
71a5494dcdSEric W. Biederman }
72a5494dcdSEric W. Biederman 
730050ee05SManfred Spraul static int proc_ipc_auto_msgmni(struct ctl_table *table, int write,
7432927393SChristoph Hellwig 		void *buffer, size_t *lenp, loff_t *ppos)
759eefe520SNadia Derbey {
769eefe520SNadia Derbey 	struct ctl_table ipc_table;
770050ee05SManfred Spraul 	int dummy = 0;
789eefe520SNadia Derbey 
799eefe520SNadia Derbey 	memcpy(&ipc_table, table, sizeof(ipc_table));
800050ee05SManfred Spraul 	ipc_table.data = &dummy;
819eefe520SNadia Derbey 
820050ee05SManfred Spraul 	if (write)
830050ee05SManfred Spraul 		pr_info_once("writing to auto_msgmni has no effect");
849eefe520SNadia Derbey 
850050ee05SManfred Spraul 	return proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos);
869eefe520SNadia Derbey }
879eefe520SNadia Derbey 
888c81ddd2SWaiman Long static int proc_ipc_sem_dointvec(struct ctl_table *table, int write,
89fff1662cSTobias Klauser 	void *buffer, size_t *lenp, loff_t *ppos)
908c81ddd2SWaiman Long {
918c81ddd2SWaiman Long 	int ret, semmni;
928c81ddd2SWaiman Long 	struct ipc_namespace *ns = current->nsproxy->ipc_ns;
938c81ddd2SWaiman Long 
948c81ddd2SWaiman Long 	semmni = ns->sem_ctls[3];
958c81ddd2SWaiman Long 	ret = proc_ipc_dointvec(table, write, buffer, lenp, ppos);
968c81ddd2SWaiman Long 
978c81ddd2SWaiman Long 	if (!ret)
988c81ddd2SWaiman Long 		ret = sem_check_semmni(current->nsproxy->ipc_ns);
998c81ddd2SWaiman Long 
1008c81ddd2SWaiman Long 	/*
1018c81ddd2SWaiman Long 	 * Reset the semmni value if an error happens.
1028c81ddd2SWaiman Long 	 */
1038c81ddd2SWaiman Long 	if (ret)
1048c81ddd2SWaiman Long 		ns->sem_ctls[3] = semmni;
1058c81ddd2SWaiman Long 	return ret;
1068c81ddd2SWaiman Long }
1078c81ddd2SWaiman Long 
108*5563cabdSMichal Clapinski #ifdef CONFIG_CHECKPOINT_RESTORE
109*5563cabdSMichal Clapinski static int proc_ipc_dointvec_minmax_checkpoint_restore(struct ctl_table *table,
110*5563cabdSMichal Clapinski 		int write, void *buffer, size_t *lenp, loff_t *ppos)
111*5563cabdSMichal Clapinski {
112*5563cabdSMichal Clapinski 	struct user_namespace *user_ns = current->nsproxy->ipc_ns->user_ns;
113*5563cabdSMichal Clapinski 
114*5563cabdSMichal Clapinski 	if (write && !checkpoint_restore_ns_capable(user_ns))
115*5563cabdSMichal Clapinski 		return -EPERM;
116*5563cabdSMichal Clapinski 
117*5563cabdSMichal Clapinski 	return proc_ipc_dointvec_minmax(table, write, buffer, lenp, ppos);
118*5563cabdSMichal Clapinski }
119*5563cabdSMichal Clapinski #endif
120*5563cabdSMichal Clapinski 
121a5494dcdSEric W. Biederman #else
122a5494dcdSEric W. Biederman #define proc_ipc_doulongvec_minmax NULL
123a5494dcdSEric W. Biederman #define proc_ipc_dointvec	   NULL
124b34a6b1dSVasiliy Kulikov #define proc_ipc_dointvec_minmax   NULL
125b34a6b1dSVasiliy Kulikov #define proc_ipc_dointvec_minmax_orphans   NULL
1260050ee05SManfred Spraul #define proc_ipc_auto_msgmni	   NULL
1278c81ddd2SWaiman Long #define proc_ipc_sem_dointvec	   NULL
128*5563cabdSMichal Clapinski #ifdef CONFIG_CHECKPOINT_RESTORE
129*5563cabdSMichal Clapinski #define proc_ipc_dointvec_minmax_checkpoint_restore	NULL
130*5563cabdSMichal Clapinski #endif	/* CONFIG_CHECKPOINT_RESTORE */
131a5494dcdSEric W. Biederman #endif
132a5494dcdSEric W. Biederman 
1335ac893b8SWaiman Long int ipc_mni = IPCMNI;
1345ac893b8SWaiman Long int ipc_mni_shift = IPCMNI_SHIFT;
13599db46eaSManfred Spraul int ipc_min_cycle = RADIX_TREE_MAP_SIZE;
1369eefe520SNadia Derbey 
137a5494dcdSEric W. Biederman static struct ctl_table ipc_kern_table[] = {
138a5494dcdSEric W. Biederman 	{
139a5494dcdSEric W. Biederman 		.procname	= "shmmax",
140a5494dcdSEric W. Biederman 		.data		= &init_ipc_ns.shm_ctlmax,
141a5494dcdSEric W. Biederman 		.maxlen		= sizeof(init_ipc_ns.shm_ctlmax),
142a5494dcdSEric W. Biederman 		.mode		= 0644,
143a5494dcdSEric W. Biederman 		.proc_handler	= proc_ipc_doulongvec_minmax,
144a5494dcdSEric W. Biederman 	},
145a5494dcdSEric W. Biederman 	{
146a5494dcdSEric W. Biederman 		.procname	= "shmall",
147a5494dcdSEric W. Biederman 		.data		= &init_ipc_ns.shm_ctlall,
148a5494dcdSEric W. Biederman 		.maxlen		= sizeof(init_ipc_ns.shm_ctlall),
149a5494dcdSEric W. Biederman 		.mode		= 0644,
150a5494dcdSEric W. Biederman 		.proc_handler	= proc_ipc_doulongvec_minmax,
151a5494dcdSEric W. Biederman 	},
152a5494dcdSEric W. Biederman 	{
153a5494dcdSEric W. Biederman 		.procname	= "shmmni",
154a5494dcdSEric W. Biederman 		.data		= &init_ipc_ns.shm_ctlmni,
155a5494dcdSEric W. Biederman 		.maxlen		= sizeof(init_ipc_ns.shm_ctlmni),
156a5494dcdSEric W. Biederman 		.mode		= 0644,
1576730e658SWaiman Long 		.proc_handler	= proc_ipc_dointvec_minmax,
158eec4844fSMatteo Croce 		.extra1		= SYSCTL_ZERO,
1596730e658SWaiman Long 		.extra2		= &ipc_mni,
160a5494dcdSEric W. Biederman 	},
161a5494dcdSEric W. Biederman 	{
162b34a6b1dSVasiliy Kulikov 		.procname	= "shm_rmid_forced",
163b34a6b1dSVasiliy Kulikov 		.data		= &init_ipc_ns.shm_rmid_forced,
164b34a6b1dSVasiliy Kulikov 		.maxlen		= sizeof(init_ipc_ns.shm_rmid_forced),
165b34a6b1dSVasiliy Kulikov 		.mode		= 0644,
166b34a6b1dSVasiliy Kulikov 		.proc_handler	= proc_ipc_dointvec_minmax_orphans,
167eec4844fSMatteo Croce 		.extra1		= SYSCTL_ZERO,
168eec4844fSMatteo Croce 		.extra2		= SYSCTL_ONE,
169b34a6b1dSVasiliy Kulikov 	},
170b34a6b1dSVasiliy Kulikov 	{
171a5494dcdSEric W. Biederman 		.procname	= "msgmax",
172a5494dcdSEric W. Biederman 		.data		= &init_ipc_ns.msg_ctlmax,
173a5494dcdSEric W. Biederman 		.maxlen		= sizeof(init_ipc_ns.msg_ctlmax),
174a5494dcdSEric W. Biederman 		.mode		= 0644,
1759bf76ca3SMathias Krause 		.proc_handler	= proc_ipc_dointvec_minmax,
176eec4844fSMatteo Croce 		.extra1		= SYSCTL_ZERO,
177eec4844fSMatteo Croce 		.extra2		= SYSCTL_INT_MAX,
178a5494dcdSEric W. Biederman 	},
179a5494dcdSEric W. Biederman 	{
180a5494dcdSEric W. Biederman 		.procname	= "msgmni",
181a5494dcdSEric W. Biederman 		.data		= &init_ipc_ns.msg_ctlmni,
182a5494dcdSEric W. Biederman 		.maxlen		= sizeof(init_ipc_ns.msg_ctlmni),
183a5494dcdSEric W. Biederman 		.mode		= 0644,
1840050ee05SManfred Spraul 		.proc_handler	= proc_ipc_dointvec_minmax,
185eec4844fSMatteo Croce 		.extra1		= SYSCTL_ZERO,
1866730e658SWaiman Long 		.extra2		= &ipc_mni,
187a5494dcdSEric W. Biederman 	},
188a5494dcdSEric W. Biederman 	{
1890050ee05SManfred Spraul 		.procname	= "auto_msgmni",
1900050ee05SManfred Spraul 		.data		= NULL,
1910050ee05SManfred Spraul 		.maxlen		= sizeof(int),
1920050ee05SManfred Spraul 		.mode		= 0644,
1930050ee05SManfred Spraul 		.proc_handler	= proc_ipc_auto_msgmni,
194eec4844fSMatteo Croce 		.extra1		= SYSCTL_ZERO,
195eec4844fSMatteo Croce 		.extra2		= SYSCTL_ONE,
1960050ee05SManfred Spraul 	},
1970050ee05SManfred Spraul 	{
198a5494dcdSEric W. Biederman 		.procname	=  "msgmnb",
199a5494dcdSEric W. Biederman 		.data		= &init_ipc_ns.msg_ctlmnb,
200a5494dcdSEric W. Biederman 		.maxlen		= sizeof(init_ipc_ns.msg_ctlmnb),
201a5494dcdSEric W. Biederman 		.mode		= 0644,
2029bf76ca3SMathias Krause 		.proc_handler	= proc_ipc_dointvec_minmax,
203eec4844fSMatteo Croce 		.extra1		= SYSCTL_ZERO,
204eec4844fSMatteo Croce 		.extra2		= SYSCTL_INT_MAX,
205a5494dcdSEric W. Biederman 	},
206a5494dcdSEric W. Biederman 	{
207a5494dcdSEric W. Biederman 		.procname	= "sem",
208a5494dcdSEric W. Biederman 		.data		= &init_ipc_ns.sem_ctls,
209a5494dcdSEric W. Biederman 		.maxlen		= 4*sizeof(int),
210a5494dcdSEric W. Biederman 		.mode		= 0644,
2118c81ddd2SWaiman Long 		.proc_handler	= proc_ipc_sem_dointvec,
212a5494dcdSEric W. Biederman 	},
21303f59566SStanislav Kinsbursky #ifdef CONFIG_CHECKPOINT_RESTORE
21403f59566SStanislav Kinsbursky 	{
21503f59566SStanislav Kinsbursky 		.procname	= "sem_next_id",
21603f59566SStanislav Kinsbursky 		.data		= &init_ipc_ns.ids[IPC_SEM_IDS].next_id,
21703f59566SStanislav Kinsbursky 		.maxlen		= sizeof(init_ipc_ns.ids[IPC_SEM_IDS].next_id),
218*5563cabdSMichal Clapinski 		.mode		= 0666,
219*5563cabdSMichal Clapinski 		.proc_handler	= proc_ipc_dointvec_minmax_checkpoint_restore,
220eec4844fSMatteo Croce 		.extra1		= SYSCTL_ZERO,
221eec4844fSMatteo Croce 		.extra2		= SYSCTL_INT_MAX,
22203f59566SStanislav Kinsbursky 	},
22303f59566SStanislav Kinsbursky 	{
22403f59566SStanislav Kinsbursky 		.procname	= "msg_next_id",
22503f59566SStanislav Kinsbursky 		.data		= &init_ipc_ns.ids[IPC_MSG_IDS].next_id,
22603f59566SStanislav Kinsbursky 		.maxlen		= sizeof(init_ipc_ns.ids[IPC_MSG_IDS].next_id),
227*5563cabdSMichal Clapinski 		.mode		= 0666,
228*5563cabdSMichal Clapinski 		.proc_handler	= proc_ipc_dointvec_minmax_checkpoint_restore,
229eec4844fSMatteo Croce 		.extra1		= SYSCTL_ZERO,
230eec4844fSMatteo Croce 		.extra2		= SYSCTL_INT_MAX,
23103f59566SStanislav Kinsbursky 	},
23203f59566SStanislav Kinsbursky 	{
23303f59566SStanislav Kinsbursky 		.procname	= "shm_next_id",
23403f59566SStanislav Kinsbursky 		.data		= &init_ipc_ns.ids[IPC_SHM_IDS].next_id,
23503f59566SStanislav Kinsbursky 		.maxlen		= sizeof(init_ipc_ns.ids[IPC_SHM_IDS].next_id),
236*5563cabdSMichal Clapinski 		.mode		= 0666,
237*5563cabdSMichal Clapinski 		.proc_handler	= proc_ipc_dointvec_minmax_checkpoint_restore,
238eec4844fSMatteo Croce 		.extra1		= SYSCTL_ZERO,
239eec4844fSMatteo Croce 		.extra2		= SYSCTL_INT_MAX,
24003f59566SStanislav Kinsbursky 	},
24103f59566SStanislav Kinsbursky #endif
242a5494dcdSEric W. Biederman 	{}
243a5494dcdSEric W. Biederman };
244a5494dcdSEric W. Biederman 
245a5494dcdSEric W. Biederman static struct ctl_table ipc_root_table[] = {
246a5494dcdSEric W. Biederman 	{
247a5494dcdSEric W. Biederman 		.procname	= "kernel",
248a5494dcdSEric W. Biederman 		.mode		= 0555,
249a5494dcdSEric W. Biederman 		.child		= ipc_kern_table,
250a5494dcdSEric W. Biederman 	},
251a5494dcdSEric W. Biederman 	{}
252a5494dcdSEric W. Biederman };
253a5494dcdSEric W. Biederman 
254a5494dcdSEric W. Biederman static int __init ipc_sysctl_init(void)
255a5494dcdSEric W. Biederman {
2560b4d4147SEric W. Biederman 	register_sysctl_table(ipc_root_table);
257a5494dcdSEric W. Biederman 	return 0;
258a5494dcdSEric W. Biederman }
259a5494dcdSEric W. Biederman 
2606d08a256SDavidlohr Bueso device_initcall(ipc_sysctl_init);
2615ac893b8SWaiman Long 
2625ac893b8SWaiman Long static int __init ipc_mni_extend(char *str)
2635ac893b8SWaiman Long {
2645ac893b8SWaiman Long 	ipc_mni = IPCMNI_EXTEND;
2655ac893b8SWaiman Long 	ipc_mni_shift = IPCMNI_EXTEND_SHIFT;
26699db46eaSManfred Spraul 	ipc_min_cycle = IPCMNI_EXTEND_MIN_CYCLE;
2675ac893b8SWaiman Long 	pr_info("IPCMNI extended to %d.\n", ipc_mni);
2685ac893b8SWaiman Long 	return 0;
2695ac893b8SWaiman Long }
2705ac893b8SWaiman Long early_param("ipcmni_extend", ipc_mni_extend);
271