linux/ipc/ipc_sysctl.c
<<
>>
Prefs
   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#include <linux/ipc_namespace.h>
  18#include <linux/msg.h>
  19#include "util.h"
  20
  21static void *get_ipc(struct ctl_table *table)
  22{
  23        char *which = table->data;
  24        struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns;
  25        which = (which - (char *)&init_ipc_ns) + (char *)ipc_ns;
  26        return which;
  27}
  28
  29#ifdef CONFIG_PROC_SYSCTL
  30static int proc_ipc_dointvec(struct ctl_table *table, int write,
  31        void __user *buffer, size_t *lenp, loff_t *ppos)
  32{
  33        struct ctl_table ipc_table;
  34
  35        memcpy(&ipc_table, table, sizeof(ipc_table));
  36        ipc_table.data = get_ipc(table);
  37
  38        return proc_dointvec(&ipc_table, write, buffer, lenp, ppos);
  39}
  40
  41static int proc_ipc_dointvec_minmax(struct ctl_table *table, int write,
  42        void __user *buffer, size_t *lenp, loff_t *ppos)
  43{
  44        struct ctl_table ipc_table;
  45
  46        memcpy(&ipc_table, table, sizeof(ipc_table));
  47        ipc_table.data = get_ipc(table);
  48
  49        return proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos);
  50}
  51
  52static int proc_ipc_dointvec_minmax_orphans(struct ctl_table *table, int write,
  53        void __user *buffer, size_t *lenp, loff_t *ppos)
  54{
  55        struct ipc_namespace *ns = current->nsproxy->ipc_ns;
  56        int err = proc_ipc_dointvec_minmax(table, write, buffer, lenp, ppos);
  57
  58        if (err < 0)
  59                return err;
  60        if (ns->shm_rmid_forced)
  61                shm_destroy_orphaned(ns);
  62        return err;
  63}
  64
  65static int proc_ipc_doulongvec_minmax(struct ctl_table *table, int write,
  66        void __user *buffer, size_t *lenp, loff_t *ppos)
  67{
  68        struct ctl_table ipc_table;
  69        memcpy(&ipc_table, table, sizeof(ipc_table));
  70        ipc_table.data = get_ipc(table);
  71
  72        return proc_doulongvec_minmax(&ipc_table, write, buffer,
  73                                        lenp, ppos);
  74}
  75
  76static int proc_ipc_auto_msgmni(struct ctl_table *table, int write,
  77        void __user *buffer, size_t *lenp, loff_t *ppos)
  78{
  79        struct ctl_table ipc_table;
  80        int dummy = 0;
  81
  82        memcpy(&ipc_table, table, sizeof(ipc_table));
  83        ipc_table.data = &dummy;
  84
  85        if (write)
  86                pr_info_once("writing to auto_msgmni has no effect");
  87
  88        return proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos);
  89}
  90
  91#else
  92#define proc_ipc_doulongvec_minmax NULL
  93#define proc_ipc_dointvec          NULL
  94#define proc_ipc_dointvec_minmax   NULL
  95#define proc_ipc_dointvec_minmax_orphans   NULL
  96#define proc_ipc_auto_msgmni       NULL
  97#endif
  98
  99static int zero;
 100static int one = 1;
 101static int int_max = INT_MAX;
 102
 103static struct ctl_table ipc_kern_table[] = {
 104        {
 105                .procname       = "shmmax",
 106                .data           = &init_ipc_ns.shm_ctlmax,
 107                .maxlen         = sizeof(init_ipc_ns.shm_ctlmax),
 108                .mode           = 0644,
 109                .proc_handler   = proc_ipc_doulongvec_minmax,
 110        },
 111        {
 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        },
 118        {
 119                .procname       = "shmmni",
 120                .data           = &init_ipc_ns.shm_ctlmni,
 121                .maxlen         = sizeof(init_ipc_ns.shm_ctlmni),
 122                .mode           = 0644,
 123                .proc_handler   = proc_ipc_dointvec,
 124        },
 125        {
 126                .procname       = "shm_rmid_forced",
 127                .data           = &init_ipc_ns.shm_rmid_forced,
 128                .maxlen         = sizeof(init_ipc_ns.shm_rmid_forced),
 129                .mode           = 0644,
 130                .proc_handler   = proc_ipc_dointvec_minmax_orphans,
 131                .extra1         = &zero,
 132                .extra2         = &one,
 133        },
 134        {
 135                .procname       = "msgmax",
 136                .data           = &init_ipc_ns.msg_ctlmax,
 137                .maxlen         = sizeof(init_ipc_ns.msg_ctlmax),
 138                .mode           = 0644,
 139                .proc_handler   = proc_ipc_dointvec_minmax,
 140                .extra1         = &zero,
 141                .extra2         = &int_max,
 142        },
 143        {
 144                .procname       = "msgmni",
 145                .data           = &init_ipc_ns.msg_ctlmni,
 146                .maxlen         = sizeof(init_ipc_ns.msg_ctlmni),
 147                .mode           = 0644,
 148                .proc_handler   = proc_ipc_dointvec_minmax,
 149                .extra1         = &zero,
 150                .extra2         = &int_max,
 151        },
 152        {
 153                .procname       = "auto_msgmni",
 154                .data           = NULL,
 155                .maxlen         = sizeof(int),
 156                .mode           = 0644,
 157                .proc_handler   = proc_ipc_auto_msgmni,
 158                .extra1         = &zero,
 159                .extra2         = &one,
 160        },
 161        {
 162                .procname       =  "msgmnb",
 163                .data           = &init_ipc_ns.msg_ctlmnb,
 164                .maxlen         = sizeof(init_ipc_ns.msg_ctlmnb),
 165                .mode           = 0644,
 166                .proc_handler   = proc_ipc_dointvec_minmax,
 167                .extra1         = &zero,
 168                .extra2         = &int_max,
 169        },
 170        {
 171                .procname       = "sem",
 172                .data           = &init_ipc_ns.sem_ctls,
 173                .maxlen         = 4*sizeof(int),
 174                .mode           = 0644,
 175                .proc_handler   = proc_ipc_dointvec,
 176        },
 177#ifdef CONFIG_CHECKPOINT_RESTORE
 178        {
 179                .procname       = "sem_next_id",
 180                .data           = &init_ipc_ns.ids[IPC_SEM_IDS].next_id,
 181                .maxlen         = sizeof(init_ipc_ns.ids[IPC_SEM_IDS].next_id),
 182                .mode           = 0644,
 183                .proc_handler   = proc_ipc_dointvec_minmax,
 184                .extra1         = &zero,
 185                .extra2         = &int_max,
 186        },
 187        {
 188                .procname       = "msg_next_id",
 189                .data           = &init_ipc_ns.ids[IPC_MSG_IDS].next_id,
 190                .maxlen         = sizeof(init_ipc_ns.ids[IPC_MSG_IDS].next_id),
 191                .mode           = 0644,
 192                .proc_handler   = proc_ipc_dointvec_minmax,
 193                .extra1         = &zero,
 194                .extra2         = &int_max,
 195        },
 196        {
 197                .procname       = "shm_next_id",
 198                .data           = &init_ipc_ns.ids[IPC_SHM_IDS].next_id,
 199                .maxlen         = sizeof(init_ipc_ns.ids[IPC_SHM_IDS].next_id),
 200                .mode           = 0644,
 201                .proc_handler   = proc_ipc_dointvec_minmax,
 202                .extra1         = &zero,
 203                .extra2         = &int_max,
 204        },
 205#endif
 206        {}
 207};
 208
 209static struct ctl_table ipc_root_table[] = {
 210        {
 211                .procname       = "kernel",
 212                .mode           = 0555,
 213                .child          = ipc_kern_table,
 214        },
 215        {}
 216};
 217
 218static int __init ipc_sysctl_init(void)
 219{
 220        register_sysctl_table(ipc_root_table);
 221        return 0;
 222}
 223
 224device_initcall(ipc_sysctl_init);
 225