1b886d83cSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2a5494dcdSEric W. Biederman /* 3a5494dcdSEric W. Biederman * Copyright (C) 2007 4a5494dcdSEric W. Biederman * 5a5494dcdSEric W. Biederman * Author: Eric Biederman <ebiederm@xmision.com> 6a5494dcdSEric W. Biederman */ 7a5494dcdSEric W. Biederman 8a5494dcdSEric W. Biederman #include <linux/module.h> 9a5494dcdSEric W. Biederman #include <linux/ipc.h> 10a5494dcdSEric W. Biederman #include <linux/nsproxy.h> 11a5494dcdSEric W. Biederman #include <linux/sysctl.h> 12a5494dcdSEric W. Biederman #include <linux/uaccess.h> 13*5563cabdSMichal Clapinski #include <linux/capability.h> 14ae5e1b22SPavel Emelyanov #include <linux/ipc_namespace.h> 156546bc42SNadia Derbey #include <linux/msg.h> 166546bc42SNadia Derbey #include "util.h" 17a5494dcdSEric W. Biederman 18a5c5928bSJoe Perches static void *get_ipc(struct ctl_table *table) 19a5494dcdSEric W. Biederman { 20a5494dcdSEric W. Biederman char *which = table->data; 21a5494dcdSEric W. Biederman struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns; 22a5494dcdSEric W. Biederman which = (which - (char *)&init_ipc_ns) + (char *)ipc_ns; 23a5494dcdSEric W. Biederman return which; 24a5494dcdSEric W. Biederman } 25a5494dcdSEric W. Biederman 2611dea190SSerge E. Hallyn #ifdef CONFIG_PROC_SYSCTL 27a5c5928bSJoe Perches static int proc_ipc_dointvec(struct ctl_table *table, int write, 2832927393SChristoph Hellwig void *buffer, size_t *lenp, loff_t *ppos) 29a5494dcdSEric W. Biederman { 30a5494dcdSEric W. Biederman struct ctl_table ipc_table; 31b34a6b1dSVasiliy Kulikov 32a5494dcdSEric W. Biederman memcpy(&ipc_table, table, sizeof(ipc_table)); 33a5494dcdSEric W. Biederman ipc_table.data = get_ipc(table); 34a5494dcdSEric W. Biederman 358d65af78SAlexey Dobriyan return proc_dointvec(&ipc_table, write, buffer, lenp, ppos); 36a5494dcdSEric W. Biederman } 37a5494dcdSEric W. Biederman 38a5c5928bSJoe Perches static int proc_ipc_dointvec_minmax(struct ctl_table *table, int write, 3932927393SChristoph Hellwig void *buffer, size_t *lenp, loff_t *ppos) 40b34a6b1dSVasiliy Kulikov { 41b34a6b1dSVasiliy Kulikov struct ctl_table ipc_table; 42b34a6b1dSVasiliy Kulikov 43b34a6b1dSVasiliy Kulikov memcpy(&ipc_table, table, sizeof(ipc_table)); 44b34a6b1dSVasiliy Kulikov ipc_table.data = get_ipc(table); 45b34a6b1dSVasiliy Kulikov 46b34a6b1dSVasiliy Kulikov return proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos); 47b34a6b1dSVasiliy Kulikov } 48b34a6b1dSVasiliy Kulikov 49a5c5928bSJoe Perches static int proc_ipc_dointvec_minmax_orphans(struct ctl_table *table, int write, 5032927393SChristoph Hellwig void *buffer, size_t *lenp, loff_t *ppos) 51b34a6b1dSVasiliy Kulikov { 52b34a6b1dSVasiliy Kulikov struct ipc_namespace *ns = current->nsproxy->ipc_ns; 53b34a6b1dSVasiliy Kulikov int err = proc_ipc_dointvec_minmax(table, write, buffer, lenp, ppos); 54b34a6b1dSVasiliy Kulikov 55b34a6b1dSVasiliy Kulikov if (err < 0) 56b34a6b1dSVasiliy Kulikov return err; 57b34a6b1dSVasiliy Kulikov if (ns->shm_rmid_forced) 58b34a6b1dSVasiliy Kulikov shm_destroy_orphaned(ns); 59b34a6b1dSVasiliy Kulikov return err; 60b34a6b1dSVasiliy Kulikov } 61b34a6b1dSVasiliy Kulikov 62a5c5928bSJoe Perches static int proc_ipc_doulongvec_minmax(struct ctl_table *table, int write, 6332927393SChristoph Hellwig void *buffer, size_t *lenp, loff_t *ppos) 64a5494dcdSEric W. Biederman { 65a5494dcdSEric W. Biederman struct ctl_table ipc_table; 66a5494dcdSEric W. Biederman memcpy(&ipc_table, table, sizeof(ipc_table)); 67a5494dcdSEric W. Biederman ipc_table.data = get_ipc(table); 68a5494dcdSEric W. Biederman 698d65af78SAlexey Dobriyan return proc_doulongvec_minmax(&ipc_table, write, buffer, 70a5494dcdSEric W. Biederman lenp, ppos); 71a5494dcdSEric W. Biederman } 72a5494dcdSEric W. Biederman 730050ee05SManfred Spraul static int proc_ipc_auto_msgmni(struct ctl_table *table, int write, 7432927393SChristoph Hellwig void *buffer, size_t *lenp, loff_t *ppos) 759eefe520SNadia Derbey { 769eefe520SNadia Derbey struct ctl_table ipc_table; 770050ee05SManfred Spraul int dummy = 0; 789eefe520SNadia Derbey 799eefe520SNadia Derbey memcpy(&ipc_table, table, sizeof(ipc_table)); 800050ee05SManfred Spraul ipc_table.data = &dummy; 819eefe520SNadia Derbey 820050ee05SManfred Spraul if (write) 830050ee05SManfred Spraul pr_info_once("writing to auto_msgmni has no effect"); 849eefe520SNadia Derbey 850050ee05SManfred Spraul return proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos); 869eefe520SNadia Derbey } 879eefe520SNadia Derbey 888c81ddd2SWaiman Long static int proc_ipc_sem_dointvec(struct ctl_table *table, int write, 89fff1662cSTobias Klauser void *buffer, size_t *lenp, loff_t *ppos) 908c81ddd2SWaiman Long { 918c81ddd2SWaiman Long int ret, semmni; 928c81ddd2SWaiman Long struct ipc_namespace *ns = current->nsproxy->ipc_ns; 938c81ddd2SWaiman Long 948c81ddd2SWaiman Long semmni = ns->sem_ctls[3]; 958c81ddd2SWaiman Long ret = proc_ipc_dointvec(table, write, buffer, lenp, ppos); 968c81ddd2SWaiman Long 978c81ddd2SWaiman Long if (!ret) 988c81ddd2SWaiman Long ret = sem_check_semmni(current->nsproxy->ipc_ns); 998c81ddd2SWaiman Long 1008c81ddd2SWaiman Long /* 1018c81ddd2SWaiman Long * Reset the semmni value if an error happens. 1028c81ddd2SWaiman Long */ 1038c81ddd2SWaiman Long if (ret) 1048c81ddd2SWaiman Long ns->sem_ctls[3] = semmni; 1058c81ddd2SWaiman Long return ret; 1068c81ddd2SWaiman Long } 1078c81ddd2SWaiman Long 108*5563cabdSMichal Clapinski #ifdef CONFIG_CHECKPOINT_RESTORE 109*5563cabdSMichal Clapinski static int proc_ipc_dointvec_minmax_checkpoint_restore(struct ctl_table *table, 110*5563cabdSMichal Clapinski int write, void *buffer, size_t *lenp, loff_t *ppos) 111*5563cabdSMichal Clapinski { 112*5563cabdSMichal Clapinski struct user_namespace *user_ns = current->nsproxy->ipc_ns->user_ns; 113*5563cabdSMichal Clapinski 114*5563cabdSMichal Clapinski if (write && !checkpoint_restore_ns_capable(user_ns)) 115*5563cabdSMichal Clapinski return -EPERM; 116*5563cabdSMichal Clapinski 117*5563cabdSMichal Clapinski return proc_ipc_dointvec_minmax(table, write, buffer, lenp, ppos); 118*5563cabdSMichal Clapinski } 119*5563cabdSMichal Clapinski #endif 120*5563cabdSMichal Clapinski 121a5494dcdSEric W. Biederman #else 122a5494dcdSEric W. Biederman #define proc_ipc_doulongvec_minmax NULL 123a5494dcdSEric W. Biederman #define proc_ipc_dointvec NULL 124b34a6b1dSVasiliy Kulikov #define proc_ipc_dointvec_minmax NULL 125b34a6b1dSVasiliy Kulikov #define proc_ipc_dointvec_minmax_orphans NULL 1260050ee05SManfred Spraul #define proc_ipc_auto_msgmni NULL 1278c81ddd2SWaiman Long #define proc_ipc_sem_dointvec NULL 128*5563cabdSMichal Clapinski #ifdef CONFIG_CHECKPOINT_RESTORE 129*5563cabdSMichal Clapinski #define proc_ipc_dointvec_minmax_checkpoint_restore NULL 130*5563cabdSMichal Clapinski #endif /* CONFIG_CHECKPOINT_RESTORE */ 131a5494dcdSEric W. Biederman #endif 132a5494dcdSEric W. Biederman 1335ac893b8SWaiman Long int ipc_mni = IPCMNI; 1345ac893b8SWaiman Long int ipc_mni_shift = IPCMNI_SHIFT; 13599db46eaSManfred Spraul int ipc_min_cycle = RADIX_TREE_MAP_SIZE; 1369eefe520SNadia Derbey 137a5494dcdSEric W. Biederman static struct ctl_table ipc_kern_table[] = { 138a5494dcdSEric W. Biederman { 139a5494dcdSEric W. Biederman .procname = "shmmax", 140a5494dcdSEric W. Biederman .data = &init_ipc_ns.shm_ctlmax, 141a5494dcdSEric W. Biederman .maxlen = sizeof(init_ipc_ns.shm_ctlmax), 142a5494dcdSEric W. Biederman .mode = 0644, 143a5494dcdSEric W. Biederman .proc_handler = proc_ipc_doulongvec_minmax, 144a5494dcdSEric W. Biederman }, 145a5494dcdSEric W. Biederman { 146a5494dcdSEric W. Biederman .procname = "shmall", 147a5494dcdSEric W. Biederman .data = &init_ipc_ns.shm_ctlall, 148a5494dcdSEric W. Biederman .maxlen = sizeof(init_ipc_ns.shm_ctlall), 149a5494dcdSEric W. Biederman .mode = 0644, 150a5494dcdSEric W. Biederman .proc_handler = proc_ipc_doulongvec_minmax, 151a5494dcdSEric W. Biederman }, 152a5494dcdSEric W. Biederman { 153a5494dcdSEric W. Biederman .procname = "shmmni", 154a5494dcdSEric W. Biederman .data = &init_ipc_ns.shm_ctlmni, 155a5494dcdSEric W. Biederman .maxlen = sizeof(init_ipc_ns.shm_ctlmni), 156a5494dcdSEric W. Biederman .mode = 0644, 1576730e658SWaiman Long .proc_handler = proc_ipc_dointvec_minmax, 158eec4844fSMatteo Croce .extra1 = SYSCTL_ZERO, 1596730e658SWaiman Long .extra2 = &ipc_mni, 160a5494dcdSEric W. Biederman }, 161a5494dcdSEric W. Biederman { 162b34a6b1dSVasiliy Kulikov .procname = "shm_rmid_forced", 163b34a6b1dSVasiliy Kulikov .data = &init_ipc_ns.shm_rmid_forced, 164b34a6b1dSVasiliy Kulikov .maxlen = sizeof(init_ipc_ns.shm_rmid_forced), 165b34a6b1dSVasiliy Kulikov .mode = 0644, 166b34a6b1dSVasiliy Kulikov .proc_handler = proc_ipc_dointvec_minmax_orphans, 167eec4844fSMatteo Croce .extra1 = SYSCTL_ZERO, 168eec4844fSMatteo Croce .extra2 = SYSCTL_ONE, 169b34a6b1dSVasiliy Kulikov }, 170b34a6b1dSVasiliy Kulikov { 171a5494dcdSEric W. Biederman .procname = "msgmax", 172a5494dcdSEric W. Biederman .data = &init_ipc_ns.msg_ctlmax, 173a5494dcdSEric W. Biederman .maxlen = sizeof(init_ipc_ns.msg_ctlmax), 174a5494dcdSEric W. Biederman .mode = 0644, 1759bf76ca3SMathias Krause .proc_handler = proc_ipc_dointvec_minmax, 176eec4844fSMatteo Croce .extra1 = SYSCTL_ZERO, 177eec4844fSMatteo Croce .extra2 = SYSCTL_INT_MAX, 178a5494dcdSEric W. Biederman }, 179a5494dcdSEric W. Biederman { 180a5494dcdSEric W. Biederman .procname = "msgmni", 181a5494dcdSEric W. Biederman .data = &init_ipc_ns.msg_ctlmni, 182a5494dcdSEric W. Biederman .maxlen = sizeof(init_ipc_ns.msg_ctlmni), 183a5494dcdSEric W. Biederman .mode = 0644, 1840050ee05SManfred Spraul .proc_handler = proc_ipc_dointvec_minmax, 185eec4844fSMatteo Croce .extra1 = SYSCTL_ZERO, 1866730e658SWaiman Long .extra2 = &ipc_mni, 187a5494dcdSEric W. Biederman }, 188a5494dcdSEric W. Biederman { 1890050ee05SManfred Spraul .procname = "auto_msgmni", 1900050ee05SManfred Spraul .data = NULL, 1910050ee05SManfred Spraul .maxlen = sizeof(int), 1920050ee05SManfred Spraul .mode = 0644, 1930050ee05SManfred Spraul .proc_handler = proc_ipc_auto_msgmni, 194eec4844fSMatteo Croce .extra1 = SYSCTL_ZERO, 195eec4844fSMatteo Croce .extra2 = SYSCTL_ONE, 1960050ee05SManfred Spraul }, 1970050ee05SManfred Spraul { 198a5494dcdSEric W. Biederman .procname = "msgmnb", 199a5494dcdSEric W. Biederman .data = &init_ipc_ns.msg_ctlmnb, 200a5494dcdSEric W. Biederman .maxlen = sizeof(init_ipc_ns.msg_ctlmnb), 201a5494dcdSEric W. Biederman .mode = 0644, 2029bf76ca3SMathias Krause .proc_handler = proc_ipc_dointvec_minmax, 203eec4844fSMatteo Croce .extra1 = SYSCTL_ZERO, 204eec4844fSMatteo Croce .extra2 = SYSCTL_INT_MAX, 205a5494dcdSEric W. Biederman }, 206a5494dcdSEric W. Biederman { 207a5494dcdSEric W. Biederman .procname = "sem", 208a5494dcdSEric W. Biederman .data = &init_ipc_ns.sem_ctls, 209a5494dcdSEric W. Biederman .maxlen = 4*sizeof(int), 210a5494dcdSEric W. Biederman .mode = 0644, 2118c81ddd2SWaiman Long .proc_handler = proc_ipc_sem_dointvec, 212a5494dcdSEric W. Biederman }, 21303f59566SStanislav Kinsbursky #ifdef CONFIG_CHECKPOINT_RESTORE 21403f59566SStanislav Kinsbursky { 21503f59566SStanislav Kinsbursky .procname = "sem_next_id", 21603f59566SStanislav Kinsbursky .data = &init_ipc_ns.ids[IPC_SEM_IDS].next_id, 21703f59566SStanislav Kinsbursky .maxlen = sizeof(init_ipc_ns.ids[IPC_SEM_IDS].next_id), 218*5563cabdSMichal Clapinski .mode = 0666, 219*5563cabdSMichal Clapinski .proc_handler = proc_ipc_dointvec_minmax_checkpoint_restore, 220eec4844fSMatteo Croce .extra1 = SYSCTL_ZERO, 221eec4844fSMatteo Croce .extra2 = SYSCTL_INT_MAX, 22203f59566SStanislav Kinsbursky }, 22303f59566SStanislav Kinsbursky { 22403f59566SStanislav Kinsbursky .procname = "msg_next_id", 22503f59566SStanislav Kinsbursky .data = &init_ipc_ns.ids[IPC_MSG_IDS].next_id, 22603f59566SStanislav Kinsbursky .maxlen = sizeof(init_ipc_ns.ids[IPC_MSG_IDS].next_id), 227*5563cabdSMichal Clapinski .mode = 0666, 228*5563cabdSMichal Clapinski .proc_handler = proc_ipc_dointvec_minmax_checkpoint_restore, 229eec4844fSMatteo Croce .extra1 = SYSCTL_ZERO, 230eec4844fSMatteo Croce .extra2 = SYSCTL_INT_MAX, 23103f59566SStanislav Kinsbursky }, 23203f59566SStanislav Kinsbursky { 23303f59566SStanislav Kinsbursky .procname = "shm_next_id", 23403f59566SStanislav Kinsbursky .data = &init_ipc_ns.ids[IPC_SHM_IDS].next_id, 23503f59566SStanislav Kinsbursky .maxlen = sizeof(init_ipc_ns.ids[IPC_SHM_IDS].next_id), 236*5563cabdSMichal Clapinski .mode = 0666, 237*5563cabdSMichal Clapinski .proc_handler = proc_ipc_dointvec_minmax_checkpoint_restore, 238eec4844fSMatteo Croce .extra1 = SYSCTL_ZERO, 239eec4844fSMatteo Croce .extra2 = SYSCTL_INT_MAX, 24003f59566SStanislav Kinsbursky }, 24103f59566SStanislav Kinsbursky #endif 242a5494dcdSEric W. Biederman {} 243a5494dcdSEric W. Biederman }; 244a5494dcdSEric W. Biederman 245a5494dcdSEric W. Biederman static struct ctl_table ipc_root_table[] = { 246a5494dcdSEric W. Biederman { 247a5494dcdSEric W. Biederman .procname = "kernel", 248a5494dcdSEric W. Biederman .mode = 0555, 249a5494dcdSEric W. Biederman .child = ipc_kern_table, 250a5494dcdSEric W. Biederman }, 251a5494dcdSEric W. Biederman {} 252a5494dcdSEric W. Biederman }; 253a5494dcdSEric W. Biederman 254a5494dcdSEric W. Biederman static int __init ipc_sysctl_init(void) 255a5494dcdSEric W. Biederman { 2560b4d4147SEric W. Biederman register_sysctl_table(ipc_root_table); 257a5494dcdSEric W. Biederman return 0; 258a5494dcdSEric W. Biederman } 259a5494dcdSEric W. Biederman 2606d08a256SDavidlohr Bueso device_initcall(ipc_sysctl_init); 2615ac893b8SWaiman Long 2625ac893b8SWaiman Long static int __init ipc_mni_extend(char *str) 2635ac893b8SWaiman Long { 2645ac893b8SWaiman Long ipc_mni = IPCMNI_EXTEND; 2655ac893b8SWaiman Long ipc_mni_shift = IPCMNI_EXTEND_SHIFT; 26699db46eaSManfred Spraul ipc_min_cycle = IPCMNI_EXTEND_MIN_CYCLE; 2675ac893b8SWaiman Long pr_info("IPCMNI extended to %d.\n", ipc_mni); 2685ac893b8SWaiman Long return 0; 2695ac893b8SWaiman Long } 2705ac893b8SWaiman Long early_param("ipcmni_extend", ipc_mni_extend); 271