xref: /openbmc/linux/ipc/ipc_sysctl.c (revision a5494dcd8b92dce64317f2f7dd0d62747c54980b)
1*a5494dcdSEric W. Biederman /*
2*a5494dcdSEric W. Biederman  *  Copyright (C) 2007
3*a5494dcdSEric W. Biederman  *
4*a5494dcdSEric W. Biederman  *  Author: Eric Biederman <ebiederm@xmision.com>
5*a5494dcdSEric W. Biederman  *
6*a5494dcdSEric W. Biederman  *  This program is free software; you can redistribute it and/or
7*a5494dcdSEric W. Biederman  *  modify it under the terms of the GNU General Public License as
8*a5494dcdSEric W. Biederman  *  published by the Free Software Foundation, version 2 of the
9*a5494dcdSEric W. Biederman  *  License.
10*a5494dcdSEric W. Biederman  */
11*a5494dcdSEric W. Biederman 
12*a5494dcdSEric W. Biederman #include <linux/module.h>
13*a5494dcdSEric W. Biederman #include <linux/ipc.h>
14*a5494dcdSEric W. Biederman #include <linux/nsproxy.h>
15*a5494dcdSEric W. Biederman #include <linux/sysctl.h>
16*a5494dcdSEric W. Biederman #include <linux/uaccess.h>
17*a5494dcdSEric W. Biederman 
18*a5494dcdSEric W. Biederman #ifdef CONFIG_IPC_NS
19*a5494dcdSEric W. Biederman static void *get_ipc(ctl_table *table)
20*a5494dcdSEric W. Biederman {
21*a5494dcdSEric W. Biederman 	char *which = table->data;
22*a5494dcdSEric W. Biederman 	struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns;
23*a5494dcdSEric W. Biederman 	which = (which - (char *)&init_ipc_ns) + (char *)ipc_ns;
24*a5494dcdSEric W. Biederman 	return which;
25*a5494dcdSEric W. Biederman }
26*a5494dcdSEric W. Biederman #else
27*a5494dcdSEric W. Biederman #define get_ipc(T) ((T)->data)
28*a5494dcdSEric W. Biederman #endif
29*a5494dcdSEric W. Biederman 
30*a5494dcdSEric W. Biederman #ifdef CONFIG_PROC_FS
31*a5494dcdSEric W. Biederman static int proc_ipc_dointvec(ctl_table *table, int write, struct file *filp,
32*a5494dcdSEric W. Biederman 	void __user *buffer, size_t *lenp, loff_t *ppos)
33*a5494dcdSEric W. Biederman {
34*a5494dcdSEric W. Biederman 	struct ctl_table ipc_table;
35*a5494dcdSEric W. Biederman 	memcpy(&ipc_table, table, sizeof(ipc_table));
36*a5494dcdSEric W. Biederman 	ipc_table.data = get_ipc(table);
37*a5494dcdSEric W. Biederman 
38*a5494dcdSEric W. Biederman 	return proc_dointvec(&ipc_table, write, filp, buffer, lenp, ppos);
39*a5494dcdSEric W. Biederman }
40*a5494dcdSEric W. Biederman 
41*a5494dcdSEric W. Biederman static int proc_ipc_doulongvec_minmax(ctl_table *table, int write,
42*a5494dcdSEric W. Biederman 	struct file *filp, void __user *buffer, size_t *lenp, loff_t *ppos)
43*a5494dcdSEric W. Biederman {
44*a5494dcdSEric W. Biederman 	struct ctl_table ipc_table;
45*a5494dcdSEric W. Biederman 	memcpy(&ipc_table, table, sizeof(ipc_table));
46*a5494dcdSEric W. Biederman 	ipc_table.data = get_ipc(table);
47*a5494dcdSEric W. Biederman 
48*a5494dcdSEric W. Biederman 	return proc_doulongvec_minmax(&ipc_table, write, filp, buffer,
49*a5494dcdSEric W. Biederman 					lenp, ppos);
50*a5494dcdSEric W. Biederman }
51*a5494dcdSEric W. Biederman 
52*a5494dcdSEric W. Biederman #else
53*a5494dcdSEric W. Biederman #define proc_ipc_doulongvec_minmax NULL
54*a5494dcdSEric W. Biederman #define proc_ipc_dointvec	   NULL
55*a5494dcdSEric W. Biederman #endif
56*a5494dcdSEric W. Biederman 
57*a5494dcdSEric W. Biederman #ifdef CONFIG_SYSCTL_SYSCALL
58*a5494dcdSEric W. Biederman /* The generic sysctl ipc data routine. */
59*a5494dcdSEric W. Biederman static int sysctl_ipc_data(ctl_table *table, int __user *name, int nlen,
60*a5494dcdSEric W. Biederman 		void __user *oldval, size_t __user *oldlenp,
61*a5494dcdSEric W. Biederman 		void __user *newval, size_t newlen)
62*a5494dcdSEric W. Biederman {
63*a5494dcdSEric W. Biederman 	size_t len;
64*a5494dcdSEric W. Biederman 	void *data;
65*a5494dcdSEric W. Biederman 
66*a5494dcdSEric W. Biederman 	/* Get out of I don't have a variable */
67*a5494dcdSEric W. Biederman 	if (!table->data || !table->maxlen)
68*a5494dcdSEric W. Biederman 		return -ENOTDIR;
69*a5494dcdSEric W. Biederman 
70*a5494dcdSEric W. Biederman 	data = get_ipc(table);
71*a5494dcdSEric W. Biederman 	if (!data)
72*a5494dcdSEric W. Biederman 		return -ENOTDIR;
73*a5494dcdSEric W. Biederman 
74*a5494dcdSEric W. Biederman 	if (oldval && oldlenp) {
75*a5494dcdSEric W. Biederman 		if (get_user(len, oldlenp))
76*a5494dcdSEric W. Biederman 			return -EFAULT;
77*a5494dcdSEric W. Biederman 		if (len) {
78*a5494dcdSEric W. Biederman 			if (len > table->maxlen)
79*a5494dcdSEric W. Biederman 				len = table->maxlen;
80*a5494dcdSEric W. Biederman 			if (copy_to_user(oldval, data, len))
81*a5494dcdSEric W. Biederman 				return -EFAULT;
82*a5494dcdSEric W. Biederman 			if (put_user(len, oldlenp))
83*a5494dcdSEric W. Biederman 				return -EFAULT;
84*a5494dcdSEric W. Biederman 		}
85*a5494dcdSEric W. Biederman 	}
86*a5494dcdSEric W. Biederman 
87*a5494dcdSEric W. Biederman 	if (newval && newlen) {
88*a5494dcdSEric W. Biederman 		if (newlen > table->maxlen)
89*a5494dcdSEric W. Biederman 			newlen = table->maxlen;
90*a5494dcdSEric W. Biederman 
91*a5494dcdSEric W. Biederman 		if (copy_from_user(data, newval, newlen))
92*a5494dcdSEric W. Biederman 			return -EFAULT;
93*a5494dcdSEric W. Biederman 	}
94*a5494dcdSEric W. Biederman 	return 1;
95*a5494dcdSEric W. Biederman }
96*a5494dcdSEric W. Biederman #else
97*a5494dcdSEric W. Biederman #define sysctl_ipc_data NULL
98*a5494dcdSEric W. Biederman #endif
99*a5494dcdSEric W. Biederman 
100*a5494dcdSEric W. Biederman static struct ctl_table ipc_kern_table[] = {
101*a5494dcdSEric W. Biederman 	{
102*a5494dcdSEric W. Biederman 		.ctl_name	= KERN_SHMMAX,
103*a5494dcdSEric W. Biederman 		.procname	= "shmmax",
104*a5494dcdSEric W. Biederman 		.data		= &init_ipc_ns.shm_ctlmax,
105*a5494dcdSEric W. Biederman 		.maxlen		= sizeof (init_ipc_ns.shm_ctlmax),
106*a5494dcdSEric W. Biederman 		.mode		= 0644,
107*a5494dcdSEric W. Biederman 		.proc_handler	= proc_ipc_doulongvec_minmax,
108*a5494dcdSEric W. Biederman 		.strategy	= sysctl_ipc_data,
109*a5494dcdSEric W. Biederman 	},
110*a5494dcdSEric W. Biederman 	{
111*a5494dcdSEric W. Biederman 		.ctl_name	= KERN_SHMALL,
112*a5494dcdSEric W. Biederman 		.procname	= "shmall",
113*a5494dcdSEric W. Biederman 		.data		= &init_ipc_ns.shm_ctlall,
114*a5494dcdSEric W. Biederman 		.maxlen		= sizeof (init_ipc_ns.shm_ctlall),
115*a5494dcdSEric W. Biederman 		.mode		= 0644,
116*a5494dcdSEric W. Biederman 		.proc_handler	= proc_ipc_doulongvec_minmax,
117*a5494dcdSEric W. Biederman 		.strategy	= sysctl_ipc_data,
118*a5494dcdSEric W. Biederman 	},
119*a5494dcdSEric W. Biederman 	{
120*a5494dcdSEric W. Biederman 		.ctl_name	= KERN_SHMMNI,
121*a5494dcdSEric W. Biederman 		.procname	= "shmmni",
122*a5494dcdSEric W. Biederman 		.data		= &init_ipc_ns.shm_ctlmni,
123*a5494dcdSEric W. Biederman 		.maxlen		= sizeof (init_ipc_ns.shm_ctlmni),
124*a5494dcdSEric W. Biederman 		.mode		= 0644,
125*a5494dcdSEric W. Biederman 		.proc_handler	= proc_ipc_dointvec,
126*a5494dcdSEric W. Biederman 		.strategy	= sysctl_ipc_data,
127*a5494dcdSEric W. Biederman 	},
128*a5494dcdSEric W. Biederman 	{
129*a5494dcdSEric W. Biederman 		.ctl_name	= KERN_MSGMAX,
130*a5494dcdSEric W. Biederman 		.procname	= "msgmax",
131*a5494dcdSEric W. Biederman 		.data		= &init_ipc_ns.msg_ctlmax,
132*a5494dcdSEric W. Biederman 		.maxlen		= sizeof (init_ipc_ns.msg_ctlmax),
133*a5494dcdSEric W. Biederman 		.mode		= 0644,
134*a5494dcdSEric W. Biederman 		.proc_handler	= proc_ipc_dointvec,
135*a5494dcdSEric W. Biederman 		.strategy	= sysctl_ipc_data,
136*a5494dcdSEric W. Biederman 	},
137*a5494dcdSEric W. Biederman 	{
138*a5494dcdSEric W. Biederman 		.ctl_name	= KERN_MSGMNI,
139*a5494dcdSEric W. Biederman 		.procname	= "msgmni",
140*a5494dcdSEric W. Biederman 		.data		= &init_ipc_ns.msg_ctlmni,
141*a5494dcdSEric W. Biederman 		.maxlen		= sizeof (init_ipc_ns.msg_ctlmni),
142*a5494dcdSEric W. Biederman 		.mode		= 0644,
143*a5494dcdSEric W. Biederman 		.proc_handler	= proc_ipc_dointvec,
144*a5494dcdSEric W. Biederman 		.strategy	= sysctl_ipc_data,
145*a5494dcdSEric W. Biederman 	},
146*a5494dcdSEric W. Biederman 	{
147*a5494dcdSEric W. Biederman 		.ctl_name	= KERN_MSGMNB,
148*a5494dcdSEric W. Biederman 		.procname	=  "msgmnb",
149*a5494dcdSEric W. Biederman 		.data		= &init_ipc_ns.msg_ctlmnb,
150*a5494dcdSEric W. Biederman 		.maxlen		= sizeof (init_ipc_ns.msg_ctlmnb),
151*a5494dcdSEric W. Biederman 		.mode		= 0644,
152*a5494dcdSEric W. Biederman 		.proc_handler	= proc_ipc_dointvec,
153*a5494dcdSEric W. Biederman 		.strategy	= sysctl_ipc_data,
154*a5494dcdSEric W. Biederman 	},
155*a5494dcdSEric W. Biederman 	{
156*a5494dcdSEric W. Biederman 		.ctl_name	= KERN_SEM,
157*a5494dcdSEric W. Biederman 		.procname	= "sem",
158*a5494dcdSEric W. Biederman 		.data		= &init_ipc_ns.sem_ctls,
159*a5494dcdSEric W. Biederman 		.maxlen		= 4*sizeof (int),
160*a5494dcdSEric W. Biederman 		.mode		= 0644,
161*a5494dcdSEric W. Biederman 		.proc_handler	= proc_ipc_dointvec,
162*a5494dcdSEric W. Biederman 		.strategy	= sysctl_ipc_data,
163*a5494dcdSEric W. Biederman 	},
164*a5494dcdSEric W. Biederman 	{}
165*a5494dcdSEric W. Biederman };
166*a5494dcdSEric W. Biederman 
167*a5494dcdSEric W. Biederman static struct ctl_table ipc_root_table[] = {
168*a5494dcdSEric W. Biederman 	{
169*a5494dcdSEric W. Biederman 		.ctl_name	= CTL_KERN,
170*a5494dcdSEric W. Biederman 		.procname	= "kernel",
171*a5494dcdSEric W. Biederman 		.mode		= 0555,
172*a5494dcdSEric W. Biederman 		.child		= ipc_kern_table,
173*a5494dcdSEric W. Biederman 	},
174*a5494dcdSEric W. Biederman 	{}
175*a5494dcdSEric W. Biederman };
176*a5494dcdSEric W. Biederman 
177*a5494dcdSEric W. Biederman static int __init ipc_sysctl_init(void)
178*a5494dcdSEric W. Biederman {
179*a5494dcdSEric W. Biederman 	register_sysctl_table(ipc_root_table, 0);
180*a5494dcdSEric W. Biederman 	return 0;
181*a5494dcdSEric W. Biederman }
182*a5494dcdSEric W. Biederman 
183*a5494dcdSEric W. Biederman __initcall(ipc_sysctl_init);
184