1/*
2 *  Copyright (C) 2007 IBM Corporation
3 *
4 *  Author: Cedric Le Goater <clg@fr.ibm.com>
5 *
6 *  This program is free software; you can redistribute it and/or
7 *  modify it under the terms of the GNU General Public License as
8 *  published by the Free Software Foundation, version 2 of the
9 *  License.
10 */
11
12#include <linux/nsproxy.h>
13#include <linux/ipc_namespace.h>
14#include <linux/sysctl.h>
15
16/*
17 * Define the ranges various user-specified maximum values can
18 * be set to.
19 */
20#define MIN_MSGMAX	1		/* min value for msg_max */
21#define MAX_MSGMAX	HARD_MSGMAX	/* max value for msg_max */
22#define MIN_MSGSIZEMAX	128		/* min value for msgsize_max */
23#define MAX_MSGSIZEMAX	(8192*128)	/* max value for msgsize_max */
24
25#ifdef CONFIG_PROC_SYSCTL
26static void *get_mq(ctl_table *table)
27{
28	char *which = table->data;
29	struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns;
30	which = (which - (char *)&init_ipc_ns) + (char *)ipc_ns;
31	return which;
32}
33
34static int proc_mq_dointvec(ctl_table *table, int write,
35	void __user *buffer, size_t *lenp, loff_t *ppos)
36{
37	struct ctl_table mq_table;
38	memcpy(&mq_table, table, sizeof(mq_table));
39	mq_table.data = get_mq(table);
40
41	return proc_dointvec(&mq_table, write, buffer, lenp, ppos);
42}
43
44static int proc_mq_dointvec_minmax(ctl_table *table, int write,
45	void __user *buffer, size_t *lenp, loff_t *ppos)
46{
47	struct ctl_table mq_table;
48	memcpy(&mq_table, table, sizeof(mq_table));
49	mq_table.data = get_mq(table);
50
51	return proc_dointvec_minmax(&mq_table, write, buffer,
52					lenp, ppos);
53}
54#else
55#define proc_mq_dointvec NULL
56#define proc_mq_dointvec_minmax NULL
57#endif
58
59static int msg_max_limit_min = MIN_MSGMAX;
60static int msg_max_limit_max = MAX_MSGMAX;
61
62static int msg_maxsize_limit_min = MIN_MSGSIZEMAX;
63static int msg_maxsize_limit_max = MAX_MSGSIZEMAX;
64
65static ctl_table mq_sysctls[] = {
66	{
67		.procname	= "queues_max",
68		.data		= &init_ipc_ns.mq_queues_max,
69		.maxlen		= sizeof(int),
70		.mode		= 0644,
71		.proc_handler	= proc_mq_dointvec,
72	},
73	{
74		.procname	= "msg_max",
75		.data		= &init_ipc_ns.mq_msg_max,
76		.maxlen		= sizeof(int),
77		.mode		= 0644,
78		.proc_handler	= proc_mq_dointvec_minmax,
79		.extra1		= &msg_max_limit_min,
80		.extra2		= &msg_max_limit_max,
81	},
82	{
83		.procname	= "msgsize_max",
84		.data		= &init_ipc_ns.mq_msgsize_max,
85		.maxlen		= sizeof(int),
86		.mode		= 0644,
87		.proc_handler	= proc_mq_dointvec_minmax,
88		.extra1		= &msg_maxsize_limit_min,
89		.extra2		= &msg_maxsize_limit_max,
90	},
91	{}
92};
93
94static ctl_table mq_sysctl_dir[] = {
95	{
96		.procname	= "mqueue",
97		.mode		= 0555,
98		.child		= mq_sysctls,
99	},
100	{}
101};
102
103static ctl_table mq_sysctl_root[] = {
104	{
105		.procname	= "fs",
106		.mode		= 0555,
107		.child		= mq_sysctl_dir,
108	},
109	{}
110};
111
112struct ctl_table_header *mq_register_sysctl_table(void)
113{
114	return register_sysctl_table(mq_sysctl_root);
115}
116