1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2007 4 * 5 * Author: Eric Biederman <ebiederm@xmision.com> 6 */ 7 8 #include <linux/module.h> 9 #include <linux/ipc.h> 10 #include <linux/nsproxy.h> 11 #include <linux/sysctl.h> 12 #include <linux/uaccess.h> 13 #include <linux/capability.h> 14 #include <linux/ipc_namespace.h> 15 #include <linux/msg.h> 16 #include "util.h" 17 18 static void *get_ipc(struct ctl_table *table) 19 { 20 char *which = table->data; 21 struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns; 22 which = (which - (char *)&init_ipc_ns) + (char *)ipc_ns; 23 return which; 24 } 25 26 static int proc_ipc_dointvec(struct ctl_table *table, int write, 27 void *buffer, size_t *lenp, loff_t *ppos) 28 { 29 struct ctl_table ipc_table; 30 31 memcpy(&ipc_table, table, sizeof(ipc_table)); 32 ipc_table.data = get_ipc(table); 33 34 return proc_dointvec(&ipc_table, write, buffer, lenp, ppos); 35 } 36 37 static int proc_ipc_dointvec_minmax(struct ctl_table *table, int write, 38 void *buffer, size_t *lenp, loff_t *ppos) 39 { 40 struct ctl_table ipc_table; 41 42 memcpy(&ipc_table, table, sizeof(ipc_table)); 43 ipc_table.data = get_ipc(table); 44 45 return proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos); 46 } 47 48 static int proc_ipc_dointvec_minmax_orphans(struct ctl_table *table, int write, 49 void *buffer, size_t *lenp, loff_t *ppos) 50 { 51 struct ipc_namespace *ns = current->nsproxy->ipc_ns; 52 int err = proc_ipc_dointvec_minmax(table, write, buffer, lenp, ppos); 53 54 if (err < 0) 55 return err; 56 if (ns->shm_rmid_forced) 57 shm_destroy_orphaned(ns); 58 return err; 59 } 60 61 static int proc_ipc_doulongvec_minmax(struct ctl_table *table, int write, 62 void *buffer, size_t *lenp, loff_t *ppos) 63 { 64 struct ctl_table ipc_table; 65 memcpy(&ipc_table, table, sizeof(ipc_table)); 66 ipc_table.data = get_ipc(table); 67 68 return proc_doulongvec_minmax(&ipc_table, write, buffer, 69 lenp, ppos); 70 } 71 72 static int proc_ipc_auto_msgmni(struct ctl_table *table, int write, 73 void *buffer, size_t *lenp, loff_t *ppos) 74 { 75 struct ctl_table ipc_table; 76 int dummy = 0; 77 78 memcpy(&ipc_table, table, sizeof(ipc_table)); 79 ipc_table.data = &dummy; 80 81 if (write) 82 pr_info_once("writing to auto_msgmni has no effect"); 83 84 return proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos); 85 } 86 87 static int proc_ipc_sem_dointvec(struct ctl_table *table, int write, 88 void *buffer, size_t *lenp, loff_t *ppos) 89 { 90 int ret, semmni; 91 struct ipc_namespace *ns = current->nsproxy->ipc_ns; 92 93 semmni = ns->sem_ctls[3]; 94 ret = proc_ipc_dointvec(table, write, buffer, lenp, ppos); 95 96 if (!ret) 97 ret = sem_check_semmni(current->nsproxy->ipc_ns); 98 99 /* 100 * Reset the semmni value if an error happens. 101 */ 102 if (ret) 103 ns->sem_ctls[3] = semmni; 104 return ret; 105 } 106 107 #ifdef CONFIG_CHECKPOINT_RESTORE 108 static int proc_ipc_dointvec_minmax_checkpoint_restore(struct ctl_table *table, 109 int write, void *buffer, size_t *lenp, loff_t *ppos) 110 { 111 struct user_namespace *user_ns = current->nsproxy->ipc_ns->user_ns; 112 113 if (write && !checkpoint_restore_ns_capable(user_ns)) 114 return -EPERM; 115 116 return proc_ipc_dointvec_minmax(table, write, buffer, lenp, ppos); 117 } 118 #endif 119 120 int ipc_mni = IPCMNI; 121 int ipc_mni_shift = IPCMNI_SHIFT; 122 int ipc_min_cycle = RADIX_TREE_MAP_SIZE; 123 124 static struct ctl_table ipc_kern_table[] = { 125 { 126 .procname = "shmmax", 127 .data = &init_ipc_ns.shm_ctlmax, 128 .maxlen = sizeof(init_ipc_ns.shm_ctlmax), 129 .mode = 0644, 130 .proc_handler = proc_ipc_doulongvec_minmax, 131 }, 132 { 133 .procname = "shmall", 134 .data = &init_ipc_ns.shm_ctlall, 135 .maxlen = sizeof(init_ipc_ns.shm_ctlall), 136 .mode = 0644, 137 .proc_handler = proc_ipc_doulongvec_minmax, 138 }, 139 { 140 .procname = "shmmni", 141 .data = &init_ipc_ns.shm_ctlmni, 142 .maxlen = sizeof(init_ipc_ns.shm_ctlmni), 143 .mode = 0644, 144 .proc_handler = proc_ipc_dointvec_minmax, 145 .extra1 = SYSCTL_ZERO, 146 .extra2 = &ipc_mni, 147 }, 148 { 149 .procname = "shm_rmid_forced", 150 .data = &init_ipc_ns.shm_rmid_forced, 151 .maxlen = sizeof(init_ipc_ns.shm_rmid_forced), 152 .mode = 0644, 153 .proc_handler = proc_ipc_dointvec_minmax_orphans, 154 .extra1 = SYSCTL_ZERO, 155 .extra2 = SYSCTL_ONE, 156 }, 157 { 158 .procname = "msgmax", 159 .data = &init_ipc_ns.msg_ctlmax, 160 .maxlen = sizeof(init_ipc_ns.msg_ctlmax), 161 .mode = 0644, 162 .proc_handler = proc_ipc_dointvec_minmax, 163 .extra1 = SYSCTL_ZERO, 164 .extra2 = SYSCTL_INT_MAX, 165 }, 166 { 167 .procname = "msgmni", 168 .data = &init_ipc_ns.msg_ctlmni, 169 .maxlen = sizeof(init_ipc_ns.msg_ctlmni), 170 .mode = 0644, 171 .proc_handler = proc_ipc_dointvec_minmax, 172 .extra1 = SYSCTL_ZERO, 173 .extra2 = &ipc_mni, 174 }, 175 { 176 .procname = "auto_msgmni", 177 .data = NULL, 178 .maxlen = sizeof(int), 179 .mode = 0644, 180 .proc_handler = proc_ipc_auto_msgmni, 181 .extra1 = SYSCTL_ZERO, 182 .extra2 = SYSCTL_ONE, 183 }, 184 { 185 .procname = "msgmnb", 186 .data = &init_ipc_ns.msg_ctlmnb, 187 .maxlen = sizeof(init_ipc_ns.msg_ctlmnb), 188 .mode = 0644, 189 .proc_handler = proc_ipc_dointvec_minmax, 190 .extra1 = SYSCTL_ZERO, 191 .extra2 = SYSCTL_INT_MAX, 192 }, 193 { 194 .procname = "sem", 195 .data = &init_ipc_ns.sem_ctls, 196 .maxlen = 4*sizeof(int), 197 .mode = 0644, 198 .proc_handler = proc_ipc_sem_dointvec, 199 }, 200 #ifdef CONFIG_CHECKPOINT_RESTORE 201 { 202 .procname = "sem_next_id", 203 .data = &init_ipc_ns.ids[IPC_SEM_IDS].next_id, 204 .maxlen = sizeof(init_ipc_ns.ids[IPC_SEM_IDS].next_id), 205 .mode = 0666, 206 .proc_handler = proc_ipc_dointvec_minmax_checkpoint_restore, 207 .extra1 = SYSCTL_ZERO, 208 .extra2 = SYSCTL_INT_MAX, 209 }, 210 { 211 .procname = "msg_next_id", 212 .data = &init_ipc_ns.ids[IPC_MSG_IDS].next_id, 213 .maxlen = sizeof(init_ipc_ns.ids[IPC_MSG_IDS].next_id), 214 .mode = 0666, 215 .proc_handler = proc_ipc_dointvec_minmax_checkpoint_restore, 216 .extra1 = SYSCTL_ZERO, 217 .extra2 = SYSCTL_INT_MAX, 218 }, 219 { 220 .procname = "shm_next_id", 221 .data = &init_ipc_ns.ids[IPC_SHM_IDS].next_id, 222 .maxlen = sizeof(init_ipc_ns.ids[IPC_SHM_IDS].next_id), 223 .mode = 0666, 224 .proc_handler = proc_ipc_dointvec_minmax_checkpoint_restore, 225 .extra1 = SYSCTL_ZERO, 226 .extra2 = SYSCTL_INT_MAX, 227 }, 228 #endif 229 {} 230 }; 231 232 static struct ctl_table ipc_root_table[] = { 233 { 234 .procname = "kernel", 235 .mode = 0555, 236 .child = ipc_kern_table, 237 }, 238 {} 239 }; 240 241 static int __init ipc_sysctl_init(void) 242 { 243 register_sysctl_table(ipc_root_table); 244 return 0; 245 } 246 247 device_initcall(ipc_sysctl_init); 248 249 static int __init ipc_mni_extend(char *str) 250 { 251 ipc_mni = IPCMNI_EXTEND; 252 ipc_mni_shift = IPCMNI_EXTEND_SHIFT; 253 ipc_min_cycle = IPCMNI_EXTEND_MIN_CYCLE; 254 pr_info("IPCMNI extended to %d.\n", ipc_mni); 255 return 0; 256 } 257 early_param("ipcmni_extend", ipc_mni_extend); 258