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 
   29 #include <sys/cdefs.h>
   30 __FBSDID("$FreeBSD$");
   31 
   32 #include <sys/param.h>
   33 #include <sys/kernel.h>
   34 #include <sys/systm.h>
   35 #include <sys/sysctl.h>
   36 #include <sys/proc.h>
   37 #include <sys/malloc.h>
   38 #include <sys/jail.h>
   39 #include <sys/lock.h>
   40 #include <sys/mutex.h>
   41 
   42 #include "opt_compat.h"
   43 
   44 #ifdef COMPAT_LINUX32
   45 #include <machine/../linux32/linux.h>
   46 #else
   47 #include <machine/../linux/linux.h>
   48 #endif
   49 #include <compat/linux/linux_mib.h>
   50 
   51 struct linux_prison {
   52         char    pr_osname[LINUX_MAX_UTSNAME];
   53         char    pr_osrelease[LINUX_MAX_UTSNAME];
   54         int     pr_oss_version;
   55         int     pr_osrel;
   56 };
   57 
   58 SYSCTL_NODE(_compat, OID_AUTO, linux, CTLFLAG_RW, 0,
   59             "Linux mode");
   60 
   61 static struct mtx osname_lock;
   62 MTX_SYSINIT(linux_osname, &osname_lock, "linux osname", MTX_DEF);
   63 
   64 static char     linux_osname[LINUX_MAX_UTSNAME] = "Linux";
   65 
   66 static int
   67 linux_sysctl_osname(SYSCTL_HANDLER_ARGS)
   68 {
   69         char osname[LINUX_MAX_UTSNAME];
   70         int error;
   71 
   72         linux_get_osname(req->td, osname);
   73         error = sysctl_handle_string(oidp, osname, LINUX_MAX_UTSNAME, req);
   74         if (error || req->newptr == NULL)
   75                 return (error);
   76         error = linux_set_osname(req->td, osname);
   77         return (error);
   78 }
   79 
   80 SYSCTL_PROC(_compat_linux, OID_AUTO, osname,
   81             CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON,
   82             0, 0, linux_sysctl_osname, "A",
   83             "Linux kernel OS name");
   84 
   85 static char     linux_osrelease[LINUX_MAX_UTSNAME] = "2.4.2";
   86 static int      linux_osrel = 2004002;
   87 
   88 static int
   89 linux_sysctl_osrelease(SYSCTL_HANDLER_ARGS)
   90 {
   91         char osrelease[LINUX_MAX_UTSNAME];
   92         int error;
   93 
   94         linux_get_osrelease(req->td, osrelease);
   95         error = sysctl_handle_string(oidp, osrelease, LINUX_MAX_UTSNAME, req);
   96         if (error || req->newptr == NULL)
   97                 return (error);
   98         error = linux_set_osrelease(req->td, osrelease);
   99         return (error);
  100 }
  101 
  102 SYSCTL_PROC(_compat_linux, OID_AUTO, osrelease,
  103             CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON,
  104             0, 0, linux_sysctl_osrelease, "A",
  105             "Linux kernel OS release");
  106 
  107 static int      linux_oss_version = 0x030600;
  108 
  109 static int
  110 linux_sysctl_oss_version(SYSCTL_HANDLER_ARGS)
  111 {
  112         int oss_version;
  113         int error;
  114 
  115         oss_version = linux_get_oss_version(req->td);
  116         error = sysctl_handle_int(oidp, &oss_version, 0, req);
  117         if (error || req->newptr == NULL)
  118                 return (error);
  119         error = linux_set_oss_version(req->td, oss_version);
  120         return (error);
  121 }
  122 
  123 SYSCTL_PROC(_compat_linux, OID_AUTO, oss_version,
  124             CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_PRISON,
  125             0, 0, linux_sysctl_oss_version, "I",
  126             "Linux OSS version");
  127 
  128 /*
  129  * Map the osrelease into integer
  130  */
  131 static int
  132 linux_map_osrel(char *osrelease, int *osrel)
  133 {
  134         char *sep, *eosrelease;
  135         int len, v0, v1, v2, v;
  136 
  137         len = strlen(osrelease);
  138         eosrelease = osrelease + len;
  139         v0 = strtol(osrelease, &sep, 10);
  140         if (osrelease == sep || sep + 1 >= eosrelease || *sep != '.')
  141                 return (EINVAL);
  142         osrelease = sep + 1;
  143         v1 = strtol(osrelease, &sep, 10);
  144         if (osrelease == sep || sep + 1 >= eosrelease || *sep != '.')
  145                 return (EINVAL);
  146         osrelease = sep + 1;
  147         v2 = strtol(osrelease, &sep, 10);
  148         if (osrelease == sep || sep != eosrelease)
  149                 return (EINVAL);
  150 
  151         v = v0 * 1000000 + v1 * 1000 + v2;
  152         if (v < 1000000)
  153                 return (EINVAL);
  154 
  155         *osrel = v;
  156         return (0);
  157 }
  158 
  159 /*
  160  * Returns holding the prison mutex if return non-NULL.
  161  */
  162 static struct prison *
  163 linux_get_prison(struct thread *td)
  164 {
  165         register struct prison *pr;
  166         register struct linux_prison *lpr;
  167 
  168         KASSERT(td == curthread, ("linux_get_prison() called on !curthread"));
  169         if (!jailed(td->td_ucred))
  170                 return (NULL);
  171         pr = td->td_ucred->cr_prison;
  172         mtx_lock(&pr->pr_mtx);
  173         if (pr->pr_linux == NULL) {
  174                 /*
  175                  * If we don't have a linux prison structure yet, allocate
  176                  * one.  We have to handle the race where another thread
  177                  * could be adding a linux prison to this process already.
  178                  */
  179                 mtx_unlock(&pr->pr_mtx);
  180                 lpr = malloc(sizeof(struct linux_prison), M_PRISON,
  181                     M_WAITOK | M_ZERO);
  182                 mtx_lock(&pr->pr_mtx);
  183                 if (pr->pr_linux == NULL)
  184                         pr->pr_linux = lpr;
  185                 else
  186                         free(lpr, M_PRISON);
  187         }
  188         return (pr);
  189 }
  190 
  191 void
  192 linux_get_osname(struct thread *td, char *dst)
  193 {
  194         register struct prison *pr;
  195         register struct linux_prison *lpr;
  196 
  197         pr = td->td_ucred->cr_prison;
  198         if (pr != NULL) {
  199                 mtx_lock(&pr->pr_mtx);
  200                 if (pr->pr_linux != NULL) {
  201                         lpr = (struct linux_prison *)pr->pr_linux;
  202                         if (lpr->pr_osname[0]) {
  203                                 bcopy(lpr->pr_osname, dst, LINUX_MAX_UTSNAME);
  204                                 mtx_unlock(&pr->pr_mtx);
  205                                 return;
  206                         }
  207                 }
  208                 mtx_unlock(&pr->pr_mtx);
  209         }
  210 
  211         mtx_lock(&osname_lock);
  212         bcopy(linux_osname, dst, LINUX_MAX_UTSNAME);
  213         mtx_unlock(&osname_lock);
  214 }
  215 
  216 int
  217 linux_set_osname(struct thread *td, char *osname)
  218 {
  219         struct prison *pr;
  220         struct linux_prison *lpr;
  221 
  222         pr = linux_get_prison(td);
  223         if (pr != NULL) {
  224                 lpr = (struct linux_prison *)pr->pr_linux;
  225                 strcpy(lpr->pr_osname, osname);
  226                 mtx_unlock(&pr->pr_mtx);
  227         } else {
  228                 mtx_lock(&osname_lock);
  229                 strcpy(linux_osname, osname);
  230                 mtx_unlock(&osname_lock);
  231         }
  232 
  233         return (0);
  234 }
  235 
  236 void
  237 linux_get_osrelease(struct thread *td, char *dst)
  238 {
  239         register struct prison *pr;
  240         struct linux_prison *lpr;
  241 
  242         pr = td->td_ucred->cr_prison;
  243         if (pr != NULL) {
  244                 mtx_lock(&pr->pr_mtx);
  245                 if (pr->pr_linux != NULL) {
  246                         lpr = (struct linux_prison *)pr->pr_linux;
  247                         if (lpr->pr_osrelease[0]) {
  248                                 bcopy(lpr->pr_osrelease, dst,
  249                                     LINUX_MAX_UTSNAME);
  250                                 mtx_unlock(&pr->pr_mtx);
  251                                 return;
  252                         }
  253                 }
  254                 mtx_unlock(&pr->pr_mtx);
  255         }
  256 
  257         mtx_lock(&osname_lock);
  258         bcopy(linux_osrelease, dst, LINUX_MAX_UTSNAME);
  259         mtx_unlock(&osname_lock);
  260 }
  261 
  262 int
  263 linux_kernver(struct thread *td)
  264 {
  265         struct prison *pr;
  266         struct linux_prison *lpr;
  267         int osrel;
  268 
  269         pr = td->td_ucred->cr_prison;
  270         if (pr != NULL && pr->pr_linux != NULL) {
  271                 lpr = (struct linux_prison *)pr->pr_linux;
  272                 osrel = lpr->pr_osrel;
  273         } else
  274                 osrel = linux_osrel;
  275         return (osrel);
  276 }
  277 
  278 int
  279 linux_set_osrelease(struct thread *td, char *osrelease)
  280 {
  281         struct prison *pr;
  282         struct linux_prison *lpr;
  283         int error;
  284 
  285         pr = linux_get_prison(td);
  286         if (pr != NULL) {
  287                 lpr = (struct linux_prison *)pr->pr_linux;
  288                 error = linux_map_osrel(osrelease, &lpr->pr_osrel);
  289                 if (error) {
  290                         mtx_unlock(&pr->pr_mtx);
  291                         return (error);
  292                 }
  293                 strcpy(lpr->pr_osrelease, osrelease);
  294                 mtx_unlock(&pr->pr_mtx);
  295         } else {
  296                 mtx_lock(&osname_lock);
  297                 error = linux_map_osrel(osrelease, &linux_osrel);
  298                 if (error) {
  299                         mtx_unlock(&osname_lock);
  300                         return (error);
  301                 }
  302                 strcpy(linux_osrelease, osrelease);
  303                 mtx_unlock(&osname_lock);
  304         }
  305 
  306         return (0);
  307 }
  308 
  309 int
  310 linux_get_oss_version(struct thread *td)
  311 {
  312         register struct prison *pr;
  313         register struct linux_prison *lpr;
  314         int version;
  315 
  316         pr = td->td_ucred->cr_prison;
  317         if (pr != NULL) {
  318                 mtx_lock(&pr->pr_mtx);
  319                 if (pr->pr_linux != NULL) {
  320                         lpr = (struct linux_prison *)pr->pr_linux;
  321                         if (lpr->pr_oss_version) {
  322                                 version = lpr->pr_oss_version;
  323                                 mtx_unlock(&pr->pr_mtx);
  324                                 return (version);
  325                         }
  326                 }
  327                 mtx_unlock(&pr->pr_mtx);
  328         }
  329 
  330         mtx_lock(&osname_lock);
  331         version = linux_oss_version;
  332         mtx_unlock(&osname_lock);
  333         return (version);
  334 }
  335 
  336 int
  337 linux_set_oss_version(struct thread *td, int oss_version)
  338 {
  339         struct prison *pr;
  340         struct linux_prison *lpr;
  341 
  342         pr = linux_get_prison(td);
  343         if (pr != NULL) {
  344                 lpr = (struct linux_prison *)pr->pr_linux;
  345                 lpr->pr_oss_version = oss_version;
  346                 mtx_unlock(&pr->pr_mtx);
  347         } else {
  348                 mtx_lock(&osname_lock);
  349                 linux_oss_version = oss_version;
  350                 mtx_unlock(&osname_lock);
  351         }
  352 
  353         return (0);
  354 }
  355 
  356 #if defined(DEBUG) || defined(KTR)
  357 
  358 u_char linux_debug_map[howmany(LINUX_SYS_MAXSYSCALL, sizeof(u_char))];
  359 
  360 static int
  361 linux_debug(int syscall, int toggle, int global)
  362 {
  363 
  364         if (global) {
  365                 char c = toggle ? 0 : 0xff;
  366 
  367                 memset(linux_debug_map, c, sizeof(linux_debug_map));
  368                 return (0);
  369         }
  370         if (syscall < 0 || syscall >= LINUX_SYS_MAXSYSCALL)
  371                 return (EINVAL);
  372         if (toggle)
  373                 clrbit(linux_debug_map, syscall);
  374         else
  375                 setbit(linux_debug_map, syscall);
  376         return (0);
  377 }
  378 
  379 /*
  380  * Usage: sysctl linux.debug=<syscall_nr>.<0/1>
  381  *
  382  *    E.g.: sysctl linux.debug=21.0
  383  *
  384  * As a special case, syscall "all" will apply to all syscalls globally.
  385  */
  386 #define LINUX_MAX_DEBUGSTR      16
  387 static int
  388 linux_sysctl_debug(SYSCTL_HANDLER_ARGS)
  389 {
  390         char value[LINUX_MAX_DEBUGSTR], *p;
  391         int error, sysc, toggle;
  392         int global = 0;
  393 
  394         value[0] = '\0';
  395         error = sysctl_handle_string(oidp, value, LINUX_MAX_DEBUGSTR, req);
  396         if (error || req->newptr == NULL)
  397                 return (error);
  398         for (p = value; *p != '\0' && *p != '.'; p++);
  399         if (*p == '\0')
  400                 return (EINVAL);
  401         *p++ = '\0';
  402         sysc = strtol(value, NULL, 0);
  403         toggle = strtol(p, NULL, 0);
  404         if (strcmp(value, "all") == 0)
  405                 global = 1;
  406         error = linux_debug(sysc, toggle, global);
  407         return (error);
  408 }
  409 
  410 SYSCTL_PROC(_compat_linux, OID_AUTO, debug,
  411             CTLTYPE_STRING | CTLFLAG_RW,
  412             0, 0, linux_sysctl_debug, "A",
  413             "Linux debugging control");
  414 
  415 #endif /* DEBUG || KTR */

Cache object: cd8c87ae0ccea59077050ef5c39625fe


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