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 76*0050ee05SManfred 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; 80*0050ee05SManfred Spraul int dummy = 0; 819eefe520SNadia Derbey 829eefe520SNadia Derbey memcpy(&ipc_table, table, sizeof(ipc_table)); 83*0050ee05SManfred Spraul ipc_table.data = &dummy; 849eefe520SNadia Derbey 85*0050ee05SManfred Spraul if (write) 86*0050ee05SManfred Spraul pr_info_once("writing to auto_msgmni has no effect"); 879eefe520SNadia Derbey 88*0050ee05SManfred Spraul return proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos); 899eefe520SNadia Derbey } 909eefe520SNadia Derbey 91a5494dcdSEric W. Biederman #else 92a5494dcdSEric W. Biederman #define proc_ipc_doulongvec_minmax NULL 93a5494dcdSEric W. Biederman #define proc_ipc_dointvec NULL 94b34a6b1dSVasiliy Kulikov #define proc_ipc_dointvec_minmax NULL 95b34a6b1dSVasiliy Kulikov #define proc_ipc_dointvec_minmax_orphans NULL 96*0050ee05SManfred Spraul #define proc_ipc_auto_msgmni NULL 97a5494dcdSEric W. Biederman #endif 98a5494dcdSEric W. Biederman 999eefe520SNadia Derbey static int zero; 1009eefe520SNadia Derbey static int one = 1; 10103f59566SStanislav Kinsbursky static int int_max = INT_MAX; 1029eefe520SNadia Derbey 103a5494dcdSEric W. Biederman static struct ctl_table ipc_kern_table[] = { 104a5494dcdSEric W. Biederman { 105a5494dcdSEric W. Biederman .procname = "shmmax", 106a5494dcdSEric W. Biederman .data = &init_ipc_ns.shm_ctlmax, 107a5494dcdSEric W. Biederman .maxlen = sizeof(init_ipc_ns.shm_ctlmax), 108a5494dcdSEric W. Biederman .mode = 0644, 109a5494dcdSEric W. Biederman .proc_handler = proc_ipc_doulongvec_minmax, 110a5494dcdSEric W. Biederman }, 111a5494dcdSEric W. Biederman { 112a5494dcdSEric W. Biederman .procname = "shmall", 113a5494dcdSEric W. Biederman .data = &init_ipc_ns.shm_ctlall, 114a5494dcdSEric W. Biederman .maxlen = sizeof(init_ipc_ns.shm_ctlall), 115a5494dcdSEric W. Biederman .mode = 0644, 116a5494dcdSEric W. Biederman .proc_handler = proc_ipc_doulongvec_minmax, 117a5494dcdSEric W. Biederman }, 118a5494dcdSEric W. Biederman { 119a5494dcdSEric W. Biederman .procname = "shmmni", 120a5494dcdSEric W. Biederman .data = &init_ipc_ns.shm_ctlmni, 121a5494dcdSEric W. Biederman .maxlen = sizeof(init_ipc_ns.shm_ctlmni), 122a5494dcdSEric W. Biederman .mode = 0644, 123a5494dcdSEric W. Biederman .proc_handler = proc_ipc_dointvec, 124a5494dcdSEric W. Biederman }, 125a5494dcdSEric W. Biederman { 126b34a6b1dSVasiliy Kulikov .procname = "shm_rmid_forced", 127b34a6b1dSVasiliy Kulikov .data = &init_ipc_ns.shm_rmid_forced, 128b34a6b1dSVasiliy Kulikov .maxlen = sizeof(init_ipc_ns.shm_rmid_forced), 129b34a6b1dSVasiliy Kulikov .mode = 0644, 130b34a6b1dSVasiliy Kulikov .proc_handler = proc_ipc_dointvec_minmax_orphans, 131b34a6b1dSVasiliy Kulikov .extra1 = &zero, 132b34a6b1dSVasiliy Kulikov .extra2 = &one, 133b34a6b1dSVasiliy Kulikov }, 134b34a6b1dSVasiliy Kulikov { 135a5494dcdSEric W. Biederman .procname = "msgmax", 136a5494dcdSEric W. Biederman .data = &init_ipc_ns.msg_ctlmax, 137a5494dcdSEric W. Biederman .maxlen = sizeof(init_ipc_ns.msg_ctlmax), 138a5494dcdSEric W. Biederman .mode = 0644, 1399bf76ca3SMathias Krause .proc_handler = proc_ipc_dointvec_minmax, 1409bf76ca3SMathias Krause .extra1 = &zero, 1419bf76ca3SMathias Krause .extra2 = &int_max, 142a5494dcdSEric W. Biederman }, 143a5494dcdSEric W. Biederman { 144a5494dcdSEric W. Biederman .procname = "msgmni", 145a5494dcdSEric W. Biederman .data = &init_ipc_ns.msg_ctlmni, 146a5494dcdSEric W. Biederman .maxlen = sizeof(init_ipc_ns.msg_ctlmni), 147a5494dcdSEric W. Biederman .mode = 0644, 148*0050ee05SManfred Spraul .proc_handler = proc_ipc_dointvec_minmax, 1499bf76ca3SMathias Krause .extra1 = &zero, 1509bf76ca3SMathias Krause .extra2 = &int_max, 151a5494dcdSEric W. Biederman }, 152a5494dcdSEric W. Biederman { 153*0050ee05SManfred Spraul .procname = "auto_msgmni", 154*0050ee05SManfred Spraul .data = NULL, 155*0050ee05SManfred Spraul .maxlen = sizeof(int), 156*0050ee05SManfred Spraul .mode = 0644, 157*0050ee05SManfred Spraul .proc_handler = proc_ipc_auto_msgmni, 158*0050ee05SManfred Spraul .extra1 = &zero, 159*0050ee05SManfred Spraul .extra2 = &one, 160*0050ee05SManfred Spraul }, 161*0050ee05SManfred Spraul { 162a5494dcdSEric W. Biederman .procname = "msgmnb", 163a5494dcdSEric W. Biederman .data = &init_ipc_ns.msg_ctlmnb, 164a5494dcdSEric W. Biederman .maxlen = sizeof(init_ipc_ns.msg_ctlmnb), 165a5494dcdSEric W. Biederman .mode = 0644, 1669bf76ca3SMathias Krause .proc_handler = proc_ipc_dointvec_minmax, 1679bf76ca3SMathias Krause .extra1 = &zero, 1689bf76ca3SMathias Krause .extra2 = &int_max, 169a5494dcdSEric W. Biederman }, 170a5494dcdSEric W. Biederman { 171a5494dcdSEric W. Biederman .procname = "sem", 172a5494dcdSEric W. Biederman .data = &init_ipc_ns.sem_ctls, 173a5494dcdSEric W. Biederman .maxlen = 4*sizeof(int), 174a5494dcdSEric W. Biederman .mode = 0644, 175a5494dcdSEric W. Biederman .proc_handler = proc_ipc_dointvec, 176a5494dcdSEric W. Biederman }, 17703f59566SStanislav Kinsbursky #ifdef CONFIG_CHECKPOINT_RESTORE 17803f59566SStanislav Kinsbursky { 17903f59566SStanislav Kinsbursky .procname = "sem_next_id", 18003f59566SStanislav Kinsbursky .data = &init_ipc_ns.ids[IPC_SEM_IDS].next_id, 18103f59566SStanislav Kinsbursky .maxlen = sizeof(init_ipc_ns.ids[IPC_SEM_IDS].next_id), 18203f59566SStanislav Kinsbursky .mode = 0644, 18303f59566SStanislav Kinsbursky .proc_handler = proc_ipc_dointvec_minmax, 18403f59566SStanislav Kinsbursky .extra1 = &zero, 18503f59566SStanislav Kinsbursky .extra2 = &int_max, 18603f59566SStanislav Kinsbursky }, 18703f59566SStanislav Kinsbursky { 18803f59566SStanislav Kinsbursky .procname = "msg_next_id", 18903f59566SStanislav Kinsbursky .data = &init_ipc_ns.ids[IPC_MSG_IDS].next_id, 19003f59566SStanislav Kinsbursky .maxlen = sizeof(init_ipc_ns.ids[IPC_MSG_IDS].next_id), 19103f59566SStanislav Kinsbursky .mode = 0644, 19203f59566SStanislav Kinsbursky .proc_handler = proc_ipc_dointvec_minmax, 19303f59566SStanislav Kinsbursky .extra1 = &zero, 19403f59566SStanislav Kinsbursky .extra2 = &int_max, 19503f59566SStanislav Kinsbursky }, 19603f59566SStanislav Kinsbursky { 19703f59566SStanislav Kinsbursky .procname = "shm_next_id", 19803f59566SStanislav Kinsbursky .data = &init_ipc_ns.ids[IPC_SHM_IDS].next_id, 19903f59566SStanislav Kinsbursky .maxlen = sizeof(init_ipc_ns.ids[IPC_SHM_IDS].next_id), 20003f59566SStanislav Kinsbursky .mode = 0644, 20103f59566SStanislav Kinsbursky .proc_handler = proc_ipc_dointvec_minmax, 20203f59566SStanislav Kinsbursky .extra1 = &zero, 20303f59566SStanislav Kinsbursky .extra2 = &int_max, 20403f59566SStanislav Kinsbursky }, 20503f59566SStanislav Kinsbursky #endif 206a5494dcdSEric W. Biederman {} 207a5494dcdSEric W. Biederman }; 208a5494dcdSEric W. Biederman 209a5494dcdSEric W. Biederman static struct ctl_table ipc_root_table[] = { 210a5494dcdSEric W. Biederman { 211a5494dcdSEric W. Biederman .procname = "kernel", 212a5494dcdSEric W. Biederman .mode = 0555, 213a5494dcdSEric W. Biederman .child = ipc_kern_table, 214a5494dcdSEric W. Biederman }, 215a5494dcdSEric W. Biederman {} 216a5494dcdSEric W. Biederman }; 217a5494dcdSEric W. Biederman 218a5494dcdSEric W. Biederman static int __init ipc_sysctl_init(void) 219a5494dcdSEric W. Biederman { 2200b4d4147SEric W. Biederman register_sysctl_table(ipc_root_table); 221a5494dcdSEric W. Biederman return 0; 222a5494dcdSEric W. Biederman } 223a5494dcdSEric W. Biederman 2246d08a256SDavidlohr Bueso device_initcall(ipc_sysctl_init); 225