1 /* 2 * Copyright (C) 2007 3 * 4 * Author: Eric Biederman <ebiederm@xmision.com> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation, version 2 of the 9 * License. 10 */ 11 12 #include <linux/module.h> 13 #include <linux/ipc.h> 14 #include <linux/nsproxy.h> 15 #include <linux/sysctl.h> 16 #include <linux/uaccess.h> 17 18 #ifdef CONFIG_IPC_NS 19 static void *get_ipc(ctl_table *table) 20 { 21 char *which = table->data; 22 struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns; 23 which = (which - (char *)&init_ipc_ns) + (char *)ipc_ns; 24 return which; 25 } 26 #else 27 #define get_ipc(T) ((T)->data) 28 #endif 29 30 #ifdef CONFIG_PROC_FS 31 static int proc_ipc_dointvec(ctl_table *table, int write, struct file *filp, 32 void __user *buffer, size_t *lenp, loff_t *ppos) 33 { 34 struct ctl_table ipc_table; 35 memcpy(&ipc_table, table, sizeof(ipc_table)); 36 ipc_table.data = get_ipc(table); 37 38 return proc_dointvec(&ipc_table, write, filp, buffer, lenp, ppos); 39 } 40 41 static int proc_ipc_doulongvec_minmax(ctl_table *table, int write, 42 struct file *filp, void __user *buffer, size_t *lenp, loff_t *ppos) 43 { 44 struct ctl_table ipc_table; 45 memcpy(&ipc_table, table, sizeof(ipc_table)); 46 ipc_table.data = get_ipc(table); 47 48 return proc_doulongvec_minmax(&ipc_table, write, filp, buffer, 49 lenp, ppos); 50 } 51 52 #else 53 #define proc_ipc_doulongvec_minmax NULL 54 #define proc_ipc_dointvec NULL 55 #endif 56 57 #ifdef CONFIG_SYSCTL_SYSCALL 58 /* The generic sysctl ipc data routine. */ 59 static int sysctl_ipc_data(ctl_table *table, int __user *name, int nlen, 60 void __user *oldval, size_t __user *oldlenp, 61 void __user *newval, size_t newlen) 62 { 63 size_t len; 64 void *data; 65 66 /* Get out of I don't have a variable */ 67 if (!table->data || !table->maxlen) 68 return -ENOTDIR; 69 70 data = get_ipc(table); 71 if (!data) 72 return -ENOTDIR; 73 74 if (oldval && oldlenp) { 75 if (get_user(len, oldlenp)) 76 return -EFAULT; 77 if (len) { 78 if (len > table->maxlen) 79 len = table->maxlen; 80 if (copy_to_user(oldval, data, len)) 81 return -EFAULT; 82 if (put_user(len, oldlenp)) 83 return -EFAULT; 84 } 85 } 86 87 if (newval && newlen) { 88 if (newlen > table->maxlen) 89 newlen = table->maxlen; 90 91 if (copy_from_user(data, newval, newlen)) 92 return -EFAULT; 93 } 94 return 1; 95 } 96 #else 97 #define sysctl_ipc_data NULL 98 #endif 99 100 static struct ctl_table ipc_kern_table[] = { 101 { 102 .ctl_name = KERN_SHMMAX, 103 .procname = "shmmax", 104 .data = &init_ipc_ns.shm_ctlmax, 105 .maxlen = sizeof (init_ipc_ns.shm_ctlmax), 106 .mode = 0644, 107 .proc_handler = proc_ipc_doulongvec_minmax, 108 .strategy = sysctl_ipc_data, 109 }, 110 { 111 .ctl_name = KERN_SHMALL, 112 .procname = "shmall", 113 .data = &init_ipc_ns.shm_ctlall, 114 .maxlen = sizeof (init_ipc_ns.shm_ctlall), 115 .mode = 0644, 116 .proc_handler = proc_ipc_doulongvec_minmax, 117 .strategy = sysctl_ipc_data, 118 }, 119 { 120 .ctl_name = KERN_SHMMNI, 121 .procname = "shmmni", 122 .data = &init_ipc_ns.shm_ctlmni, 123 .maxlen = sizeof (init_ipc_ns.shm_ctlmni), 124 .mode = 0644, 125 .proc_handler = proc_ipc_dointvec, 126 .strategy = sysctl_ipc_data, 127 }, 128 { 129 .ctl_name = KERN_MSGMAX, 130 .procname = "msgmax", 131 .data = &init_ipc_ns.msg_ctlmax, 132 .maxlen = sizeof (init_ipc_ns.msg_ctlmax), 133 .mode = 0644, 134 .proc_handler = proc_ipc_dointvec, 135 .strategy = sysctl_ipc_data, 136 }, 137 { 138 .ctl_name = KERN_MSGMNI, 139 .procname = "msgmni", 140 .data = &init_ipc_ns.msg_ctlmni, 141 .maxlen = sizeof (init_ipc_ns.msg_ctlmni), 142 .mode = 0644, 143 .proc_handler = proc_ipc_dointvec, 144 .strategy = sysctl_ipc_data, 145 }, 146 { 147 .ctl_name = KERN_MSGMNB, 148 .procname = "msgmnb", 149 .data = &init_ipc_ns.msg_ctlmnb, 150 .maxlen = sizeof (init_ipc_ns.msg_ctlmnb), 151 .mode = 0644, 152 .proc_handler = proc_ipc_dointvec, 153 .strategy = sysctl_ipc_data, 154 }, 155 { 156 .ctl_name = KERN_SEM, 157 .procname = "sem", 158 .data = &init_ipc_ns.sem_ctls, 159 .maxlen = 4*sizeof (int), 160 .mode = 0644, 161 .proc_handler = proc_ipc_dointvec, 162 .strategy = sysctl_ipc_data, 163 }, 164 {} 165 }; 166 167 static struct ctl_table ipc_root_table[] = { 168 { 169 .ctl_name = CTL_KERN, 170 .procname = "kernel", 171 .mode = 0555, 172 .child = ipc_kern_table, 173 }, 174 {} 175 }; 176 177 static int __init ipc_sysctl_init(void) 178 { 179 register_sysctl_table(ipc_root_table); 180 return 0; 181 } 182 183 __initcall(ipc_sysctl_init); 184