1b886d83cSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2bdc8e5f8SSerge E. Hallyn /* 3bdc8e5f8SSerge E. Hallyn * Copyright (C) 2007 IBM Corporation 4bdc8e5f8SSerge E. Hallyn * 5bdc8e5f8SSerge E. Hallyn * Author: Cedric Le Goater <[email protected]> 6bdc8e5f8SSerge E. Hallyn */ 7bdc8e5f8SSerge E. Hallyn 8bdc8e5f8SSerge E. Hallyn #include <linux/nsproxy.h> 9bdc8e5f8SSerge E. Hallyn #include <linux/ipc_namespace.h> 10bdc8e5f8SSerge E. Hallyn #include <linux/sysctl.h> 11bdc8e5f8SSerge E. Hallyn 12dc55e35fSAlexey Gladkov #include <linux/stat.h> 13dc55e35fSAlexey Gladkov #include <linux/capability.h> 14dc55e35fSAlexey Gladkov #include <linux/slab.h> 15f9436a5dSAlexey Gladkov #include <linux/cred.h> 16bdc8e5f8SSerge E. Hallyn 17bdc8e5f8SSerge E. Hallyn static int msg_max_limit_min = MIN_MSGMAX; 1893e6f119SDoug Ledford static int msg_max_limit_max = HARD_MSGMAX; 19bdc8e5f8SSerge E. Hallyn 20bdc8e5f8SSerge E. Hallyn static int msg_maxsize_limit_min = MIN_MSGSIZEMAX; 2193e6f119SDoug Ledford static int msg_maxsize_limit_max = HARD_MSGSIZEMAX; 22bdc8e5f8SSerge E. Hallyn 23a5c5928bSJoe Perches static struct ctl_table mq_sysctls[] = { 24bdc8e5f8SSerge E. Hallyn { 25bdc8e5f8SSerge E. Hallyn .procname = "queues_max", 26bdc8e5f8SSerge E. Hallyn .data = &init_ipc_ns.mq_queues_max, 27bdc8e5f8SSerge E. Hallyn .maxlen = sizeof(int), 28bdc8e5f8SSerge E. Hallyn .mode = 0644, 29dc55e35fSAlexey Gladkov .proc_handler = proc_dointvec, 30bdc8e5f8SSerge E. Hallyn }, 31bdc8e5f8SSerge E. Hallyn { 32bdc8e5f8SSerge E. Hallyn .procname = "msg_max", 33bdc8e5f8SSerge E. Hallyn .data = &init_ipc_ns.mq_msg_max, 34bdc8e5f8SSerge E. Hallyn .maxlen = sizeof(int), 35bdc8e5f8SSerge E. Hallyn .mode = 0644, 36dc55e35fSAlexey Gladkov .proc_handler = proc_dointvec_minmax, 37bdc8e5f8SSerge E. Hallyn .extra1 = &msg_max_limit_min, 38bdc8e5f8SSerge E. Hallyn .extra2 = &msg_max_limit_max, 39bdc8e5f8SSerge E. Hallyn }, 40bdc8e5f8SSerge E. Hallyn { 41bdc8e5f8SSerge E. Hallyn .procname = "msgsize_max", 42bdc8e5f8SSerge E. Hallyn .data = &init_ipc_ns.mq_msgsize_max, 43bdc8e5f8SSerge E. Hallyn .maxlen = sizeof(int), 44bdc8e5f8SSerge E. Hallyn .mode = 0644, 45dc55e35fSAlexey Gladkov .proc_handler = proc_dointvec_minmax, 46bdc8e5f8SSerge E. Hallyn .extra1 = &msg_maxsize_limit_min, 47bdc8e5f8SSerge E. Hallyn .extra2 = &msg_maxsize_limit_max, 48bdc8e5f8SSerge E. Hallyn }, 49cef0184cSKOSAKI Motohiro { 50cef0184cSKOSAKI Motohiro .procname = "msg_default", 51cef0184cSKOSAKI Motohiro .data = &init_ipc_ns.mq_msg_default, 52cef0184cSKOSAKI Motohiro .maxlen = sizeof(int), 53cef0184cSKOSAKI Motohiro .mode = 0644, 54dc55e35fSAlexey Gladkov .proc_handler = proc_dointvec_minmax, 55cef0184cSKOSAKI Motohiro .extra1 = &msg_max_limit_min, 56cef0184cSKOSAKI Motohiro .extra2 = &msg_max_limit_max, 57cef0184cSKOSAKI Motohiro }, 58cef0184cSKOSAKI Motohiro { 59cef0184cSKOSAKI Motohiro .procname = "msgsize_default", 60cef0184cSKOSAKI Motohiro .data = &init_ipc_ns.mq_msgsize_default, 61cef0184cSKOSAKI Motohiro .maxlen = sizeof(int), 62cef0184cSKOSAKI Motohiro .mode = 0644, 63dc55e35fSAlexey Gladkov .proc_handler = proc_dointvec_minmax, 64cef0184cSKOSAKI Motohiro .extra1 = &msg_maxsize_limit_min, 65cef0184cSKOSAKI Motohiro .extra2 = &msg_maxsize_limit_max, 66cef0184cSKOSAKI Motohiro }, 672bc4657cSEric W. Biederman {} 68bdc8e5f8SSerge E. Hallyn }; 69bdc8e5f8SSerge E. Hallyn 70dc55e35fSAlexey Gladkov static struct ctl_table_set *set_lookup(struct ctl_table_root *root) 71bdc8e5f8SSerge E. Hallyn { 72dc55e35fSAlexey Gladkov return ¤t->nsproxy->ipc_ns->mq_set; 73dc55e35fSAlexey Gladkov } 74dc55e35fSAlexey Gladkov 75dc55e35fSAlexey Gladkov static int set_is_seen(struct ctl_table_set *set) 76dc55e35fSAlexey Gladkov { 77dc55e35fSAlexey Gladkov return ¤t->nsproxy->ipc_ns->mq_set == set; 78dc55e35fSAlexey Gladkov } 79dc55e35fSAlexey Gladkov 80f9436a5dSAlexey Gladkov static void mq_set_ownership(struct ctl_table_header *head, 81f9436a5dSAlexey Gladkov struct ctl_table *table, 82f9436a5dSAlexey Gladkov kuid_t *uid, kgid_t *gid) 83f9436a5dSAlexey Gladkov { 84f9436a5dSAlexey Gladkov struct ipc_namespace *ns = 85f9436a5dSAlexey Gladkov container_of(head->set, struct ipc_namespace, mq_set); 86f9436a5dSAlexey Gladkov 87f9436a5dSAlexey Gladkov kuid_t ns_root_uid = make_kuid(ns->user_ns, 0); 88f9436a5dSAlexey Gladkov kgid_t ns_root_gid = make_kgid(ns->user_ns, 0); 89f9436a5dSAlexey Gladkov 90f9436a5dSAlexey Gladkov *uid = uid_valid(ns_root_uid) ? ns_root_uid : GLOBAL_ROOT_UID; 91f9436a5dSAlexey Gladkov *gid = gid_valid(ns_root_gid) ? ns_root_gid : GLOBAL_ROOT_GID; 92f9436a5dSAlexey Gladkov } 93f9436a5dSAlexey Gladkov 94f9436a5dSAlexey Gladkov static int mq_permissions(struct ctl_table_header *head, struct ctl_table *table) 95f9436a5dSAlexey Gladkov { 96f9436a5dSAlexey Gladkov int mode = table->mode; 97f9436a5dSAlexey Gladkov kuid_t ns_root_uid; 98f9436a5dSAlexey Gladkov kgid_t ns_root_gid; 99f9436a5dSAlexey Gladkov 100f9436a5dSAlexey Gladkov mq_set_ownership(head, table, &ns_root_uid, &ns_root_gid); 101f9436a5dSAlexey Gladkov 102f9436a5dSAlexey Gladkov if (uid_eq(current_euid(), ns_root_uid)) 103f9436a5dSAlexey Gladkov mode >>= 6; 104f9436a5dSAlexey Gladkov 105f9436a5dSAlexey Gladkov else if (in_egroup_p(ns_root_gid)) 106f9436a5dSAlexey Gladkov mode >>= 3; 107f9436a5dSAlexey Gladkov 108f9436a5dSAlexey Gladkov mode &= 7; 109f9436a5dSAlexey Gladkov 110f9436a5dSAlexey Gladkov return (mode << 6) | (mode << 3) | mode; 111f9436a5dSAlexey Gladkov } 112f9436a5dSAlexey Gladkov 113dc55e35fSAlexey Gladkov static struct ctl_table_root set_root = { 114dc55e35fSAlexey Gladkov .lookup = set_lookup, 115f9436a5dSAlexey Gladkov .permissions = mq_permissions, 116f9436a5dSAlexey Gladkov .set_ownership = mq_set_ownership, 117bdc8e5f8SSerge E. Hallyn }; 118bdc8e5f8SSerge E. Hallyn 119dc55e35fSAlexey Gladkov bool setup_mq_sysctls(struct ipc_namespace *ns) 120bdc8e5f8SSerge E. Hallyn { 121dc55e35fSAlexey Gladkov struct ctl_table *tbl; 122bdc8e5f8SSerge E. Hallyn 123dc55e35fSAlexey Gladkov setup_sysctl_set(&ns->mq_set, &set_root, set_is_seen); 124dc55e35fSAlexey Gladkov 125dc55e35fSAlexey Gladkov tbl = kmemdup(mq_sysctls, sizeof(mq_sysctls), GFP_KERNEL); 126dc55e35fSAlexey Gladkov if (tbl) { 127dc55e35fSAlexey Gladkov int i; 128dc55e35fSAlexey Gladkov 129dc55e35fSAlexey Gladkov for (i = 0; i < ARRAY_SIZE(mq_sysctls); i++) { 130dc55e35fSAlexey Gladkov if (tbl[i].data == &init_ipc_ns.mq_queues_max) 131dc55e35fSAlexey Gladkov tbl[i].data = &ns->mq_queues_max; 132dc55e35fSAlexey Gladkov 133dc55e35fSAlexey Gladkov else if (tbl[i].data == &init_ipc_ns.mq_msg_max) 134dc55e35fSAlexey Gladkov tbl[i].data = &ns->mq_msg_max; 135dc55e35fSAlexey Gladkov 136dc55e35fSAlexey Gladkov else if (tbl[i].data == &init_ipc_ns.mq_msgsize_max) 137dc55e35fSAlexey Gladkov tbl[i].data = &ns->mq_msgsize_max; 138dc55e35fSAlexey Gladkov 139dc55e35fSAlexey Gladkov else if (tbl[i].data == &init_ipc_ns.mq_msg_default) 140dc55e35fSAlexey Gladkov tbl[i].data = &ns->mq_msg_default; 141dc55e35fSAlexey Gladkov 142dc55e35fSAlexey Gladkov else if (tbl[i].data == &init_ipc_ns.mq_msgsize_default) 143dc55e35fSAlexey Gladkov tbl[i].data = &ns->mq_msgsize_default; 144dc55e35fSAlexey Gladkov else 145dc55e35fSAlexey Gladkov tbl[i].data = NULL; 146dc55e35fSAlexey Gladkov } 147dc55e35fSAlexey Gladkov 148bff97cf1SJoel Granados ns->mq_sysctls = __register_sysctl_table(&ns->mq_set, 149bff97cf1SJoel Granados "fs/mqueue", tbl, 150bff97cf1SJoel Granados ARRAY_SIZE(mq_sysctls)); 151dc55e35fSAlexey Gladkov } 152dc55e35fSAlexey Gladkov if (!ns->mq_sysctls) { 153dc55e35fSAlexey Gladkov kfree(tbl); 154dc55e35fSAlexey Gladkov retire_sysctl_set(&ns->mq_set); 155dc55e35fSAlexey Gladkov return false; 156dc55e35fSAlexey Gladkov } 157dc55e35fSAlexey Gladkov 158dc55e35fSAlexey Gladkov return true; 159dc55e35fSAlexey Gladkov } 160dc55e35fSAlexey Gladkov 161dc55e35fSAlexey Gladkov void retire_mq_sysctls(struct ipc_namespace *ns) 162bdc8e5f8SSerge E. Hallyn { 163*bfa858f2SThomas Weißschuh const struct ctl_table *tbl; 164dc55e35fSAlexey Gladkov 165dc55e35fSAlexey Gladkov tbl = ns->mq_sysctls->ctl_table_arg; 166dc55e35fSAlexey Gladkov unregister_sysctl_table(ns->mq_sysctls); 167dc55e35fSAlexey Gladkov retire_sysctl_set(&ns->mq_set); 168dc55e35fSAlexey Gladkov kfree(tbl); 169bdc8e5f8SSerge E. Hallyn } 170