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> 17ae5e1b22SPavel Emelyanov #include <linux/ipc_namespace.h> 186546bc42SNadia Derbey #include <linux/msg.h> 196546bc42SNadia Derbey #include "util.h" 20a5494dcdSEric W. Biederman 21a5c5928bSJoe Perches static void *get_ipc(struct ctl_table *table) 22a5494dcdSEric W. Biederman { 23a5494dcdSEric W. Biederman char *which = table->data; 24a5494dcdSEric W. Biederman struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns; 25a5494dcdSEric W. Biederman which = (which - (char *)&init_ipc_ns) + (char *)ipc_ns; 26a5494dcdSEric W. Biederman return which; 27a5494dcdSEric W. Biederman } 28a5494dcdSEric W. Biederman 2911dea190SSerge E. Hallyn #ifdef CONFIG_PROC_SYSCTL 30a5c5928bSJoe Perches static int proc_ipc_dointvec(struct ctl_table *table, int write, 31a5494dcdSEric W. Biederman void __user *buffer, size_t *lenp, loff_t *ppos) 32a5494dcdSEric W. Biederman { 33a5494dcdSEric W. Biederman struct ctl_table ipc_table; 34b34a6b1dSVasiliy Kulikov 35a5494dcdSEric W. Biederman memcpy(&ipc_table, table, sizeof(ipc_table)); 36a5494dcdSEric W. Biederman ipc_table.data = get_ipc(table); 37a5494dcdSEric W. Biederman 388d65af78SAlexey Dobriyan return proc_dointvec(&ipc_table, write, buffer, lenp, ppos); 39a5494dcdSEric W. Biederman } 40a5494dcdSEric W. Biederman 41a5c5928bSJoe Perches static int proc_ipc_dointvec_minmax(struct ctl_table *table, int write, 42b34a6b1dSVasiliy Kulikov void __user *buffer, size_t *lenp, loff_t *ppos) 43b34a6b1dSVasiliy Kulikov { 44b34a6b1dSVasiliy Kulikov struct ctl_table ipc_table; 45b34a6b1dSVasiliy Kulikov 46b34a6b1dSVasiliy Kulikov memcpy(&ipc_table, table, sizeof(ipc_table)); 47b34a6b1dSVasiliy Kulikov ipc_table.data = get_ipc(table); 48b34a6b1dSVasiliy Kulikov 49b34a6b1dSVasiliy Kulikov return proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos); 50b34a6b1dSVasiliy Kulikov } 51b34a6b1dSVasiliy Kulikov 52a5c5928bSJoe Perches static int proc_ipc_dointvec_minmax_orphans(struct ctl_table *table, int write, 53b34a6b1dSVasiliy Kulikov void __user *buffer, size_t *lenp, loff_t *ppos) 54b34a6b1dSVasiliy Kulikov { 55b34a6b1dSVasiliy Kulikov struct ipc_namespace *ns = current->nsproxy->ipc_ns; 56b34a6b1dSVasiliy Kulikov int err = proc_ipc_dointvec_minmax(table, write, buffer, lenp, ppos); 57b34a6b1dSVasiliy Kulikov 58b34a6b1dSVasiliy Kulikov if (err < 0) 59b34a6b1dSVasiliy Kulikov return err; 60b34a6b1dSVasiliy Kulikov if (ns->shm_rmid_forced) 61b34a6b1dSVasiliy Kulikov shm_destroy_orphaned(ns); 62b34a6b1dSVasiliy Kulikov return err; 63b34a6b1dSVasiliy Kulikov } 64b34a6b1dSVasiliy Kulikov 65a5c5928bSJoe Perches static int proc_ipc_doulongvec_minmax(struct ctl_table *table, int write, 668d65af78SAlexey Dobriyan void __user *buffer, size_t *lenp, loff_t *ppos) 67a5494dcdSEric W. Biederman { 68a5494dcdSEric W. Biederman struct ctl_table ipc_table; 69a5494dcdSEric W. Biederman memcpy(&ipc_table, table, sizeof(ipc_table)); 70a5494dcdSEric W. Biederman ipc_table.data = get_ipc(table); 71a5494dcdSEric W. Biederman 728d65af78SAlexey Dobriyan return proc_doulongvec_minmax(&ipc_table, write, buffer, 73a5494dcdSEric W. Biederman lenp, ppos); 74a5494dcdSEric W. Biederman } 75a5494dcdSEric W. Biederman 760050ee05SManfred Spraul static int proc_ipc_auto_msgmni(struct ctl_table *table, int write, 778d65af78SAlexey Dobriyan void __user *buffer, size_t *lenp, loff_t *ppos) 789eefe520SNadia Derbey { 799eefe520SNadia Derbey struct ctl_table ipc_table; 800050ee05SManfred Spraul int dummy = 0; 819eefe520SNadia Derbey 829eefe520SNadia Derbey memcpy(&ipc_table, table, sizeof(ipc_table)); 830050ee05SManfred Spraul ipc_table.data = &dummy; 849eefe520SNadia Derbey 850050ee05SManfred Spraul if (write) 860050ee05SManfred Spraul pr_info_once("writing to auto_msgmni has no effect"); 879eefe520SNadia Derbey 880050ee05SManfred Spraul return proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos); 899eefe520SNadia Derbey } 909eefe520SNadia Derbey 918c81ddd2SWaiman Long static int proc_ipc_sem_dointvec(struct ctl_table *table, int write, 928c81ddd2SWaiman Long void __user *buffer, size_t *lenp, loff_t *ppos) 938c81ddd2SWaiman Long { 948c81ddd2SWaiman Long int ret, semmni; 958c81ddd2SWaiman Long struct ipc_namespace *ns = current->nsproxy->ipc_ns; 968c81ddd2SWaiman Long 978c81ddd2SWaiman Long semmni = ns->sem_ctls[3]; 988c81ddd2SWaiman Long ret = proc_ipc_dointvec(table, write, buffer, lenp, ppos); 998c81ddd2SWaiman Long 1008c81ddd2SWaiman Long if (!ret) 1018c81ddd2SWaiman Long ret = sem_check_semmni(current->nsproxy->ipc_ns); 1028c81ddd2SWaiman Long 1038c81ddd2SWaiman Long /* 1048c81ddd2SWaiman Long * Reset the semmni value if an error happens. 1058c81ddd2SWaiman Long */ 1068c81ddd2SWaiman Long if (ret) 1078c81ddd2SWaiman Long ns->sem_ctls[3] = semmni; 1088c81ddd2SWaiman Long return ret; 1098c81ddd2SWaiman Long } 1108c81ddd2SWaiman Long 111a5494dcdSEric W. Biederman #else 112a5494dcdSEric W. Biederman #define proc_ipc_doulongvec_minmax NULL 113a5494dcdSEric W. Biederman #define proc_ipc_dointvec NULL 114b34a6b1dSVasiliy Kulikov #define proc_ipc_dointvec_minmax NULL 115b34a6b1dSVasiliy Kulikov #define proc_ipc_dointvec_minmax_orphans NULL 1160050ee05SManfred Spraul #define proc_ipc_auto_msgmni NULL 1178c81ddd2SWaiman Long #define proc_ipc_sem_dointvec NULL 118a5494dcdSEric W. Biederman #endif 119a5494dcdSEric W. Biederman 1209eefe520SNadia Derbey static int zero; 1219eefe520SNadia Derbey static int one = 1; 12203f59566SStanislav Kinsbursky static int int_max = INT_MAX; 123*5ac893b8SWaiman Long int ipc_mni = IPCMNI; 124*5ac893b8SWaiman Long int ipc_mni_shift = IPCMNI_SHIFT; 1259eefe520SNadia Derbey 126a5494dcdSEric W. Biederman static struct ctl_table ipc_kern_table[] = { 127a5494dcdSEric W. Biederman { 128a5494dcdSEric W. Biederman .procname = "shmmax", 129a5494dcdSEric W. Biederman .data = &init_ipc_ns.shm_ctlmax, 130a5494dcdSEric W. Biederman .maxlen = sizeof(init_ipc_ns.shm_ctlmax), 131a5494dcdSEric W. Biederman .mode = 0644, 132a5494dcdSEric W. Biederman .proc_handler = proc_ipc_doulongvec_minmax, 133a5494dcdSEric W. Biederman }, 134a5494dcdSEric W. Biederman { 135a5494dcdSEric W. Biederman .procname = "shmall", 136a5494dcdSEric W. Biederman .data = &init_ipc_ns.shm_ctlall, 137a5494dcdSEric W. Biederman .maxlen = sizeof(init_ipc_ns.shm_ctlall), 138a5494dcdSEric W. Biederman .mode = 0644, 139a5494dcdSEric W. Biederman .proc_handler = proc_ipc_doulongvec_minmax, 140a5494dcdSEric W. Biederman }, 141a5494dcdSEric W. Biederman { 142a5494dcdSEric W. Biederman .procname = "shmmni", 143a5494dcdSEric W. Biederman .data = &init_ipc_ns.shm_ctlmni, 144a5494dcdSEric W. Biederman .maxlen = sizeof(init_ipc_ns.shm_ctlmni), 145a5494dcdSEric W. Biederman .mode = 0644, 1466730e658SWaiman Long .proc_handler = proc_ipc_dointvec_minmax, 1476730e658SWaiman Long .extra1 = &zero, 1486730e658SWaiman Long .extra2 = &ipc_mni, 149a5494dcdSEric W. Biederman }, 150a5494dcdSEric W. Biederman { 151b34a6b1dSVasiliy Kulikov .procname = "shm_rmid_forced", 152b34a6b1dSVasiliy Kulikov .data = &init_ipc_ns.shm_rmid_forced, 153b34a6b1dSVasiliy Kulikov .maxlen = sizeof(init_ipc_ns.shm_rmid_forced), 154b34a6b1dSVasiliy Kulikov .mode = 0644, 155b34a6b1dSVasiliy Kulikov .proc_handler = proc_ipc_dointvec_minmax_orphans, 156b34a6b1dSVasiliy Kulikov .extra1 = &zero, 157b34a6b1dSVasiliy Kulikov .extra2 = &one, 158b34a6b1dSVasiliy Kulikov }, 159b34a6b1dSVasiliy Kulikov { 160a5494dcdSEric W. Biederman .procname = "msgmax", 161a5494dcdSEric W. Biederman .data = &init_ipc_ns.msg_ctlmax, 162a5494dcdSEric W. Biederman .maxlen = sizeof(init_ipc_ns.msg_ctlmax), 163a5494dcdSEric W. Biederman .mode = 0644, 1649bf76ca3SMathias Krause .proc_handler = proc_ipc_dointvec_minmax, 1659bf76ca3SMathias Krause .extra1 = &zero, 1669bf76ca3SMathias Krause .extra2 = &int_max, 167a5494dcdSEric W. Biederman }, 168a5494dcdSEric W. Biederman { 169a5494dcdSEric W. Biederman .procname = "msgmni", 170a5494dcdSEric W. Biederman .data = &init_ipc_ns.msg_ctlmni, 171a5494dcdSEric W. Biederman .maxlen = sizeof(init_ipc_ns.msg_ctlmni), 172a5494dcdSEric W. Biederman .mode = 0644, 1730050ee05SManfred Spraul .proc_handler = proc_ipc_dointvec_minmax, 1749bf76ca3SMathias Krause .extra1 = &zero, 1756730e658SWaiman Long .extra2 = &ipc_mni, 176a5494dcdSEric W. Biederman }, 177a5494dcdSEric W. Biederman { 1780050ee05SManfred Spraul .procname = "auto_msgmni", 1790050ee05SManfred Spraul .data = NULL, 1800050ee05SManfred Spraul .maxlen = sizeof(int), 1810050ee05SManfred Spraul .mode = 0644, 1820050ee05SManfred Spraul .proc_handler = proc_ipc_auto_msgmni, 1830050ee05SManfred Spraul .extra1 = &zero, 1840050ee05SManfred Spraul .extra2 = &one, 1850050ee05SManfred Spraul }, 1860050ee05SManfred Spraul { 187a5494dcdSEric W. Biederman .procname = "msgmnb", 188a5494dcdSEric W. Biederman .data = &init_ipc_ns.msg_ctlmnb, 189a5494dcdSEric W. Biederman .maxlen = sizeof(init_ipc_ns.msg_ctlmnb), 190a5494dcdSEric W. Biederman .mode = 0644, 1919bf76ca3SMathias Krause .proc_handler = proc_ipc_dointvec_minmax, 1929bf76ca3SMathias Krause .extra1 = &zero, 1939bf76ca3SMathias Krause .extra2 = &int_max, 194a5494dcdSEric W. Biederman }, 195a5494dcdSEric W. Biederman { 196a5494dcdSEric W. Biederman .procname = "sem", 197a5494dcdSEric W. Biederman .data = &init_ipc_ns.sem_ctls, 198a5494dcdSEric W. Biederman .maxlen = 4*sizeof(int), 199a5494dcdSEric W. Biederman .mode = 0644, 2008c81ddd2SWaiman Long .proc_handler = proc_ipc_sem_dointvec, 201a5494dcdSEric W. Biederman }, 20203f59566SStanislav Kinsbursky #ifdef CONFIG_CHECKPOINT_RESTORE 20303f59566SStanislav Kinsbursky { 20403f59566SStanislav Kinsbursky .procname = "sem_next_id", 20503f59566SStanislav Kinsbursky .data = &init_ipc_ns.ids[IPC_SEM_IDS].next_id, 20603f59566SStanislav Kinsbursky .maxlen = sizeof(init_ipc_ns.ids[IPC_SEM_IDS].next_id), 20703f59566SStanislav Kinsbursky .mode = 0644, 20803f59566SStanislav Kinsbursky .proc_handler = proc_ipc_dointvec_minmax, 20903f59566SStanislav Kinsbursky .extra1 = &zero, 21003f59566SStanislav Kinsbursky .extra2 = &int_max, 21103f59566SStanislav Kinsbursky }, 21203f59566SStanislav Kinsbursky { 21303f59566SStanislav Kinsbursky .procname = "msg_next_id", 21403f59566SStanislav Kinsbursky .data = &init_ipc_ns.ids[IPC_MSG_IDS].next_id, 21503f59566SStanislav Kinsbursky .maxlen = sizeof(init_ipc_ns.ids[IPC_MSG_IDS].next_id), 21603f59566SStanislav Kinsbursky .mode = 0644, 21703f59566SStanislav Kinsbursky .proc_handler = proc_ipc_dointvec_minmax, 21803f59566SStanislav Kinsbursky .extra1 = &zero, 21903f59566SStanislav Kinsbursky .extra2 = &int_max, 22003f59566SStanislav Kinsbursky }, 22103f59566SStanislav Kinsbursky { 22203f59566SStanislav Kinsbursky .procname = "shm_next_id", 22303f59566SStanislav Kinsbursky .data = &init_ipc_ns.ids[IPC_SHM_IDS].next_id, 22403f59566SStanislav Kinsbursky .maxlen = sizeof(init_ipc_ns.ids[IPC_SHM_IDS].next_id), 22503f59566SStanislav Kinsbursky .mode = 0644, 22603f59566SStanislav Kinsbursky .proc_handler = proc_ipc_dointvec_minmax, 22703f59566SStanislav Kinsbursky .extra1 = &zero, 22803f59566SStanislav Kinsbursky .extra2 = &int_max, 22903f59566SStanislav Kinsbursky }, 23003f59566SStanislav Kinsbursky #endif 231a5494dcdSEric W. Biederman {} 232a5494dcdSEric W. Biederman }; 233a5494dcdSEric W. Biederman 234a5494dcdSEric W. Biederman static struct ctl_table ipc_root_table[] = { 235a5494dcdSEric W. Biederman { 236a5494dcdSEric W. Biederman .procname = "kernel", 237a5494dcdSEric W. Biederman .mode = 0555, 238a5494dcdSEric W. Biederman .child = ipc_kern_table, 239a5494dcdSEric W. Biederman }, 240a5494dcdSEric W. Biederman {} 241a5494dcdSEric W. Biederman }; 242a5494dcdSEric W. Biederman 243a5494dcdSEric W. Biederman static int __init ipc_sysctl_init(void) 244a5494dcdSEric W. Biederman { 2450b4d4147SEric W. Biederman register_sysctl_table(ipc_root_table); 246a5494dcdSEric W. Biederman return 0; 247a5494dcdSEric W. Biederman } 248a5494dcdSEric W. Biederman 2496d08a256SDavidlohr Bueso device_initcall(ipc_sysctl_init); 250*5ac893b8SWaiman Long 251*5ac893b8SWaiman Long static int __init ipc_mni_extend(char *str) 252*5ac893b8SWaiman Long { 253*5ac893b8SWaiman Long ipc_mni = IPCMNI_EXTEND; 254*5ac893b8SWaiman Long ipc_mni_shift = IPCMNI_EXTEND_SHIFT; 255*5ac893b8SWaiman Long pr_info("IPCMNI extended to %d.\n", ipc_mni); 256*5ac893b8SWaiman Long return 0; 257*5ac893b8SWaiman Long } 258*5ac893b8SWaiman Long early_param("ipcmni_extend", ipc_mni_extend); 259