xref: /openbmc/linux/ipc/ipc_sysctl.c (revision 5ac893b8cb10fe2a47a77780d37f9bf5b142854b)
1a5494dcdSEric W. Biederman /*
2a5494dcdSEric W. Biederman  *  Copyright (C) 2007
3a5494dcdSEric W. Biederman  *
4a5494dcdSEric W. Biederman  *  Author: Eric Biederman <ebiederm@xmision.com>
5a5494dcdSEric W. Biederman  *
6a5494dcdSEric W. Biederman  *  This program is free software; you can redistribute it and/or
7a5494dcdSEric W. Biederman  *  modify it under the terms of the GNU General Public License as
8a5494dcdSEric W. Biederman  *  published by the Free Software Foundation, version 2 of the
9a5494dcdSEric W. Biederman  *  License.
10a5494dcdSEric W. Biederman  */
11a5494dcdSEric W. Biederman 
12a5494dcdSEric W. Biederman #include <linux/module.h>
13a5494dcdSEric W. Biederman #include <linux/ipc.h>
14a5494dcdSEric W. Biederman #include <linux/nsproxy.h>
15a5494dcdSEric W. Biederman #include <linux/sysctl.h>
16a5494dcdSEric W. Biederman #include <linux/uaccess.h>
17ae5e1b22SPavel Emelyanov #include <linux/ipc_namespace.h>
186546bc42SNadia Derbey #include <linux/msg.h>
196546bc42SNadia Derbey #include "util.h"
20a5494dcdSEric W. Biederman 
21a5c5928bSJoe Perches static void *get_ipc(struct ctl_table *table)
22a5494dcdSEric W. Biederman {
23a5494dcdSEric W. Biederman 	char *which = table->data;
24a5494dcdSEric W. Biederman 	struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns;
25a5494dcdSEric W. Biederman 	which = (which - (char *)&init_ipc_ns) + (char *)ipc_ns;
26a5494dcdSEric W. Biederman 	return which;
27a5494dcdSEric W. Biederman }
28a5494dcdSEric W. Biederman 
2911dea190SSerge E. Hallyn #ifdef CONFIG_PROC_SYSCTL
30a5c5928bSJoe Perches static int proc_ipc_dointvec(struct ctl_table *table, int write,
31a5494dcdSEric W. Biederman 	void __user *buffer, size_t *lenp, loff_t *ppos)
32a5494dcdSEric W. Biederman {
33a5494dcdSEric W. Biederman 	struct ctl_table ipc_table;
34b34a6b1dSVasiliy Kulikov 
35a5494dcdSEric W. Biederman 	memcpy(&ipc_table, table, sizeof(ipc_table));
36a5494dcdSEric W. Biederman 	ipc_table.data = get_ipc(table);
37a5494dcdSEric W. Biederman 
388d65af78SAlexey Dobriyan 	return proc_dointvec(&ipc_table, write, buffer, lenp, ppos);
39a5494dcdSEric W. Biederman }
40a5494dcdSEric W. Biederman 
41a5c5928bSJoe Perches static int proc_ipc_dointvec_minmax(struct ctl_table *table, int write,
42b34a6b1dSVasiliy Kulikov 	void __user *buffer, size_t *lenp, loff_t *ppos)
43b34a6b1dSVasiliy Kulikov {
44b34a6b1dSVasiliy Kulikov 	struct ctl_table ipc_table;
45b34a6b1dSVasiliy Kulikov 
46b34a6b1dSVasiliy Kulikov 	memcpy(&ipc_table, table, sizeof(ipc_table));
47b34a6b1dSVasiliy Kulikov 	ipc_table.data = get_ipc(table);
48b34a6b1dSVasiliy Kulikov 
49b34a6b1dSVasiliy Kulikov 	return proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos);
50b34a6b1dSVasiliy Kulikov }
51b34a6b1dSVasiliy Kulikov 
52a5c5928bSJoe Perches static int proc_ipc_dointvec_minmax_orphans(struct ctl_table *table, int write,
53b34a6b1dSVasiliy Kulikov 	void __user *buffer, size_t *lenp, loff_t *ppos)
54b34a6b1dSVasiliy Kulikov {
55b34a6b1dSVasiliy Kulikov 	struct ipc_namespace *ns = current->nsproxy->ipc_ns;
56b34a6b1dSVasiliy Kulikov 	int err = proc_ipc_dointvec_minmax(table, write, buffer, lenp, ppos);
57b34a6b1dSVasiliy Kulikov 
58b34a6b1dSVasiliy Kulikov 	if (err < 0)
59b34a6b1dSVasiliy Kulikov 		return err;
60b34a6b1dSVasiliy Kulikov 	if (ns->shm_rmid_forced)
61b34a6b1dSVasiliy Kulikov 		shm_destroy_orphaned(ns);
62b34a6b1dSVasiliy Kulikov 	return err;
63b34a6b1dSVasiliy Kulikov }
64b34a6b1dSVasiliy Kulikov 
65a5c5928bSJoe Perches static int proc_ipc_doulongvec_minmax(struct ctl_table *table, int write,
668d65af78SAlexey Dobriyan 	void __user *buffer, size_t *lenp, loff_t *ppos)
67a5494dcdSEric W. Biederman {
68a5494dcdSEric W. Biederman 	struct ctl_table ipc_table;
69a5494dcdSEric W. Biederman 	memcpy(&ipc_table, table, sizeof(ipc_table));
70a5494dcdSEric W. Biederman 	ipc_table.data = get_ipc(table);
71a5494dcdSEric W. Biederman 
728d65af78SAlexey Dobriyan 	return proc_doulongvec_minmax(&ipc_table, write, buffer,
73a5494dcdSEric W. Biederman 					lenp, ppos);
74a5494dcdSEric W. Biederman }
75a5494dcdSEric W. Biederman 
760050ee05SManfred Spraul static int proc_ipc_auto_msgmni(struct ctl_table *table, int write,
778d65af78SAlexey Dobriyan 	void __user *buffer, size_t *lenp, loff_t *ppos)
789eefe520SNadia Derbey {
799eefe520SNadia Derbey 	struct ctl_table ipc_table;
800050ee05SManfred Spraul 	int dummy = 0;
819eefe520SNadia Derbey 
829eefe520SNadia Derbey 	memcpy(&ipc_table, table, sizeof(ipc_table));
830050ee05SManfred Spraul 	ipc_table.data = &dummy;
849eefe520SNadia Derbey 
850050ee05SManfred Spraul 	if (write)
860050ee05SManfred Spraul 		pr_info_once("writing to auto_msgmni has no effect");
879eefe520SNadia Derbey 
880050ee05SManfred Spraul 	return proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos);
899eefe520SNadia Derbey }
909eefe520SNadia Derbey 
918c81ddd2SWaiman Long static int proc_ipc_sem_dointvec(struct ctl_table *table, int write,
928c81ddd2SWaiman Long 	void __user *buffer, size_t *lenp, loff_t *ppos)
938c81ddd2SWaiman Long {
948c81ddd2SWaiman Long 	int ret, semmni;
958c81ddd2SWaiman Long 	struct ipc_namespace *ns = current->nsproxy->ipc_ns;
968c81ddd2SWaiman Long 
978c81ddd2SWaiman Long 	semmni = ns->sem_ctls[3];
988c81ddd2SWaiman Long 	ret = proc_ipc_dointvec(table, write, buffer, lenp, ppos);
998c81ddd2SWaiman Long 
1008c81ddd2SWaiman Long 	if (!ret)
1018c81ddd2SWaiman Long 		ret = sem_check_semmni(current->nsproxy->ipc_ns);
1028c81ddd2SWaiman Long 
1038c81ddd2SWaiman Long 	/*
1048c81ddd2SWaiman Long 	 * Reset the semmni value if an error happens.
1058c81ddd2SWaiman Long 	 */
1068c81ddd2SWaiman Long 	if (ret)
1078c81ddd2SWaiman Long 		ns->sem_ctls[3] = semmni;
1088c81ddd2SWaiman Long 	return ret;
1098c81ddd2SWaiman Long }
1108c81ddd2SWaiman Long 
111a5494dcdSEric W. Biederman #else
112a5494dcdSEric W. Biederman #define proc_ipc_doulongvec_minmax NULL
113a5494dcdSEric W. Biederman #define proc_ipc_dointvec	   NULL
114b34a6b1dSVasiliy Kulikov #define proc_ipc_dointvec_minmax   NULL
115b34a6b1dSVasiliy Kulikov #define proc_ipc_dointvec_minmax_orphans   NULL
1160050ee05SManfred Spraul #define proc_ipc_auto_msgmni	   NULL
1178c81ddd2SWaiman Long #define proc_ipc_sem_dointvec	   NULL
118a5494dcdSEric W. Biederman #endif
119a5494dcdSEric W. Biederman 
1209eefe520SNadia Derbey static int zero;
1219eefe520SNadia Derbey static int one = 1;
12203f59566SStanislav Kinsbursky static int int_max = INT_MAX;
123*5ac893b8SWaiman Long int ipc_mni = IPCMNI;
124*5ac893b8SWaiman Long int ipc_mni_shift = IPCMNI_SHIFT;
1259eefe520SNadia Derbey 
126a5494dcdSEric W. Biederman static struct ctl_table ipc_kern_table[] = {
127a5494dcdSEric W. Biederman 	{
128a5494dcdSEric W. Biederman 		.procname	= "shmmax",
129a5494dcdSEric W. Biederman 		.data		= &init_ipc_ns.shm_ctlmax,
130a5494dcdSEric W. Biederman 		.maxlen		= sizeof(init_ipc_ns.shm_ctlmax),
131a5494dcdSEric W. Biederman 		.mode		= 0644,
132a5494dcdSEric W. Biederman 		.proc_handler	= proc_ipc_doulongvec_minmax,
133a5494dcdSEric W. Biederman 	},
134a5494dcdSEric W. Biederman 	{
135a5494dcdSEric W. Biederman 		.procname	= "shmall",
136a5494dcdSEric W. Biederman 		.data		= &init_ipc_ns.shm_ctlall,
137a5494dcdSEric W. Biederman 		.maxlen		= sizeof(init_ipc_ns.shm_ctlall),
138a5494dcdSEric W. Biederman 		.mode		= 0644,
139a5494dcdSEric W. Biederman 		.proc_handler	= proc_ipc_doulongvec_minmax,
140a5494dcdSEric W. Biederman 	},
141a5494dcdSEric W. Biederman 	{
142a5494dcdSEric W. Biederman 		.procname	= "shmmni",
143a5494dcdSEric W. Biederman 		.data		= &init_ipc_ns.shm_ctlmni,
144a5494dcdSEric W. Biederman 		.maxlen		= sizeof(init_ipc_ns.shm_ctlmni),
145a5494dcdSEric W. Biederman 		.mode		= 0644,
1466730e658SWaiman Long 		.proc_handler	= proc_ipc_dointvec_minmax,
1476730e658SWaiman Long 		.extra1		= &zero,
1486730e658SWaiman Long 		.extra2		= &ipc_mni,
149a5494dcdSEric W. Biederman 	},
150a5494dcdSEric W. Biederman 	{
151b34a6b1dSVasiliy Kulikov 		.procname	= "shm_rmid_forced",
152b34a6b1dSVasiliy Kulikov 		.data		= &init_ipc_ns.shm_rmid_forced,
153b34a6b1dSVasiliy Kulikov 		.maxlen		= sizeof(init_ipc_ns.shm_rmid_forced),
154b34a6b1dSVasiliy Kulikov 		.mode		= 0644,
155b34a6b1dSVasiliy Kulikov 		.proc_handler	= proc_ipc_dointvec_minmax_orphans,
156b34a6b1dSVasiliy Kulikov 		.extra1		= &zero,
157b34a6b1dSVasiliy Kulikov 		.extra2		= &one,
158b34a6b1dSVasiliy Kulikov 	},
159b34a6b1dSVasiliy Kulikov 	{
160a5494dcdSEric W. Biederman 		.procname	= "msgmax",
161a5494dcdSEric W. Biederman 		.data		= &init_ipc_ns.msg_ctlmax,
162a5494dcdSEric W. Biederman 		.maxlen		= sizeof(init_ipc_ns.msg_ctlmax),
163a5494dcdSEric W. Biederman 		.mode		= 0644,
1649bf76ca3SMathias Krause 		.proc_handler	= proc_ipc_dointvec_minmax,
1659bf76ca3SMathias Krause 		.extra1		= &zero,
1669bf76ca3SMathias Krause 		.extra2		= &int_max,
167a5494dcdSEric W. Biederman 	},
168a5494dcdSEric W. Biederman 	{
169a5494dcdSEric W. Biederman 		.procname	= "msgmni",
170a5494dcdSEric W. Biederman 		.data		= &init_ipc_ns.msg_ctlmni,
171a5494dcdSEric W. Biederman 		.maxlen		= sizeof(init_ipc_ns.msg_ctlmni),
172a5494dcdSEric W. Biederman 		.mode		= 0644,
1730050ee05SManfred Spraul 		.proc_handler	= proc_ipc_dointvec_minmax,
1749bf76ca3SMathias Krause 		.extra1		= &zero,
1756730e658SWaiman Long 		.extra2		= &ipc_mni,
176a5494dcdSEric W. Biederman 	},
177a5494dcdSEric W. Biederman 	{
1780050ee05SManfred Spraul 		.procname	= "auto_msgmni",
1790050ee05SManfred Spraul 		.data		= NULL,
1800050ee05SManfred Spraul 		.maxlen		= sizeof(int),
1810050ee05SManfred Spraul 		.mode		= 0644,
1820050ee05SManfred Spraul 		.proc_handler	= proc_ipc_auto_msgmni,
1830050ee05SManfred Spraul 		.extra1		= &zero,
1840050ee05SManfred Spraul 		.extra2		= &one,
1850050ee05SManfred Spraul 	},
1860050ee05SManfred Spraul 	{
187a5494dcdSEric W. Biederman 		.procname	=  "msgmnb",
188a5494dcdSEric W. Biederman 		.data		= &init_ipc_ns.msg_ctlmnb,
189a5494dcdSEric W. Biederman 		.maxlen		= sizeof(init_ipc_ns.msg_ctlmnb),
190a5494dcdSEric W. Biederman 		.mode		= 0644,
1919bf76ca3SMathias Krause 		.proc_handler	= proc_ipc_dointvec_minmax,
1929bf76ca3SMathias Krause 		.extra1		= &zero,
1939bf76ca3SMathias Krause 		.extra2		= &int_max,
194a5494dcdSEric W. Biederman 	},
195a5494dcdSEric W. Biederman 	{
196a5494dcdSEric W. Biederman 		.procname	= "sem",
197a5494dcdSEric W. Biederman 		.data		= &init_ipc_ns.sem_ctls,
198a5494dcdSEric W. Biederman 		.maxlen		= 4*sizeof(int),
199a5494dcdSEric W. Biederman 		.mode		= 0644,
2008c81ddd2SWaiman Long 		.proc_handler	= proc_ipc_sem_dointvec,
201a5494dcdSEric W. Biederman 	},
20203f59566SStanislav Kinsbursky #ifdef CONFIG_CHECKPOINT_RESTORE
20303f59566SStanislav Kinsbursky 	{
20403f59566SStanislav Kinsbursky 		.procname	= "sem_next_id",
20503f59566SStanislav Kinsbursky 		.data		= &init_ipc_ns.ids[IPC_SEM_IDS].next_id,
20603f59566SStanislav Kinsbursky 		.maxlen		= sizeof(init_ipc_ns.ids[IPC_SEM_IDS].next_id),
20703f59566SStanislav Kinsbursky 		.mode		= 0644,
20803f59566SStanislav Kinsbursky 		.proc_handler	= proc_ipc_dointvec_minmax,
20903f59566SStanislav Kinsbursky 		.extra1		= &zero,
21003f59566SStanislav Kinsbursky 		.extra2		= &int_max,
21103f59566SStanislav Kinsbursky 	},
21203f59566SStanislav Kinsbursky 	{
21303f59566SStanislav Kinsbursky 		.procname	= "msg_next_id",
21403f59566SStanislav Kinsbursky 		.data		= &init_ipc_ns.ids[IPC_MSG_IDS].next_id,
21503f59566SStanislav Kinsbursky 		.maxlen		= sizeof(init_ipc_ns.ids[IPC_MSG_IDS].next_id),
21603f59566SStanislav Kinsbursky 		.mode		= 0644,
21703f59566SStanislav Kinsbursky 		.proc_handler	= proc_ipc_dointvec_minmax,
21803f59566SStanislav Kinsbursky 		.extra1		= &zero,
21903f59566SStanislav Kinsbursky 		.extra2		= &int_max,
22003f59566SStanislav Kinsbursky 	},
22103f59566SStanislav Kinsbursky 	{
22203f59566SStanislav Kinsbursky 		.procname	= "shm_next_id",
22303f59566SStanislav Kinsbursky 		.data		= &init_ipc_ns.ids[IPC_SHM_IDS].next_id,
22403f59566SStanislav Kinsbursky 		.maxlen		= sizeof(init_ipc_ns.ids[IPC_SHM_IDS].next_id),
22503f59566SStanislav Kinsbursky 		.mode		= 0644,
22603f59566SStanislav Kinsbursky 		.proc_handler	= proc_ipc_dointvec_minmax,
22703f59566SStanislav Kinsbursky 		.extra1		= &zero,
22803f59566SStanislav Kinsbursky 		.extra2		= &int_max,
22903f59566SStanislav Kinsbursky 	},
23003f59566SStanislav Kinsbursky #endif
231a5494dcdSEric W. Biederman 	{}
232a5494dcdSEric W. Biederman };
233a5494dcdSEric W. Biederman 
234a5494dcdSEric W. Biederman static struct ctl_table ipc_root_table[] = {
235a5494dcdSEric W. Biederman 	{
236a5494dcdSEric W. Biederman 		.procname	= "kernel",
237a5494dcdSEric W. Biederman 		.mode		= 0555,
238a5494dcdSEric W. Biederman 		.child		= ipc_kern_table,
239a5494dcdSEric W. Biederman 	},
240a5494dcdSEric W. Biederman 	{}
241a5494dcdSEric W. Biederman };
242a5494dcdSEric W. Biederman 
243a5494dcdSEric W. Biederman static int __init ipc_sysctl_init(void)
244a5494dcdSEric W. Biederman {
2450b4d4147SEric W. Biederman 	register_sysctl_table(ipc_root_table);
246a5494dcdSEric W. Biederman 	return 0;
247a5494dcdSEric W. Biederman }
248a5494dcdSEric W. Biederman 
2496d08a256SDavidlohr Bueso device_initcall(ipc_sysctl_init);
250*5ac893b8SWaiman Long 
251*5ac893b8SWaiman Long static int __init ipc_mni_extend(char *str)
252*5ac893b8SWaiman Long {
253*5ac893b8SWaiman Long 	ipc_mni = IPCMNI_EXTEND;
254*5ac893b8SWaiman Long 	ipc_mni_shift = IPCMNI_EXTEND_SHIFT;
255*5ac893b8SWaiman Long 	pr_info("IPCMNI extended to %d.\n", ipc_mni);
256*5ac893b8SWaiman Long 	return 0;
257*5ac893b8SWaiman Long }
258*5ac893b8SWaiman Long early_param("ipcmni_extend", ipc_mni_extend);
259