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 91*8c81ddd2SWaiman Long static int proc_ipc_sem_dointvec(struct ctl_table *table, int write, 92*8c81ddd2SWaiman Long void __user *buffer, size_t *lenp, loff_t *ppos) 93*8c81ddd2SWaiman Long { 94*8c81ddd2SWaiman Long int ret, semmni; 95*8c81ddd2SWaiman Long struct ipc_namespace *ns = current->nsproxy->ipc_ns; 96*8c81ddd2SWaiman Long 97*8c81ddd2SWaiman Long semmni = ns->sem_ctls[3]; 98*8c81ddd2SWaiman Long ret = proc_ipc_dointvec(table, write, buffer, lenp, ppos); 99*8c81ddd2SWaiman Long 100*8c81ddd2SWaiman Long if (!ret) 101*8c81ddd2SWaiman Long ret = sem_check_semmni(current->nsproxy->ipc_ns); 102*8c81ddd2SWaiman Long 103*8c81ddd2SWaiman Long /* 104*8c81ddd2SWaiman Long * Reset the semmni value if an error happens. 105*8c81ddd2SWaiman Long */ 106*8c81ddd2SWaiman Long if (ret) 107*8c81ddd2SWaiman Long ns->sem_ctls[3] = semmni; 108*8c81ddd2SWaiman Long return ret; 109*8c81ddd2SWaiman Long } 110*8c81ddd2SWaiman 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 117*8c81ddd2SWaiman 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; 1236730e658SWaiman Long static int ipc_mni = IPCMNI; 1249eefe520SNadia Derbey 125a5494dcdSEric W. Biederman static struct ctl_table ipc_kern_table[] = { 126a5494dcdSEric W. Biederman { 127a5494dcdSEric W. Biederman .procname = "shmmax", 128a5494dcdSEric W. Biederman .data = &init_ipc_ns.shm_ctlmax, 129a5494dcdSEric W. Biederman .maxlen = sizeof(init_ipc_ns.shm_ctlmax), 130a5494dcdSEric W. Biederman .mode = 0644, 131a5494dcdSEric W. Biederman .proc_handler = proc_ipc_doulongvec_minmax, 132a5494dcdSEric W. Biederman }, 133a5494dcdSEric W. Biederman { 134a5494dcdSEric W. Biederman .procname = "shmall", 135a5494dcdSEric W. Biederman .data = &init_ipc_ns.shm_ctlall, 136a5494dcdSEric W. Biederman .maxlen = sizeof(init_ipc_ns.shm_ctlall), 137a5494dcdSEric W. Biederman .mode = 0644, 138a5494dcdSEric W. Biederman .proc_handler = proc_ipc_doulongvec_minmax, 139a5494dcdSEric W. Biederman }, 140a5494dcdSEric W. Biederman { 141a5494dcdSEric W. Biederman .procname = "shmmni", 142a5494dcdSEric W. Biederman .data = &init_ipc_ns.shm_ctlmni, 143a5494dcdSEric W. Biederman .maxlen = sizeof(init_ipc_ns.shm_ctlmni), 144a5494dcdSEric W. Biederman .mode = 0644, 1456730e658SWaiman Long .proc_handler = proc_ipc_dointvec_minmax, 1466730e658SWaiman Long .extra1 = &zero, 1476730e658SWaiman Long .extra2 = &ipc_mni, 148a5494dcdSEric W. Biederman }, 149a5494dcdSEric W. Biederman { 150b34a6b1dSVasiliy Kulikov .procname = "shm_rmid_forced", 151b34a6b1dSVasiliy Kulikov .data = &init_ipc_ns.shm_rmid_forced, 152b34a6b1dSVasiliy Kulikov .maxlen = sizeof(init_ipc_ns.shm_rmid_forced), 153b34a6b1dSVasiliy Kulikov .mode = 0644, 154b34a6b1dSVasiliy Kulikov .proc_handler = proc_ipc_dointvec_minmax_orphans, 155b34a6b1dSVasiliy Kulikov .extra1 = &zero, 156b34a6b1dSVasiliy Kulikov .extra2 = &one, 157b34a6b1dSVasiliy Kulikov }, 158b34a6b1dSVasiliy Kulikov { 159a5494dcdSEric W. Biederman .procname = "msgmax", 160a5494dcdSEric W. Biederman .data = &init_ipc_ns.msg_ctlmax, 161a5494dcdSEric W. Biederman .maxlen = sizeof(init_ipc_ns.msg_ctlmax), 162a5494dcdSEric W. Biederman .mode = 0644, 1639bf76ca3SMathias Krause .proc_handler = proc_ipc_dointvec_minmax, 1649bf76ca3SMathias Krause .extra1 = &zero, 1659bf76ca3SMathias Krause .extra2 = &int_max, 166a5494dcdSEric W. Biederman }, 167a5494dcdSEric W. Biederman { 168a5494dcdSEric W. Biederman .procname = "msgmni", 169a5494dcdSEric W. Biederman .data = &init_ipc_ns.msg_ctlmni, 170a5494dcdSEric W. Biederman .maxlen = sizeof(init_ipc_ns.msg_ctlmni), 171a5494dcdSEric W. Biederman .mode = 0644, 1720050ee05SManfred Spraul .proc_handler = proc_ipc_dointvec_minmax, 1739bf76ca3SMathias Krause .extra1 = &zero, 1746730e658SWaiman Long .extra2 = &ipc_mni, 175a5494dcdSEric W. Biederman }, 176a5494dcdSEric W. Biederman { 1770050ee05SManfred Spraul .procname = "auto_msgmni", 1780050ee05SManfred Spraul .data = NULL, 1790050ee05SManfred Spraul .maxlen = sizeof(int), 1800050ee05SManfred Spraul .mode = 0644, 1810050ee05SManfred Spraul .proc_handler = proc_ipc_auto_msgmni, 1820050ee05SManfred Spraul .extra1 = &zero, 1830050ee05SManfred Spraul .extra2 = &one, 1840050ee05SManfred Spraul }, 1850050ee05SManfred Spraul { 186a5494dcdSEric W. Biederman .procname = "msgmnb", 187a5494dcdSEric W. Biederman .data = &init_ipc_ns.msg_ctlmnb, 188a5494dcdSEric W. Biederman .maxlen = sizeof(init_ipc_ns.msg_ctlmnb), 189a5494dcdSEric W. Biederman .mode = 0644, 1909bf76ca3SMathias Krause .proc_handler = proc_ipc_dointvec_minmax, 1919bf76ca3SMathias Krause .extra1 = &zero, 1929bf76ca3SMathias Krause .extra2 = &int_max, 193a5494dcdSEric W. Biederman }, 194a5494dcdSEric W. Biederman { 195a5494dcdSEric W. Biederman .procname = "sem", 196a5494dcdSEric W. Biederman .data = &init_ipc_ns.sem_ctls, 197a5494dcdSEric W. Biederman .maxlen = 4*sizeof(int), 198a5494dcdSEric W. Biederman .mode = 0644, 199*8c81ddd2SWaiman Long .proc_handler = proc_ipc_sem_dointvec, 200a5494dcdSEric W. Biederman }, 20103f59566SStanislav Kinsbursky #ifdef CONFIG_CHECKPOINT_RESTORE 20203f59566SStanislav Kinsbursky { 20303f59566SStanislav Kinsbursky .procname = "sem_next_id", 20403f59566SStanislav Kinsbursky .data = &init_ipc_ns.ids[IPC_SEM_IDS].next_id, 20503f59566SStanislav Kinsbursky .maxlen = sizeof(init_ipc_ns.ids[IPC_SEM_IDS].next_id), 20603f59566SStanislav Kinsbursky .mode = 0644, 20703f59566SStanislav Kinsbursky .proc_handler = proc_ipc_dointvec_minmax, 20803f59566SStanislav Kinsbursky .extra1 = &zero, 20903f59566SStanislav Kinsbursky .extra2 = &int_max, 21003f59566SStanislav Kinsbursky }, 21103f59566SStanislav Kinsbursky { 21203f59566SStanislav Kinsbursky .procname = "msg_next_id", 21303f59566SStanislav Kinsbursky .data = &init_ipc_ns.ids[IPC_MSG_IDS].next_id, 21403f59566SStanislav Kinsbursky .maxlen = sizeof(init_ipc_ns.ids[IPC_MSG_IDS].next_id), 21503f59566SStanislav Kinsbursky .mode = 0644, 21603f59566SStanislav Kinsbursky .proc_handler = proc_ipc_dointvec_minmax, 21703f59566SStanislav Kinsbursky .extra1 = &zero, 21803f59566SStanislav Kinsbursky .extra2 = &int_max, 21903f59566SStanislav Kinsbursky }, 22003f59566SStanislav Kinsbursky { 22103f59566SStanislav Kinsbursky .procname = "shm_next_id", 22203f59566SStanislav Kinsbursky .data = &init_ipc_ns.ids[IPC_SHM_IDS].next_id, 22303f59566SStanislav Kinsbursky .maxlen = sizeof(init_ipc_ns.ids[IPC_SHM_IDS].next_id), 22403f59566SStanislav Kinsbursky .mode = 0644, 22503f59566SStanislav Kinsbursky .proc_handler = proc_ipc_dointvec_minmax, 22603f59566SStanislav Kinsbursky .extra1 = &zero, 22703f59566SStanislav Kinsbursky .extra2 = &int_max, 22803f59566SStanislav Kinsbursky }, 22903f59566SStanislav Kinsbursky #endif 230a5494dcdSEric W. Biederman {} 231a5494dcdSEric W. Biederman }; 232a5494dcdSEric W. Biederman 233a5494dcdSEric W. Biederman static struct ctl_table ipc_root_table[] = { 234a5494dcdSEric W. Biederman { 235a5494dcdSEric W. Biederman .procname = "kernel", 236a5494dcdSEric W. Biederman .mode = 0555, 237a5494dcdSEric W. Biederman .child = ipc_kern_table, 238a5494dcdSEric W. Biederman }, 239a5494dcdSEric W. Biederman {} 240a5494dcdSEric W. Biederman }; 241a5494dcdSEric W. Biederman 242a5494dcdSEric W. Biederman static int __init ipc_sysctl_init(void) 243a5494dcdSEric W. Biederman { 2440b4d4147SEric W. Biederman register_sysctl_table(ipc_root_table); 245a5494dcdSEric W. Biederman return 0; 246a5494dcdSEric W. Biederman } 247a5494dcdSEric W. Biederman 2486d08a256SDavidlohr Bueso device_initcall(ipc_sysctl_init); 249