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/emulation/linux/linux_util.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) 1994 Christos Zoulas
    3  * Copyright (c) 1995 Frank van der Linden
    4  * Copyright (c) 1995 Scott Bartram
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. The name of the author may not be used to endorse or promote products
   16  *    derived from this software without specific prior written permission
   17  *
   18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   28  *
   29  *      from: svr4_util.c,v 1.5 1995/01/22 23:44:50 christos Exp
   30  * $FreeBSD: src/sys/compat/linux/linux_util.c,v 1.12.2.2 2001/11/05 19:08:23 marcel Exp $
   31  * $DragonFly: src/sys/emulation/linux/linux_util.c,v 1.14 2006/10/27 04:56:28 dillon Exp $
   32  */
   33 
   34 #include <sys/param.h>
   35 #include <sys/systm.h>
   36 #include <sys/proc.h>
   37 #include <sys/nlookup.h>
   38 #include <sys/malloc.h>
   39 #include <sys/vnode.h>
   40 
   41 #include "linux_util.h"
   42 
   43 const char      linux_emul_path[] = "/compat/linux";
   44 
   45 /*
   46  * Search for an alternate path before passing pathname arguments on
   47  * to system calls.
   48  *
   49  * Only signal an error if something really bad happens.  In most cases
   50  * we can just return the untranslated path, eg. name lookup failures.
   51  */
   52 int
   53 linux_copyin_path(char *uname, char **kname, int flags)
   54 {
   55         struct nlookupdata nd, ndroot;
   56         struct vattr vat, vatroot;
   57         struct vnode *vp, *vproot;
   58         char *buf, *cp;
   59         int error, length, dummy, byte;
   60 
   61         buf = (char *) kmalloc(MAXPATHLEN, M_TEMP, M_WAITOK);
   62         *kname = buf;
   63 
   64         /*
   65          * Read a byte and see if uname is a valid address. if not, EFAULT.
   66          */
   67         byte = fubyte(uname);
   68         if (byte == -1) {
   69                 error = EFAULT;
   70                 goto done;
   71         }
   72         /*
   73          * Don't bother trying to translate if the path is relative.
   74          */
   75         if (byte != '/')
   76                 goto dont_translate;
   77 
   78         /*
   79          * The path is absolute.  Prepend the buffer with the emulation
   80          * path and copy in.
   81          */
   82         length = strlen(linux_emul_path);
   83         bcopy(linux_emul_path, buf, length);
   84         error = copyinstr(uname, buf + length, MAXPATHLEN - length, &dummy);
   85         if (error)
   86                 goto done;
   87 
   88         switch (flags) {
   89         case LINUX_PATH_CREATE:
   90                 /*
   91                  * Check to see if the parent directory exists in the
   92                  * emulation tree.  Walk the string backwards to find
   93                  * the last '/'.
   94                  */
   95                 cp = buf + strlen(buf);
   96                 while (--cp >= buf) {
   97                         if (*cp == '/')
   98                                 break;
   99                 }
  100                 if (cp < buf)
  101                         goto dont_translate;
  102                 *cp = 0;
  103 
  104                 error = nlookup_init(&nd, buf, UIO_SYSSPACE, NLC_FOLLOW);
  105                 if (error == 0)
  106                         error = nlookup(&nd);
  107                 nlookup_done(&nd);
  108                 if (error)
  109                         goto dont_translate;
  110                 *cp = '/';
  111                 return (0);
  112         case LINUX_PATH_EXISTS:
  113                 error = nlookup_init(&nd, buf, UIO_SYSSPACE, NLC_FOLLOW);
  114                 if (error == 0)
  115                         error = nlookup(&nd);
  116                 vp = NULL;
  117                 if (error == 0)
  118                         error = cache_vref(&nd.nl_nch, nd.nl_cred, &vp);
  119                 nlookup_done(&nd);
  120                 if (error)
  121                         goto dont_translate;
  122 
  123                 /*
  124                  * We now compare the vnode of the linux_root to the one
  125                  * vnode asked. If they resolve to be the same, then we
  126                  * ignore the match so that the real root gets used.
  127                  * This avoids the problem of traversing "../.." to find the
  128                  * root directory and never finding it, because "/" resolves
  129                  * to the emulation root directory. This is expensive :-(
  130                  *
  131                  * The next three function calls should not return errors.
  132                  * If they do something is seriously wrong, eg. the
  133                  * emulation subtree does not exist.  Cross our fingers
  134                  * and return the untranslated path if something happens.
  135                  */
  136                 error = nlookup_init(&ndroot, linux_emul_path, UIO_SYSSPACE,
  137                                         NLC_FOLLOW);
  138                 if (error == 0)
  139                         error = nlookup(&ndroot);
  140                 vproot = NULL;
  141                 if (error == 0) {
  142                         error = cache_vref(&ndroot.nl_nch, ndroot.nl_cred,
  143                                            &vproot);
  144                 }
  145                 nlookup_done(&ndroot);
  146                 if (error) {
  147                         vrele(vp);
  148                         goto dont_translate;
  149                 }
  150                 
  151                 error = VOP_GETATTR(vp, &vat);
  152                 if (error == 0) {
  153                         error = VOP_GETATTR(vproot, &vatroot);
  154                         if (error == 0) {
  155                                 if (vat.va_fsid == vatroot.va_fsid &&
  156                                     vat.va_fileid == vatroot.va_fileid)
  157                                         error = ENOENT;
  158                         }
  159                 }
  160                 vrele(vp);
  161                 vrele(vproot);
  162                 if (error)
  163                         goto dont_translate;
  164                 return (0);
  165         default:
  166                 error = EINVAL;
  167                 goto done;
  168         }
  169         
  170 dont_translate:
  171         error = copyinstr(uname, buf, MAXPATHLEN, &dummy);
  172 done:
  173         if (error)
  174                 linux_free_path(kname);
  175         return (error);
  176 }
  177 
  178 /*
  179  * Smaller version of the above for translating in kernel buffers.  Only
  180  * used in exec_linux_imgact_try().  Only check is path exists.
  181  */
  182 int
  183 linux_translate_path(char *path, int size)
  184 {
  185         struct nlookupdata nd;
  186         char *buf;
  187         int error, length, dummy;
  188 
  189         buf = (char *) kmalloc(MAXPATHLEN, M_TEMP, M_WAITOK);
  190         length = strlen(linux_emul_path);
  191         bcopy(linux_emul_path, buf, length);
  192         error = copystr(path, buf + length, MAXPATHLEN - length, &dummy);
  193         if (error)
  194                 goto cleanup;
  195         
  196         /*
  197          * If this errors, then the path probably doesn't exist.
  198          */
  199         error = nlookup_init(&nd, buf, UIO_SYSSPACE, NLC_FOLLOW);
  200         if (error == 0)
  201                 error = nlookup(&nd);
  202         nlookup_done(&nd);
  203         if (error) {
  204                 error = 0;
  205                 goto cleanup;
  206         }
  207 
  208         /*
  209          * The alternate path does exist.  Return it in the buffer if
  210          * it fits.
  211          */
  212         if (strlen(buf) + 1 <= size)
  213                 error = copystr(buf, path, size, &dummy);
  214 
  215 cleanup:
  216 
  217         kfree(buf, M_TEMP);
  218         return (error);
  219 }

Cache object: 2d60cc262f12c58e0ff275953d61dd45


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