Back to home page

LXR

 
 

    


0001 /*
0002  *  Copyright (C) 2007
0003  *
0004  *  Author: Eric Biederman <ebiederm@xmision.com>
0005  *
0006  *  This program is free software; you can redistribute it and/or
0007  *  modify it under the terms of the GNU General Public License as
0008  *  published by the Free Software Foundation, version 2 of the
0009  *  License.
0010  */
0011 
0012 #include <linux/module.h>
0013 #include <linux/ipc.h>
0014 #include <linux/nsproxy.h>
0015 #include <linux/sysctl.h>
0016 #include <linux/uaccess.h>
0017 #include <linux/ipc_namespace.h>
0018 #include <linux/msg.h>
0019 #include "util.h"
0020 
0021 static void *get_ipc(struct ctl_table *table)
0022 {
0023     char *which = table->data;
0024     struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns;
0025     which = (which - (char *)&init_ipc_ns) + (char *)ipc_ns;
0026     return which;
0027 }
0028 
0029 #ifdef CONFIG_PROC_SYSCTL
0030 static int proc_ipc_dointvec(struct ctl_table *table, int write,
0031     void __user *buffer, size_t *lenp, loff_t *ppos)
0032 {
0033     struct ctl_table ipc_table;
0034 
0035     memcpy(&ipc_table, table, sizeof(ipc_table));
0036     ipc_table.data = get_ipc(table);
0037 
0038     return proc_dointvec(&ipc_table, write, buffer, lenp, ppos);
0039 }
0040 
0041 static int proc_ipc_dointvec_minmax(struct ctl_table *table, int write,
0042     void __user *buffer, size_t *lenp, loff_t *ppos)
0043 {
0044     struct ctl_table ipc_table;
0045 
0046     memcpy(&ipc_table, table, sizeof(ipc_table));
0047     ipc_table.data = get_ipc(table);
0048 
0049     return proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos);
0050 }
0051 
0052 static int proc_ipc_dointvec_minmax_orphans(struct ctl_table *table, int write,
0053     void __user *buffer, size_t *lenp, loff_t *ppos)
0054 {
0055     struct ipc_namespace *ns = current->nsproxy->ipc_ns;
0056     int err = proc_ipc_dointvec_minmax(table, write, buffer, lenp, ppos);
0057 
0058     if (err < 0)
0059         return err;
0060     if (ns->shm_rmid_forced)
0061         shm_destroy_orphaned(ns);
0062     return err;
0063 }
0064 
0065 static int proc_ipc_doulongvec_minmax(struct ctl_table *table, int write,
0066     void __user *buffer, size_t *lenp, loff_t *ppos)
0067 {
0068     struct ctl_table ipc_table;
0069     memcpy(&ipc_table, table, sizeof(ipc_table));
0070     ipc_table.data = get_ipc(table);
0071 
0072     return proc_doulongvec_minmax(&ipc_table, write, buffer,
0073                     lenp, ppos);
0074 }
0075 
0076 static int proc_ipc_auto_msgmni(struct ctl_table *table, int write,
0077     void __user *buffer, size_t *lenp, loff_t *ppos)
0078 {
0079     struct ctl_table ipc_table;
0080     int dummy = 0;
0081 
0082     memcpy(&ipc_table, table, sizeof(ipc_table));
0083     ipc_table.data = &dummy;
0084 
0085     if (write)
0086         pr_info_once("writing to auto_msgmni has no effect");
0087 
0088     return proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos);
0089 }
0090 
0091 #else
0092 #define proc_ipc_doulongvec_minmax NULL
0093 #define proc_ipc_dointvec      NULL
0094 #define proc_ipc_dointvec_minmax   NULL
0095 #define proc_ipc_dointvec_minmax_orphans   NULL
0096 #define proc_ipc_auto_msgmni       NULL
0097 #endif
0098 
0099 static int zero;
0100 static int one = 1;
0101 static int int_max = INT_MAX;
0102 
0103 static struct ctl_table ipc_kern_table[] = {
0104     {
0105         .procname   = "shmmax",
0106         .data       = &init_ipc_ns.shm_ctlmax,
0107         .maxlen     = sizeof(init_ipc_ns.shm_ctlmax),
0108         .mode       = 0644,
0109         .proc_handler   = proc_ipc_doulongvec_minmax,
0110     },
0111     {
0112         .procname   = "shmall",
0113         .data       = &init_ipc_ns.shm_ctlall,
0114         .maxlen     = sizeof(init_ipc_ns.shm_ctlall),
0115         .mode       = 0644,
0116         .proc_handler   = proc_ipc_doulongvec_minmax,
0117     },
0118     {
0119         .procname   = "shmmni",
0120         .data       = &init_ipc_ns.shm_ctlmni,
0121         .maxlen     = sizeof(init_ipc_ns.shm_ctlmni),
0122         .mode       = 0644,
0123         .proc_handler   = proc_ipc_dointvec,
0124     },
0125     {
0126         .procname   = "shm_rmid_forced",
0127         .data       = &init_ipc_ns.shm_rmid_forced,
0128         .maxlen     = sizeof(init_ipc_ns.shm_rmid_forced),
0129         .mode       = 0644,
0130         .proc_handler   = proc_ipc_dointvec_minmax_orphans,
0131         .extra1     = &zero,
0132         .extra2     = &one,
0133     },
0134     {
0135         .procname   = "msgmax",
0136         .data       = &init_ipc_ns.msg_ctlmax,
0137         .maxlen     = sizeof(init_ipc_ns.msg_ctlmax),
0138         .mode       = 0644,
0139         .proc_handler   = proc_ipc_dointvec_minmax,
0140         .extra1     = &zero,
0141         .extra2     = &int_max,
0142     },
0143     {
0144         .procname   = "msgmni",
0145         .data       = &init_ipc_ns.msg_ctlmni,
0146         .maxlen     = sizeof(init_ipc_ns.msg_ctlmni),
0147         .mode       = 0644,
0148         .proc_handler   = proc_ipc_dointvec_minmax,
0149         .extra1     = &zero,
0150         .extra2     = &int_max,
0151     },
0152     {
0153         .procname   = "auto_msgmni",
0154         .data       = NULL,
0155         .maxlen     = sizeof(int),
0156         .mode       = 0644,
0157         .proc_handler   = proc_ipc_auto_msgmni,
0158         .extra1     = &zero,
0159         .extra2     = &one,
0160     },
0161     {
0162         .procname   =  "msgmnb",
0163         .data       = &init_ipc_ns.msg_ctlmnb,
0164         .maxlen     = sizeof(init_ipc_ns.msg_ctlmnb),
0165         .mode       = 0644,
0166         .proc_handler   = proc_ipc_dointvec_minmax,
0167         .extra1     = &zero,
0168         .extra2     = &int_max,
0169     },
0170     {
0171         .procname   = "sem",
0172         .data       = &init_ipc_ns.sem_ctls,
0173         .maxlen     = 4*sizeof(int),
0174         .mode       = 0644,
0175         .proc_handler   = proc_ipc_dointvec,
0176     },
0177 #ifdef CONFIG_CHECKPOINT_RESTORE
0178     {
0179         .procname   = "sem_next_id",
0180         .data       = &init_ipc_ns.ids[IPC_SEM_IDS].next_id,
0181         .maxlen     = sizeof(init_ipc_ns.ids[IPC_SEM_IDS].next_id),
0182         .mode       = 0644,
0183         .proc_handler   = proc_ipc_dointvec_minmax,
0184         .extra1     = &zero,
0185         .extra2     = &int_max,
0186     },
0187     {
0188         .procname   = "msg_next_id",
0189         .data       = &init_ipc_ns.ids[IPC_MSG_IDS].next_id,
0190         .maxlen     = sizeof(init_ipc_ns.ids[IPC_MSG_IDS].next_id),
0191         .mode       = 0644,
0192         .proc_handler   = proc_ipc_dointvec_minmax,
0193         .extra1     = &zero,
0194         .extra2     = &int_max,
0195     },
0196     {
0197         .procname   = "shm_next_id",
0198         .data       = &init_ipc_ns.ids[IPC_SHM_IDS].next_id,
0199         .maxlen     = sizeof(init_ipc_ns.ids[IPC_SHM_IDS].next_id),
0200         .mode       = 0644,
0201         .proc_handler   = proc_ipc_dointvec_minmax,
0202         .extra1     = &zero,
0203         .extra2     = &int_max,
0204     },
0205 #endif
0206     {}
0207 };
0208 
0209 static struct ctl_table ipc_root_table[] = {
0210     {
0211         .procname   = "kernel",
0212         .mode       = 0555,
0213         .child      = ipc_kern_table,
0214     },
0215     {}
0216 };
0217 
0218 static int __init ipc_sysctl_init(void)
0219 {
0220     register_sysctl_table(ipc_root_table);
0221     return 0;
0222 }
0223 
0224 device_initcall(ipc_sysctl_init);