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 Perchesstatic 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 Perchesstatic int proc_ipc_dointvec(struct ctl_table *table, int write,
2732927393SChristoph 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 Perchesstatic int proc_ipc_dointvec_minmax(struct ctl_table *table, int write,
3832927393SChristoph 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 Perchesstatic int proc_ipc_dointvec_minmax_orphans(struct ctl_table *table, int write,
4932927393SChristoph 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 Perchesstatic int proc_ipc_doulongvec_minmax(struct ctl_table *table, int write,
6232927393SChristoph 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 Spraulstatic int proc_ipc_auto_msgmni(struct ctl_table *table, int write,
7332927393SChristoph 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;
800050ee05SManfred Spraul
810050ee05SManfred Spraul	if (write)
820050ee05SManfred Spraul		pr_info_once("writing to auto_msgmni has no effect");
830050ee05SManfred Spraul
840050ee05SManfred Spraul	return proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos);
859eefe520SNadia Derbey}
869eefe520SNadia Derbey
878c81ddd2SWaiman Longstatic int proc_ipc_sem_dointvec(struct ctl_table *table, int write,
88fff1662cSTobias Klauser	void *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 Longint ipc_mni = IPCMNI;
1175ac893b8SWaiman Longint ipc_mni_shift = IPCMNI_SHIFT;
11899db46eaSManfred Spraulint ipc_min_cycle = RADIX_TREE_MAP_SIZE;
1199eefe520SNadia Derbey
120a5494dcdSEric W. Biedermanstatic struct ctl_table ipc_kern_table[] = {
121a5494dcdSEric W. Biederman	{
122a5494dcdSEric W. Biederman		.procname	= "shmmax",
123a5494dcdSEric W. Biederman		.data		= &init_ipc_ns.shm_ctlmax,
124239521f3SManfred Spraul		.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,
131239521f3SManfred Spraul		.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,
138239521f3SManfred Spraul		.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	},
144b34a6b1dSVasiliy Kulikov	{
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	},
153a5494dcdSEric W. Biederman	{
154a5494dcdSEric W. Biederman		.procname	= "msgmax",
155a5494dcdSEric W. Biederman		.data		= &init_ipc_ns.msg_ctlmax,
156239521f3SManfred Spraul		.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,
165239521f3SManfred Spraul		.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	},
1710050ee05SManfred Spraul	{
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	},
180a5494dcdSEric W. Biederman	{
181a5494dcdSEric W. Biederman		.procname	=  "msgmnb",
182a5494dcdSEric W. Biederman		.data		= &init_ipc_ns.msg_ctlmnb,
183239521f3SManfred Spraul		.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,
192239521f3SManfred Spraul		.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. Biedermanstatic 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. Biedermanstatic 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 Buesodevice_initcall(ipc_sysctl_init);
2445ac893b8SWaiman Long
2455ac893b8SWaiman Longstatic 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 Longearly_param("ipcmni_extend", ipc_mni_extend);
254