0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/nsproxy.h>
0009 #include <linux/ipc_namespace.h>
0010 #include <linux/sysctl.h>
0011
0012 #include <linux/stat.h>
0013 #include <linux/capability.h>
0014 #include <linux/slab.h>
0015
0016 static int msg_max_limit_min = MIN_MSGMAX;
0017 static int msg_max_limit_max = HARD_MSGMAX;
0018
0019 static int msg_maxsize_limit_min = MIN_MSGSIZEMAX;
0020 static int msg_maxsize_limit_max = HARD_MSGSIZEMAX;
0021
0022 static struct ctl_table mq_sysctls[] = {
0023 {
0024 .procname = "queues_max",
0025 .data = &init_ipc_ns.mq_queues_max,
0026 .maxlen = sizeof(int),
0027 .mode = 0644,
0028 .proc_handler = proc_dointvec,
0029 },
0030 {
0031 .procname = "msg_max",
0032 .data = &init_ipc_ns.mq_msg_max,
0033 .maxlen = sizeof(int),
0034 .mode = 0644,
0035 .proc_handler = proc_dointvec_minmax,
0036 .extra1 = &msg_max_limit_min,
0037 .extra2 = &msg_max_limit_max,
0038 },
0039 {
0040 .procname = "msgsize_max",
0041 .data = &init_ipc_ns.mq_msgsize_max,
0042 .maxlen = sizeof(int),
0043 .mode = 0644,
0044 .proc_handler = proc_dointvec_minmax,
0045 .extra1 = &msg_maxsize_limit_min,
0046 .extra2 = &msg_maxsize_limit_max,
0047 },
0048 {
0049 .procname = "msg_default",
0050 .data = &init_ipc_ns.mq_msg_default,
0051 .maxlen = sizeof(int),
0052 .mode = 0644,
0053 .proc_handler = proc_dointvec_minmax,
0054 .extra1 = &msg_max_limit_min,
0055 .extra2 = &msg_max_limit_max,
0056 },
0057 {
0058 .procname = "msgsize_default",
0059 .data = &init_ipc_ns.mq_msgsize_default,
0060 .maxlen = sizeof(int),
0061 .mode = 0644,
0062 .proc_handler = proc_dointvec_minmax,
0063 .extra1 = &msg_maxsize_limit_min,
0064 .extra2 = &msg_maxsize_limit_max,
0065 },
0066 {}
0067 };
0068
0069 static struct ctl_table_set *set_lookup(struct ctl_table_root *root)
0070 {
0071 return ¤t->nsproxy->ipc_ns->mq_set;
0072 }
0073
0074 static int set_is_seen(struct ctl_table_set *set)
0075 {
0076 return ¤t->nsproxy->ipc_ns->mq_set == set;
0077 }
0078
0079 static struct ctl_table_root set_root = {
0080 .lookup = set_lookup,
0081 };
0082
0083 bool setup_mq_sysctls(struct ipc_namespace *ns)
0084 {
0085 struct ctl_table *tbl;
0086
0087 setup_sysctl_set(&ns->mq_set, &set_root, set_is_seen);
0088
0089 tbl = kmemdup(mq_sysctls, sizeof(mq_sysctls), GFP_KERNEL);
0090 if (tbl) {
0091 int i;
0092
0093 for (i = 0; i < ARRAY_SIZE(mq_sysctls); i++) {
0094 if (tbl[i].data == &init_ipc_ns.mq_queues_max)
0095 tbl[i].data = &ns->mq_queues_max;
0096
0097 else if (tbl[i].data == &init_ipc_ns.mq_msg_max)
0098 tbl[i].data = &ns->mq_msg_max;
0099
0100 else if (tbl[i].data == &init_ipc_ns.mq_msgsize_max)
0101 tbl[i].data = &ns->mq_msgsize_max;
0102
0103 else if (tbl[i].data == &init_ipc_ns.mq_msg_default)
0104 tbl[i].data = &ns->mq_msg_default;
0105
0106 else if (tbl[i].data == &init_ipc_ns.mq_msgsize_default)
0107 tbl[i].data = &ns->mq_msgsize_default;
0108 else
0109 tbl[i].data = NULL;
0110 }
0111
0112 ns->mq_sysctls = __register_sysctl_table(&ns->mq_set, "fs/mqueue", tbl);
0113 }
0114 if (!ns->mq_sysctls) {
0115 kfree(tbl);
0116 retire_sysctl_set(&ns->mq_set);
0117 return false;
0118 }
0119
0120 return true;
0121 }
0122
0123 void retire_mq_sysctls(struct ipc_namespace *ns)
0124 {
0125 struct ctl_table *tbl;
0126
0127 tbl = ns->mq_sysctls->ctl_table_arg;
0128 unregister_sysctl_table(ns->mq_sysctls);
0129 retire_sysctl_set(&ns->mq_set);
0130 kfree(tbl);
0131 }