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