The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/ipc/ipc_sysctl.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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 
   21 static void *get_ipc(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
   30 static int proc_ipc_dointvec(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 
   41 static int proc_ipc_dointvec_minmax(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 
   52 static int proc_ipc_dointvec_minmax_orphans(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 
   65 static int proc_ipc_callback_dointvec(ctl_table *table, int write,
   66         void __user *buffer, size_t *lenp, loff_t *ppos)
   67 {
   68         struct ctl_table ipc_table;
   69         size_t lenp_bef = *lenp;
   70         int rc;
   71 
   72         memcpy(&ipc_table, table, sizeof(ipc_table));
   73         ipc_table.data = get_ipc(table);
   74 
   75         rc = proc_dointvec(&ipc_table, write, buffer, lenp, ppos);
   76 
   77         if (write && !rc && lenp_bef == *lenp)
   78                 /*
   79                  * Tunable has successfully been changed by hand. Disable its
   80                  * automatic adjustment. This simply requires unregistering
   81                  * the notifiers that trigger recalculation.
   82                  */
   83                 unregister_ipcns_notifier(current->nsproxy->ipc_ns);
   84 
   85         return rc;
   86 }
   87 
   88 static int proc_ipc_doulongvec_minmax(ctl_table *table, int write,
   89         void __user *buffer, size_t *lenp, loff_t *ppos)
   90 {
   91         struct ctl_table ipc_table;
   92         memcpy(&ipc_table, table, sizeof(ipc_table));
   93         ipc_table.data = get_ipc(table);
   94 
   95         return proc_doulongvec_minmax(&ipc_table, write, buffer,
   96                                         lenp, ppos);
   97 }
   98 
   99 /*
  100  * Routine that is called when the file "auto_msgmni" has successfully been
  101  * written.
  102  * Two values are allowed:
  103  * 0: unregister msgmni's callback routine from the ipc namespace notifier
  104  *    chain. This means that msgmni won't be recomputed anymore upon memory
  105  *    add/remove or ipc namespace creation/removal.
  106  * 1: register back the callback routine.
  107  */
  108 static void ipc_auto_callback(int val)
  109 {
  110         if (!val)
  111                 unregister_ipcns_notifier(current->nsproxy->ipc_ns);
  112         else {
  113                 /*
  114                  * Re-enable automatic recomputing only if not already
  115                  * enabled.
  116                  */
  117                 recompute_msgmni(current->nsproxy->ipc_ns);
  118                 cond_register_ipcns_notifier(current->nsproxy->ipc_ns);
  119         }
  120 }
  121 
  122 static int proc_ipcauto_dointvec_minmax(ctl_table *table, int write,
  123         void __user *buffer, size_t *lenp, loff_t *ppos)
  124 {
  125         struct ctl_table ipc_table;
  126         size_t lenp_bef = *lenp;
  127         int oldval;
  128         int rc;
  129 
  130         memcpy(&ipc_table, table, sizeof(ipc_table));
  131         ipc_table.data = get_ipc(table);
  132         oldval = *((int *)(ipc_table.data));
  133 
  134         rc = proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos);
  135 
  136         if (write && !rc && lenp_bef == *lenp) {
  137                 int newval = *((int *)(ipc_table.data));
  138                 /*
  139                  * The file "auto_msgmni" has correctly been set.
  140                  * React by (un)registering the corresponding tunable, if the
  141                  * value has changed.
  142                  */
  143                 if (newval != oldval)
  144                         ipc_auto_callback(newval);
  145         }
  146 
  147         return rc;
  148 }
  149 
  150 #else
  151 #define proc_ipc_doulongvec_minmax NULL
  152 #define proc_ipc_dointvec          NULL
  153 #define proc_ipc_dointvec_minmax   NULL
  154 #define proc_ipc_dointvec_minmax_orphans   NULL
  155 #define proc_ipc_callback_dointvec NULL
  156 #define proc_ipcauto_dointvec_minmax NULL
  157 #endif
  158 
  159 static int zero;
  160 static int one = 1;
  161 #ifdef CONFIG_CHECKPOINT_RESTORE
  162 static int int_max = INT_MAX;
  163 #endif
  164 
  165 static struct ctl_table ipc_kern_table[] = {
  166         {
  167                 .procname       = "shmmax",
  168                 .data           = &init_ipc_ns.shm_ctlmax,
  169                 .maxlen         = sizeof (init_ipc_ns.shm_ctlmax),
  170                 .mode           = 0644,
  171                 .proc_handler   = proc_ipc_doulongvec_minmax,
  172         },
  173         {
  174                 .procname       = "shmall",
  175                 .data           = &init_ipc_ns.shm_ctlall,
  176                 .maxlen         = sizeof (init_ipc_ns.shm_ctlall),
  177                 .mode           = 0644,
  178                 .proc_handler   = proc_ipc_doulongvec_minmax,
  179         },
  180         {
  181                 .procname       = "shmmni",
  182                 .data           = &init_ipc_ns.shm_ctlmni,
  183                 .maxlen         = sizeof (init_ipc_ns.shm_ctlmni),
  184                 .mode           = 0644,
  185                 .proc_handler   = proc_ipc_dointvec,
  186         },
  187         {
  188                 .procname       = "shm_rmid_forced",
  189                 .data           = &init_ipc_ns.shm_rmid_forced,
  190                 .maxlen         = sizeof(init_ipc_ns.shm_rmid_forced),
  191                 .mode           = 0644,
  192                 .proc_handler   = proc_ipc_dointvec_minmax_orphans,
  193                 .extra1         = &zero,
  194                 .extra2         = &one,
  195         },
  196         {
  197                 .procname       = "msgmax",
  198                 .data           = &init_ipc_ns.msg_ctlmax,
  199                 .maxlen         = sizeof (init_ipc_ns.msg_ctlmax),
  200                 .mode           = 0644,
  201                 .proc_handler   = proc_ipc_dointvec,
  202         },
  203         {
  204                 .procname       = "msgmni",
  205                 .data           = &init_ipc_ns.msg_ctlmni,
  206                 .maxlen         = sizeof (init_ipc_ns.msg_ctlmni),
  207                 .mode           = 0644,
  208                 .proc_handler   = proc_ipc_callback_dointvec,
  209         },
  210         {
  211                 .procname       =  "msgmnb",
  212                 .data           = &init_ipc_ns.msg_ctlmnb,
  213                 .maxlen         = sizeof (init_ipc_ns.msg_ctlmnb),
  214                 .mode           = 0644,
  215                 .proc_handler   = proc_ipc_dointvec,
  216         },
  217         {
  218                 .procname       = "sem",
  219                 .data           = &init_ipc_ns.sem_ctls,
  220                 .maxlen         = 4*sizeof (int),
  221                 .mode           = 0644,
  222                 .proc_handler   = proc_ipc_dointvec,
  223         },
  224         {
  225                 .procname       = "auto_msgmni",
  226                 .data           = &init_ipc_ns.auto_msgmni,
  227                 .maxlen         = sizeof(int),
  228                 .mode           = 0644,
  229                 .proc_handler   = proc_ipcauto_dointvec_minmax,
  230                 .extra1         = &zero,
  231                 .extra2         = &one,
  232         },
  233 #ifdef CONFIG_CHECKPOINT_RESTORE
  234         {
  235                 .procname       = "sem_next_id",
  236                 .data           = &init_ipc_ns.ids[IPC_SEM_IDS].next_id,
  237                 .maxlen         = sizeof(init_ipc_ns.ids[IPC_SEM_IDS].next_id),
  238                 .mode           = 0644,
  239                 .proc_handler   = proc_ipc_dointvec_minmax,
  240                 .extra1         = &zero,
  241                 .extra2         = &int_max,
  242         },
  243         {
  244                 .procname       = "msg_next_id",
  245                 .data           = &init_ipc_ns.ids[IPC_MSG_IDS].next_id,
  246                 .maxlen         = sizeof(init_ipc_ns.ids[IPC_MSG_IDS].next_id),
  247                 .mode           = 0644,
  248                 .proc_handler   = proc_ipc_dointvec_minmax,
  249                 .extra1         = &zero,
  250                 .extra2         = &int_max,
  251         },
  252         {
  253                 .procname       = "shm_next_id",
  254                 .data           = &init_ipc_ns.ids[IPC_SHM_IDS].next_id,
  255                 .maxlen         = sizeof(init_ipc_ns.ids[IPC_SHM_IDS].next_id),
  256                 .mode           = 0644,
  257                 .proc_handler   = proc_ipc_dointvec_minmax,
  258                 .extra1         = &zero,
  259                 .extra2         = &int_max,
  260         },
  261 #endif
  262         {}
  263 };
  264 
  265 static struct ctl_table ipc_root_table[] = {
  266         {
  267                 .procname       = "kernel",
  268                 .mode           = 0555,
  269                 .child          = ipc_kern_table,
  270         },
  271         {}
  272 };
  273 
  274 static int __init ipc_sysctl_init(void)
  275 {
  276         register_sysctl_table(ipc_root_table);
  277         return 0;
  278 }
  279 
  280 __initcall(ipc_sysctl_init);

Cache object: 87592e5909bf41de5d1459bbb19b43d0


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.