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/compat/linux/linux_mib.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) 1999 Marcel Moolenaar
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer 
   10  *    in this position and unchanged.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  * 3. The name of the author may not be used to endorse or promote products
   15  *    derived from this software without specific prior written permission.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   27  *
   28  * $FreeBSD: releng/5.0/sys/compat/linux/linux_mib.c 96398 2002-05-11 06:06:11Z dd $
   29  */
   30 
   31 #include <sys/param.h>
   32 #include <sys/kernel.h>
   33 #include <sys/systm.h>
   34 #include <sys/sysctl.h>
   35 #include <sys/proc.h>
   36 #include <sys/malloc.h>
   37 #include <sys/jail.h>
   38 #include <sys/lock.h>
   39 #include <sys/mutex.h>
   40 
   41 #include <machine/../linux/linux.h>
   42 #include <compat/linux/linux_mib.h>
   43 
   44 struct linux_prison {
   45         char    pr_osname[LINUX_MAX_UTSNAME];
   46         char    pr_osrelease[LINUX_MAX_UTSNAME];
   47         int     pr_oss_version;
   48 };
   49 
   50 SYSCTL_NODE(_compat, OID_AUTO, linux, CTLFLAG_RW, 0,
   51             "Linux mode");
   52 
   53 static char     linux_osname[LINUX_MAX_UTSNAME] = "Linux";
   54 
   55 static int
   56 linux_sysctl_osname(SYSCTL_HANDLER_ARGS)
   57 {
   58         char osname[LINUX_MAX_UTSNAME];
   59         int error;
   60 
   61         linux_get_osname(req->td->td_proc, osname);
   62         error = sysctl_handle_string(oidp, osname, LINUX_MAX_UTSNAME, req);
   63         if (error || req->newptr == NULL)
   64                 return (error);
   65         error = linux_set_osname(req->td->td_proc, osname);
   66         return (error);
   67 }
   68 
   69 SYSCTL_PROC(_compat_linux, OID_AUTO, osname,
   70             CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON,
   71             0, 0, linux_sysctl_osname, "A",
   72             "Linux kernel OS name");
   73 
   74 static char     linux_osrelease[LINUX_MAX_UTSNAME] = "2.4.2";
   75 
   76 static int
   77 linux_sysctl_osrelease(SYSCTL_HANDLER_ARGS)
   78 {
   79         char osrelease[LINUX_MAX_UTSNAME];
   80         int error;
   81 
   82         linux_get_osrelease(req->td->td_proc, osrelease);
   83         error = sysctl_handle_string(oidp, osrelease, LINUX_MAX_UTSNAME, req);
   84         if (error || req->newptr == NULL)
   85                 return (error);
   86         error = linux_set_osrelease(req->td->td_proc, osrelease);
   87         return (error);
   88 }
   89 
   90 SYSCTL_PROC(_compat_linux, OID_AUTO, osrelease,
   91             CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON,
   92             0, 0, linux_sysctl_osrelease, "A",
   93             "Linux kernel OS release");
   94 
   95 static int      linux_oss_version = 0x030600;
   96 
   97 static int
   98 linux_sysctl_oss_version(SYSCTL_HANDLER_ARGS)
   99 {
  100         int oss_version;
  101         int error;
  102 
  103         oss_version = linux_get_oss_version(req->td->td_proc);
  104         error = sysctl_handle_int(oidp, &oss_version, 0, req);
  105         if (error || req->newptr == NULL)
  106                 return (error);
  107         error = linux_set_oss_version(req->td->td_proc, oss_version);
  108         return (error);
  109 }
  110 
  111 SYSCTL_PROC(_compat_linux, OID_AUTO, oss_version,
  112             CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_PRISON,
  113             0, 0, linux_sysctl_oss_version, "I",
  114             "Linux OSS version");
  115 
  116 /*
  117  * Returns holding the prison mutex if return non-NULL.
  118  */
  119 static struct linux_prison *
  120 linux_get_prison(struct proc *p)
  121 {
  122         register struct prison *pr;
  123         register struct linux_prison *lpr;
  124 
  125         if (!jailed(p->p_ucred))
  126                 return (NULL);
  127 
  128         pr = p->p_ucred->cr_prison;
  129 
  130         /*
  131          * Rather than hold the prison mutex during allocation, check to
  132          * see if we need to allocate while holding the mutex, release it,
  133          * allocate, then once we've allocated the memory, check again to
  134          * see if it's still needed, and set if appropriate.  If it's not,
  135          * we release the mutex again to FREE(), and grab it again so as
  136          * to release holding the lock.
  137          */
  138         mtx_lock(&pr->pr_mtx);
  139         if (pr->pr_linux == NULL) {
  140                 mtx_unlock(&pr->pr_mtx);
  141                 MALLOC(lpr, struct linux_prison *, sizeof *lpr,
  142                     M_PRISON, M_WAITOK|M_ZERO);
  143                 mtx_lock(&pr->pr_mtx);
  144                 if (pr->pr_linux == NULL) {
  145                         pr->pr_linux = lpr;
  146                 } else {
  147                         mtx_unlock(&pr->pr_mtx);
  148                         FREE(lpr, M_PRISON);
  149                         mtx_lock(&pr->pr_mtx);
  150                 }
  151         }
  152 
  153         return (pr->pr_linux);
  154 }
  155 
  156 void
  157 linux_get_osname(p, dst)
  158         struct proc *p;
  159         char *dst;
  160 {
  161         register struct prison *pr;
  162         register struct linux_prison *lpr;
  163 
  164         if (p->p_ucred->cr_prison == NULL) {
  165                 bcopy(linux_osname, dst, LINUX_MAX_UTSNAME);
  166                 return;
  167         }
  168 
  169         pr = p->p_ucred->cr_prison;
  170 
  171         mtx_lock(&pr->pr_mtx);
  172         if (pr->pr_linux != NULL) {
  173                 lpr = (struct linux_prison *)pr->pr_linux;
  174                 if (lpr->pr_osname[0]) {
  175                         bcopy(lpr->pr_osname, dst, LINUX_MAX_UTSNAME);
  176                         mtx_unlock(&pr->pr_mtx);
  177                         return;
  178                 }
  179         }
  180         mtx_unlock(&pr->pr_mtx);
  181         bcopy(linux_osname, dst, LINUX_MAX_UTSNAME);
  182 }
  183 
  184 int
  185 linux_set_osname(p, osname)
  186         struct proc *p;
  187         char *osname;
  188 {
  189         register struct linux_prison *lpr;
  190 
  191         lpr = linux_get_prison(p);
  192         if (lpr != NULL) {
  193                 strcpy(lpr->pr_osname, osname);
  194                 mtx_unlock(&p->p_ucred->cr_prison->pr_mtx);
  195         } else {
  196                 strcpy(linux_osname, osname);
  197         }
  198 
  199         return (0);
  200 }
  201 
  202 void
  203 linux_get_osrelease(p, dst)
  204         struct proc *p;
  205         char *dst;
  206 {
  207         register struct prison *pr;
  208         struct linux_prison *lpr;
  209 
  210         if (p->p_ucred->cr_prison == NULL) {
  211                 bcopy(linux_osrelease, dst, LINUX_MAX_UTSNAME);
  212                 return;
  213         }
  214 
  215         pr = p->p_ucred->cr_prison;
  216 
  217         mtx_lock(&pr->pr_mtx);
  218         if (pr->pr_linux != NULL) {
  219                 lpr = (struct linux_prison *) pr->pr_linux;
  220                 if (lpr->pr_osrelease[0]) {
  221                         bcopy(lpr->pr_osrelease, dst, LINUX_MAX_UTSNAME);
  222                         mtx_unlock(&pr->pr_mtx);
  223                         return;
  224                 }
  225         }
  226         mtx_unlock(&pr->pr_mtx);
  227         bcopy(linux_osrelease, dst, LINUX_MAX_UTSNAME);
  228 }
  229 
  230 int
  231 linux_set_osrelease(p, osrelease)
  232         struct proc *p;
  233         char *osrelease;
  234 {
  235         register struct linux_prison *lpr;
  236 
  237         lpr = linux_get_prison(p);
  238         if (lpr != NULL) {
  239                 strcpy(lpr->pr_osrelease, osrelease);
  240                 mtx_unlock(&p->p_ucred->cr_prison->pr_mtx);
  241         } else {
  242                 strcpy(linux_osrelease, osrelease);
  243         }
  244 
  245         return (0);
  246 }
  247 
  248 int
  249 linux_get_oss_version(p)
  250         struct proc *p;
  251 {
  252         register struct prison *pr;
  253         register struct linux_prison *lpr;
  254         int version;
  255 
  256         if (p->p_ucred->cr_prison == NULL)
  257                 return (linux_oss_version);
  258 
  259         pr = p->p_ucred->cr_prison;
  260 
  261         mtx_lock(&pr->pr_mtx);
  262         if (pr->pr_linux != NULL) {
  263                 lpr = (struct linux_prison *) pr->pr_linux;
  264                 if (lpr->pr_oss_version) {
  265                         version = lpr->pr_oss_version;
  266                 } else {
  267                         version = linux_oss_version;
  268                 }
  269         } else {
  270                 version = linux_oss_version;
  271         }
  272         mtx_unlock(&pr->pr_mtx);
  273 
  274         return (version);
  275 }
  276 
  277 int
  278 linux_set_oss_version(p, oss_version)
  279         struct proc *p;
  280         int oss_version;
  281 {
  282         register struct linux_prison *lpr;
  283 
  284         lpr = linux_get_prison(p);
  285         if (lpr != NULL) {
  286                 lpr->pr_oss_version = oss_version;
  287                 mtx_unlock(&p->p_ucred->cr_prison->pr_mtx);
  288         } else {
  289                 linux_oss_version = oss_version;
  290         }
  291 
  292         return (0);
  293 }
  294 
  295 #ifdef DEBUG
  296 
  297 u_char linux_debug_map[howmany(LINUX_SYS_MAXSYSCALL, sizeof(u_char))];
  298 
  299 static int
  300 linux_debug(int syscall, int toggle, int global)
  301 {
  302 
  303         if (global) {
  304                 char c = toggle ? 0 : 0xff;
  305 
  306                 memset(linux_debug_map, c, sizeof(linux_debug_map));
  307                 return (0);
  308         }
  309         if (syscall < 0 || syscall >= LINUX_SYS_MAXSYSCALL)
  310                 return (EINVAL);
  311         if (toggle)
  312                 clrbit(linux_debug_map, syscall);
  313         else
  314                 setbit(linux_debug_map, syscall);
  315         return (0);
  316 }
  317 
  318 /*
  319  * Usage: sysctl linux.debug=<syscall_nr>.<0/1>
  320  *
  321  *    E.g.: sysctl linux.debug=21.0
  322  *
  323  * As a special case, syscall "all" will apply to all syscalls globally.
  324  */
  325 #define LINUX_MAX_DEBUGSTR      16
  326 static int
  327 linux_sysctl_debug(SYSCTL_HANDLER_ARGS)
  328 {
  329         char value[LINUX_MAX_DEBUGSTR], *p;
  330         int error, sysc, toggle;
  331         int global = 0;
  332 
  333         value[0] = '\0';
  334         error = sysctl_handle_string(oidp, value, LINUX_MAX_DEBUGSTR, req);
  335         if (error || req->newptr == NULL)
  336                 return (error);
  337         for (p = value; *p != '\0' && *p != '.'; p++);
  338         if (*p == '\0')
  339                 return (EINVAL);
  340         *p++ = '\0';
  341         sysc = strtol(value, NULL, 0);
  342         toggle = strtol(p, NULL, 0);
  343         if (strcmp(value, "all") == 0)
  344                 global = 1;
  345         error = linux_debug(sysc, toggle, global);
  346         return (error);
  347 }
  348 
  349 SYSCTL_PROC(_compat_linux, OID_AUTO, debug,
  350             CTLTYPE_STRING | CTLFLAG_RW,
  351             0, 0, linux_sysctl_debug, "A",
  352             "Linux debugging control");
  353 
  354 #endif /* DEBUG */

Cache object: 1272621245682b14eacf892bd4036025


[ 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.