18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2007 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Author: Eric Biederman <ebiederm@xmision.com> 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/module.h> 98c2ecf20Sopenharmony_ci#include <linux/ipc.h> 108c2ecf20Sopenharmony_ci#include <linux/nsproxy.h> 118c2ecf20Sopenharmony_ci#include <linux/sysctl.h> 128c2ecf20Sopenharmony_ci#include <linux/uaccess.h> 138c2ecf20Sopenharmony_ci#include <linux/ipc_namespace.h> 148c2ecf20Sopenharmony_ci#include <linux/msg.h> 158c2ecf20Sopenharmony_ci#include "util.h" 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_cistatic void *get_ipc(struct ctl_table *table) 188c2ecf20Sopenharmony_ci{ 198c2ecf20Sopenharmony_ci char *which = table->data; 208c2ecf20Sopenharmony_ci struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns; 218c2ecf20Sopenharmony_ci which = (which - (char *)&init_ipc_ns) + (char *)ipc_ns; 228c2ecf20Sopenharmony_ci return which; 238c2ecf20Sopenharmony_ci} 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#ifdef CONFIG_PROC_SYSCTL 268c2ecf20Sopenharmony_cistatic int proc_ipc_dointvec(struct ctl_table *table, int write, 278c2ecf20Sopenharmony_ci void *buffer, size_t *lenp, loff_t *ppos) 288c2ecf20Sopenharmony_ci{ 298c2ecf20Sopenharmony_ci struct ctl_table ipc_table; 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci memcpy(&ipc_table, table, sizeof(ipc_table)); 328c2ecf20Sopenharmony_ci ipc_table.data = get_ipc(table); 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci return proc_dointvec(&ipc_table, write, buffer, lenp, ppos); 358c2ecf20Sopenharmony_ci} 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_cistatic int proc_ipc_dointvec_minmax(struct ctl_table *table, int write, 388c2ecf20Sopenharmony_ci void *buffer, size_t *lenp, loff_t *ppos) 398c2ecf20Sopenharmony_ci{ 408c2ecf20Sopenharmony_ci struct ctl_table ipc_table; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci memcpy(&ipc_table, table, sizeof(ipc_table)); 438c2ecf20Sopenharmony_ci ipc_table.data = get_ipc(table); 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci return proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos); 468c2ecf20Sopenharmony_ci} 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_cistatic int proc_ipc_dointvec_minmax_orphans(struct ctl_table *table, int write, 498c2ecf20Sopenharmony_ci void *buffer, size_t *lenp, loff_t *ppos) 508c2ecf20Sopenharmony_ci{ 518c2ecf20Sopenharmony_ci struct ipc_namespace *ns = current->nsproxy->ipc_ns; 528c2ecf20Sopenharmony_ci int err = proc_ipc_dointvec_minmax(table, write, buffer, lenp, ppos); 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci if (err < 0) 558c2ecf20Sopenharmony_ci return err; 568c2ecf20Sopenharmony_ci if (ns->shm_rmid_forced) 578c2ecf20Sopenharmony_ci shm_destroy_orphaned(ns); 588c2ecf20Sopenharmony_ci return err; 598c2ecf20Sopenharmony_ci} 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_cistatic int proc_ipc_doulongvec_minmax(struct ctl_table *table, int write, 628c2ecf20Sopenharmony_ci void *buffer, size_t *lenp, loff_t *ppos) 638c2ecf20Sopenharmony_ci{ 648c2ecf20Sopenharmony_ci struct ctl_table ipc_table; 658c2ecf20Sopenharmony_ci memcpy(&ipc_table, table, sizeof(ipc_table)); 668c2ecf20Sopenharmony_ci ipc_table.data = get_ipc(table); 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci return proc_doulongvec_minmax(&ipc_table, write, buffer, 698c2ecf20Sopenharmony_ci lenp, ppos); 708c2ecf20Sopenharmony_ci} 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_cistatic int proc_ipc_auto_msgmni(struct ctl_table *table, int write, 738c2ecf20Sopenharmony_ci void *buffer, size_t *lenp, loff_t *ppos) 748c2ecf20Sopenharmony_ci{ 758c2ecf20Sopenharmony_ci struct ctl_table ipc_table; 768c2ecf20Sopenharmony_ci int dummy = 0; 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci memcpy(&ipc_table, table, sizeof(ipc_table)); 798c2ecf20Sopenharmony_ci ipc_table.data = &dummy; 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci if (write) 828c2ecf20Sopenharmony_ci pr_info_once("writing to auto_msgmni has no effect"); 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci return proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos); 858c2ecf20Sopenharmony_ci} 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_cistatic int proc_ipc_sem_dointvec(struct ctl_table *table, int write, 888c2ecf20Sopenharmony_ci void *buffer, size_t *lenp, loff_t *ppos) 898c2ecf20Sopenharmony_ci{ 908c2ecf20Sopenharmony_ci int ret, semmni; 918c2ecf20Sopenharmony_ci struct ipc_namespace *ns = current->nsproxy->ipc_ns; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci semmni = ns->sem_ctls[3]; 948c2ecf20Sopenharmony_ci ret = proc_ipc_dointvec(table, write, buffer, lenp, ppos); 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci if (!ret) 978c2ecf20Sopenharmony_ci ret = sem_check_semmni(current->nsproxy->ipc_ns); 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci /* 1008c2ecf20Sopenharmony_ci * Reset the semmni value if an error happens. 1018c2ecf20Sopenharmony_ci */ 1028c2ecf20Sopenharmony_ci if (ret) 1038c2ecf20Sopenharmony_ci ns->sem_ctls[3] = semmni; 1048c2ecf20Sopenharmony_ci return ret; 1058c2ecf20Sopenharmony_ci} 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci#else 1088c2ecf20Sopenharmony_ci#define proc_ipc_doulongvec_minmax NULL 1098c2ecf20Sopenharmony_ci#define proc_ipc_dointvec NULL 1108c2ecf20Sopenharmony_ci#define proc_ipc_dointvec_minmax NULL 1118c2ecf20Sopenharmony_ci#define proc_ipc_dointvec_minmax_orphans NULL 1128c2ecf20Sopenharmony_ci#define proc_ipc_auto_msgmni NULL 1138c2ecf20Sopenharmony_ci#define proc_ipc_sem_dointvec NULL 1148c2ecf20Sopenharmony_ci#endif 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ciint ipc_mni = IPCMNI; 1178c2ecf20Sopenharmony_ciint ipc_mni_shift = IPCMNI_SHIFT; 1188c2ecf20Sopenharmony_ciint ipc_min_cycle = RADIX_TREE_MAP_SIZE; 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_cistatic struct ctl_table ipc_kern_table[] = { 1218c2ecf20Sopenharmony_ci { 1228c2ecf20Sopenharmony_ci .procname = "shmmax", 1238c2ecf20Sopenharmony_ci .data = &init_ipc_ns.shm_ctlmax, 1248c2ecf20Sopenharmony_ci .maxlen = sizeof(init_ipc_ns.shm_ctlmax), 1258c2ecf20Sopenharmony_ci .mode = 0644, 1268c2ecf20Sopenharmony_ci .proc_handler = proc_ipc_doulongvec_minmax, 1278c2ecf20Sopenharmony_ci }, 1288c2ecf20Sopenharmony_ci { 1298c2ecf20Sopenharmony_ci .procname = "shmall", 1308c2ecf20Sopenharmony_ci .data = &init_ipc_ns.shm_ctlall, 1318c2ecf20Sopenharmony_ci .maxlen = sizeof(init_ipc_ns.shm_ctlall), 1328c2ecf20Sopenharmony_ci .mode = 0644, 1338c2ecf20Sopenharmony_ci .proc_handler = proc_ipc_doulongvec_minmax, 1348c2ecf20Sopenharmony_ci }, 1358c2ecf20Sopenharmony_ci { 1368c2ecf20Sopenharmony_ci .procname = "shmmni", 1378c2ecf20Sopenharmony_ci .data = &init_ipc_ns.shm_ctlmni, 1388c2ecf20Sopenharmony_ci .maxlen = sizeof(init_ipc_ns.shm_ctlmni), 1398c2ecf20Sopenharmony_ci .mode = 0644, 1408c2ecf20Sopenharmony_ci .proc_handler = proc_ipc_dointvec_minmax, 1418c2ecf20Sopenharmony_ci .extra1 = SYSCTL_ZERO, 1428c2ecf20Sopenharmony_ci .extra2 = &ipc_mni, 1438c2ecf20Sopenharmony_ci }, 1448c2ecf20Sopenharmony_ci { 1458c2ecf20Sopenharmony_ci .procname = "shm_rmid_forced", 1468c2ecf20Sopenharmony_ci .data = &init_ipc_ns.shm_rmid_forced, 1478c2ecf20Sopenharmony_ci .maxlen = sizeof(init_ipc_ns.shm_rmid_forced), 1488c2ecf20Sopenharmony_ci .mode = 0644, 1498c2ecf20Sopenharmony_ci .proc_handler = proc_ipc_dointvec_minmax_orphans, 1508c2ecf20Sopenharmony_ci .extra1 = SYSCTL_ZERO, 1518c2ecf20Sopenharmony_ci .extra2 = SYSCTL_ONE, 1528c2ecf20Sopenharmony_ci }, 1538c2ecf20Sopenharmony_ci { 1548c2ecf20Sopenharmony_ci .procname = "msgmax", 1558c2ecf20Sopenharmony_ci .data = &init_ipc_ns.msg_ctlmax, 1568c2ecf20Sopenharmony_ci .maxlen = sizeof(init_ipc_ns.msg_ctlmax), 1578c2ecf20Sopenharmony_ci .mode = 0644, 1588c2ecf20Sopenharmony_ci .proc_handler = proc_ipc_dointvec_minmax, 1598c2ecf20Sopenharmony_ci .extra1 = SYSCTL_ZERO, 1608c2ecf20Sopenharmony_ci .extra2 = SYSCTL_INT_MAX, 1618c2ecf20Sopenharmony_ci }, 1628c2ecf20Sopenharmony_ci { 1638c2ecf20Sopenharmony_ci .procname = "msgmni", 1648c2ecf20Sopenharmony_ci .data = &init_ipc_ns.msg_ctlmni, 1658c2ecf20Sopenharmony_ci .maxlen = sizeof(init_ipc_ns.msg_ctlmni), 1668c2ecf20Sopenharmony_ci .mode = 0644, 1678c2ecf20Sopenharmony_ci .proc_handler = proc_ipc_dointvec_minmax, 1688c2ecf20Sopenharmony_ci .extra1 = SYSCTL_ZERO, 1698c2ecf20Sopenharmony_ci .extra2 = &ipc_mni, 1708c2ecf20Sopenharmony_ci }, 1718c2ecf20Sopenharmony_ci { 1728c2ecf20Sopenharmony_ci .procname = "auto_msgmni", 1738c2ecf20Sopenharmony_ci .data = NULL, 1748c2ecf20Sopenharmony_ci .maxlen = sizeof(int), 1758c2ecf20Sopenharmony_ci .mode = 0644, 1768c2ecf20Sopenharmony_ci .proc_handler = proc_ipc_auto_msgmni, 1778c2ecf20Sopenharmony_ci .extra1 = SYSCTL_ZERO, 1788c2ecf20Sopenharmony_ci .extra2 = SYSCTL_ONE, 1798c2ecf20Sopenharmony_ci }, 1808c2ecf20Sopenharmony_ci { 1818c2ecf20Sopenharmony_ci .procname = "msgmnb", 1828c2ecf20Sopenharmony_ci .data = &init_ipc_ns.msg_ctlmnb, 1838c2ecf20Sopenharmony_ci .maxlen = sizeof(init_ipc_ns.msg_ctlmnb), 1848c2ecf20Sopenharmony_ci .mode = 0644, 1858c2ecf20Sopenharmony_ci .proc_handler = proc_ipc_dointvec_minmax, 1868c2ecf20Sopenharmony_ci .extra1 = SYSCTL_ZERO, 1878c2ecf20Sopenharmony_ci .extra2 = SYSCTL_INT_MAX, 1888c2ecf20Sopenharmony_ci }, 1898c2ecf20Sopenharmony_ci { 1908c2ecf20Sopenharmony_ci .procname = "sem", 1918c2ecf20Sopenharmony_ci .data = &init_ipc_ns.sem_ctls, 1928c2ecf20Sopenharmony_ci .maxlen = 4*sizeof(int), 1938c2ecf20Sopenharmony_ci .mode = 0644, 1948c2ecf20Sopenharmony_ci .proc_handler = proc_ipc_sem_dointvec, 1958c2ecf20Sopenharmony_ci }, 1968c2ecf20Sopenharmony_ci#ifdef CONFIG_CHECKPOINT_RESTORE 1978c2ecf20Sopenharmony_ci { 1988c2ecf20Sopenharmony_ci .procname = "sem_next_id", 1998c2ecf20Sopenharmony_ci .data = &init_ipc_ns.ids[IPC_SEM_IDS].next_id, 2008c2ecf20Sopenharmony_ci .maxlen = sizeof(init_ipc_ns.ids[IPC_SEM_IDS].next_id), 2018c2ecf20Sopenharmony_ci .mode = 0644, 2028c2ecf20Sopenharmony_ci .proc_handler = proc_ipc_dointvec_minmax, 2038c2ecf20Sopenharmony_ci .extra1 = SYSCTL_ZERO, 2048c2ecf20Sopenharmony_ci .extra2 = SYSCTL_INT_MAX, 2058c2ecf20Sopenharmony_ci }, 2068c2ecf20Sopenharmony_ci { 2078c2ecf20Sopenharmony_ci .procname = "msg_next_id", 2088c2ecf20Sopenharmony_ci .data = &init_ipc_ns.ids[IPC_MSG_IDS].next_id, 2098c2ecf20Sopenharmony_ci .maxlen = sizeof(init_ipc_ns.ids[IPC_MSG_IDS].next_id), 2108c2ecf20Sopenharmony_ci .mode = 0644, 2118c2ecf20Sopenharmony_ci .proc_handler = proc_ipc_dointvec_minmax, 2128c2ecf20Sopenharmony_ci .extra1 = SYSCTL_ZERO, 2138c2ecf20Sopenharmony_ci .extra2 = SYSCTL_INT_MAX, 2148c2ecf20Sopenharmony_ci }, 2158c2ecf20Sopenharmony_ci { 2168c2ecf20Sopenharmony_ci .procname = "shm_next_id", 2178c2ecf20Sopenharmony_ci .data = &init_ipc_ns.ids[IPC_SHM_IDS].next_id, 2188c2ecf20Sopenharmony_ci .maxlen = sizeof(init_ipc_ns.ids[IPC_SHM_IDS].next_id), 2198c2ecf20Sopenharmony_ci .mode = 0644, 2208c2ecf20Sopenharmony_ci .proc_handler = proc_ipc_dointvec_minmax, 2218c2ecf20Sopenharmony_ci .extra1 = SYSCTL_ZERO, 2228c2ecf20Sopenharmony_ci .extra2 = SYSCTL_INT_MAX, 2238c2ecf20Sopenharmony_ci }, 2248c2ecf20Sopenharmony_ci#endif 2258c2ecf20Sopenharmony_ci {} 2268c2ecf20Sopenharmony_ci}; 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_cistatic struct ctl_table ipc_root_table[] = { 2298c2ecf20Sopenharmony_ci { 2308c2ecf20Sopenharmony_ci .procname = "kernel", 2318c2ecf20Sopenharmony_ci .mode = 0555, 2328c2ecf20Sopenharmony_ci .child = ipc_kern_table, 2338c2ecf20Sopenharmony_ci }, 2348c2ecf20Sopenharmony_ci {} 2358c2ecf20Sopenharmony_ci}; 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_cistatic int __init ipc_sysctl_init(void) 2388c2ecf20Sopenharmony_ci{ 2398c2ecf20Sopenharmony_ci register_sysctl_table(ipc_root_table); 2408c2ecf20Sopenharmony_ci return 0; 2418c2ecf20Sopenharmony_ci} 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_cidevice_initcall(ipc_sysctl_init); 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_cistatic int __init ipc_mni_extend(char *str) 2468c2ecf20Sopenharmony_ci{ 2478c2ecf20Sopenharmony_ci ipc_mni = IPCMNI_EXTEND; 2488c2ecf20Sopenharmony_ci ipc_mni_shift = IPCMNI_EXTEND_SHIFT; 2498c2ecf20Sopenharmony_ci ipc_min_cycle = IPCMNI_EXTEND_MIN_CYCLE; 2508c2ecf20Sopenharmony_ci pr_info("IPCMNI extended to %d.\n", ipc_mni); 2518c2ecf20Sopenharmony_ci return 0; 2528c2ecf20Sopenharmony_ci} 2538c2ecf20Sopenharmony_ciearly_param("ipcmni_extend", ipc_mni_extend); 254