at v5.2 256 lines 6.2 kB view raw
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/ipc_namespace.h> 14#include <linux/msg.h> 15#include "util.h" 16 17static void *get_ipc(struct ctl_table *table) 18{ 19 char *which = table->data; 20 struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns; 21 which = (which - (char *)&init_ipc_ns) + (char *)ipc_ns; 22 return which; 23} 24 25#ifdef CONFIG_PROC_SYSCTL 26static int proc_ipc_dointvec(struct ctl_table *table, int write, 27 void __user *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 37static int proc_ipc_dointvec_minmax(struct ctl_table *table, int write, 38 void __user *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 48static int proc_ipc_dointvec_minmax_orphans(struct ctl_table *table, int write, 49 void __user *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 61static int proc_ipc_doulongvec_minmax(struct ctl_table *table, int write, 62 void __user *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 72static int proc_ipc_auto_msgmni(struct ctl_table *table, int write, 73 void __user *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 87static int proc_ipc_sem_dointvec(struct ctl_table *table, int write, 88 void __user *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#else 108#define proc_ipc_doulongvec_minmax NULL 109#define proc_ipc_dointvec NULL 110#define proc_ipc_dointvec_minmax NULL 111#define proc_ipc_dointvec_minmax_orphans NULL 112#define proc_ipc_auto_msgmni NULL 113#define proc_ipc_sem_dointvec NULL 114#endif 115 116static int zero; 117static int one = 1; 118static int int_max = INT_MAX; 119int ipc_mni = IPCMNI; 120int ipc_mni_shift = IPCMNI_SHIFT; 121int ipc_min_cycle = RADIX_TREE_MAP_SIZE; 122 123static struct ctl_table ipc_kern_table[] = { 124 { 125 .procname = "shmmax", 126 .data = &init_ipc_ns.shm_ctlmax, 127 .maxlen = sizeof(init_ipc_ns.shm_ctlmax), 128 .mode = 0644, 129 .proc_handler = proc_ipc_doulongvec_minmax, 130 }, 131 { 132 .procname = "shmall", 133 .data = &init_ipc_ns.shm_ctlall, 134 .maxlen = sizeof(init_ipc_ns.shm_ctlall), 135 .mode = 0644, 136 .proc_handler = proc_ipc_doulongvec_minmax, 137 }, 138 { 139 .procname = "shmmni", 140 .data = &init_ipc_ns.shm_ctlmni, 141 .maxlen = sizeof(init_ipc_ns.shm_ctlmni), 142 .mode = 0644, 143 .proc_handler = proc_ipc_dointvec_minmax, 144 .extra1 = &zero, 145 .extra2 = &ipc_mni, 146 }, 147 { 148 .procname = "shm_rmid_forced", 149 .data = &init_ipc_ns.shm_rmid_forced, 150 .maxlen = sizeof(init_ipc_ns.shm_rmid_forced), 151 .mode = 0644, 152 .proc_handler = proc_ipc_dointvec_minmax_orphans, 153 .extra1 = &zero, 154 .extra2 = &one, 155 }, 156 { 157 .procname = "msgmax", 158 .data = &init_ipc_ns.msg_ctlmax, 159 .maxlen = sizeof(init_ipc_ns.msg_ctlmax), 160 .mode = 0644, 161 .proc_handler = proc_ipc_dointvec_minmax, 162 .extra1 = &zero, 163 .extra2 = &int_max, 164 }, 165 { 166 .procname = "msgmni", 167 .data = &init_ipc_ns.msg_ctlmni, 168 .maxlen = sizeof(init_ipc_ns.msg_ctlmni), 169 .mode = 0644, 170 .proc_handler = proc_ipc_dointvec_minmax, 171 .extra1 = &zero, 172 .extra2 = &ipc_mni, 173 }, 174 { 175 .procname = "auto_msgmni", 176 .data = NULL, 177 .maxlen = sizeof(int), 178 .mode = 0644, 179 .proc_handler = proc_ipc_auto_msgmni, 180 .extra1 = &zero, 181 .extra2 = &one, 182 }, 183 { 184 .procname = "msgmnb", 185 .data = &init_ipc_ns.msg_ctlmnb, 186 .maxlen = sizeof(init_ipc_ns.msg_ctlmnb), 187 .mode = 0644, 188 .proc_handler = proc_ipc_dointvec_minmax, 189 .extra1 = &zero, 190 .extra2 = &int_max, 191 }, 192 { 193 .procname = "sem", 194 .data = &init_ipc_ns.sem_ctls, 195 .maxlen = 4*sizeof(int), 196 .mode = 0644, 197 .proc_handler = proc_ipc_sem_dointvec, 198 }, 199#ifdef CONFIG_CHECKPOINT_RESTORE 200 { 201 .procname = "sem_next_id", 202 .data = &init_ipc_ns.ids[IPC_SEM_IDS].next_id, 203 .maxlen = sizeof(init_ipc_ns.ids[IPC_SEM_IDS].next_id), 204 .mode = 0644, 205 .proc_handler = proc_ipc_dointvec_minmax, 206 .extra1 = &zero, 207 .extra2 = &int_max, 208 }, 209 { 210 .procname = "msg_next_id", 211 .data = &init_ipc_ns.ids[IPC_MSG_IDS].next_id, 212 .maxlen = sizeof(init_ipc_ns.ids[IPC_MSG_IDS].next_id), 213 .mode = 0644, 214 .proc_handler = proc_ipc_dointvec_minmax, 215 .extra1 = &zero, 216 .extra2 = &int_max, 217 }, 218 { 219 .procname = "shm_next_id", 220 .data = &init_ipc_ns.ids[IPC_SHM_IDS].next_id, 221 .maxlen = sizeof(init_ipc_ns.ids[IPC_SHM_IDS].next_id), 222 .mode = 0644, 223 .proc_handler = proc_ipc_dointvec_minmax, 224 .extra1 = &zero, 225 .extra2 = &int_max, 226 }, 227#endif 228 {} 229}; 230 231static struct ctl_table ipc_root_table[] = { 232 { 233 .procname = "kernel", 234 .mode = 0555, 235 .child = ipc_kern_table, 236 }, 237 {} 238}; 239 240static int __init ipc_sysctl_init(void) 241{ 242 register_sysctl_table(ipc_root_table); 243 return 0; 244} 245 246device_initcall(ipc_sysctl_init); 247 248static int __init ipc_mni_extend(char *str) 249{ 250 ipc_mni = IPCMNI_EXTEND; 251 ipc_mni_shift = IPCMNI_EXTEND_SHIFT; 252 ipc_min_cycle = IPCMNI_EXTEND_MIN_CYCLE; 253 pr_info("IPCMNI extended to %d.\n", ipc_mni); 254 return 0; 255} 256early_param("ipcmni_extend", ipc_mni_extend);