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/libprop/prop_kern.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 /*      $NetBSD: prop_kern.c,v 1.17 2011/09/30 22:08:18 jym Exp $       */
    2 
    3 /*-
    4  * Copyright (c) 2006, 2009 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Jason R. Thorpe.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   29  * POSSIBILITY OF SUCH DAMAGE.
   30  */
   31 
   32 #include <sys/types.h>
   33 
   34 #include <libprop/proplib.h>
   35 
   36 #if !defined(_KERNEL) && !defined(_STANDALONE)
   37 #include <sys/mman.h>
   38 #include <errno.h>
   39 #include <string.h>
   40 #include <stdlib.h>
   41 #include <stdio.h>
   42 #include <sys/ioctl.h>
   43 
   44 static int
   45 _prop_object_externalize_to_pref(prop_object_t obj, struct plistref *pref,
   46                                  char **bufp)
   47 {
   48         char *buf;
   49 
   50         switch (prop_object_type(obj)) {
   51         case PROP_TYPE_DICTIONARY:
   52                 buf = prop_dictionary_externalize(obj);
   53                 break;
   54         case PROP_TYPE_ARRAY:
   55                 buf = prop_array_externalize(obj);
   56                 break;
   57         default:
   58                 return (ENOTSUP);
   59         }
   60         if (buf == NULL) {
   61                 /* Assume we ran out of memory. */
   62                 return (ENOMEM);
   63         }
   64         pref->pref_plist = buf;
   65         pref->pref_len = strlen(buf) + 1;
   66 
   67         *bufp = buf;
   68 
   69         return (0);
   70 }
   71 
   72 bool
   73 prop_array_externalize_to_pref(prop_array_t array, struct plistref *prefp)
   74 {
   75         char *buf;
   76         int rv;
   77 
   78         rv = _prop_object_externalize_to_pref(array, prefp, &buf);
   79         if (rv != 0)
   80                 errno = rv;     /* pass up error value in errno */
   81         return (rv == 0);
   82 }
   83 
   84 /*
   85  * prop_array_externalize_to_pref --
   86  *      Externalize an array into a plistref for sending to the kernel.
   87  */
   88 int
   89 prop_array_send_syscall(prop_array_t array, struct plistref *prefp)
   90 {
   91         if (prop_array_externalize_to_pref(array, prefp))
   92                 return 0;
   93         else
   94                 return errno;
   95 }
   96 
   97 bool
   98 prop_dictionary_externalize_to_pref(prop_dictionary_t dict,
   99                                     struct plistref *prefp)
  100 {
  101         char *buf;
  102         int rv;
  103 
  104         rv = _prop_object_externalize_to_pref(dict, prefp, &buf);
  105         if (rv != 0)
  106                 errno = rv;     /* pass up error value in errno */
  107         return (rv == 0);
  108 }
  109 
  110 /*
  111  * prop_dictionary_externalize_to_pref --
  112  *      Externalize an dictionary into a plistref for sending to the kernel.
  113  */
  114 int
  115 prop_dictionary_send_syscall(prop_dictionary_t dict,
  116                              struct plistref *prefp)
  117 {
  118         if (prop_dictionary_externalize_to_pref(dict, prefp))
  119                 return 0;
  120         else
  121                 return errno;
  122 }
  123 
  124 static int
  125 _prop_object_send_ioctl(prop_object_t obj, int fd, unsigned long cmd)
  126 {
  127         struct plistref pref;
  128         char *buf;
  129         int error;
  130 
  131         error = _prop_object_externalize_to_pref(obj, &pref, &buf);
  132         if (error)
  133                 return (error);
  134 
  135         if (ioctl(fd, cmd, &pref) == -1)
  136                 error = errno;
  137         else
  138                 error = 0;
  139         
  140         free(buf);
  141 
  142         return (error);
  143 }
  144 
  145 /*
  146  * prop_array_send_ioctl --
  147  *      Send an array to the kernel using the specified ioctl.
  148  */
  149 int
  150 prop_array_send_ioctl(prop_array_t array, int fd, unsigned long cmd)
  151 {
  152         int rv;
  153 
  154         rv = _prop_object_send_ioctl(array, fd, cmd);
  155         if (rv != 0) {
  156                 errno = rv;     /* pass up error value in errno */
  157                 return rv;
  158         } else 
  159                 return 0;
  160 }
  161 
  162 /*
  163  * prop_dictionary_send_ioctl --
  164  *      Send a dictionary to the kernel using the specified ioctl.
  165  */
  166 int
  167 prop_dictionary_send_ioctl(prop_dictionary_t dict, int fd, unsigned long cmd)
  168 {
  169         int rv;
  170 
  171         rv = _prop_object_send_ioctl(dict, fd, cmd);
  172         if (rv != 0) {
  173                 errno = rv;     /* pass up error value in errno */
  174                 return rv;
  175         } else 
  176                 return 0;
  177 }
  178 
  179 static int
  180 _prop_object_internalize_from_pref(const struct plistref *pref,
  181                                    prop_type_t type, prop_object_t *objp)
  182 {
  183         prop_object_t obj = NULL;
  184         char *buf;
  185         int error = 0;
  186 
  187         if (pref->pref_len == 0) {
  188                 /*
  189                  * This should never happen; we should always get the XML
  190                  * for an empty dictionary if it's really empty.
  191                  */
  192                 error = EIO;
  193                 goto out;
  194         } else {
  195                 buf = pref->pref_plist;
  196                 buf[pref->pref_len - 1] = '\0'; /* extra insurance */
  197                 switch (type) {
  198                 case PROP_TYPE_DICTIONARY:
  199                         obj = prop_dictionary_internalize(buf);
  200                         break;
  201                 case PROP_TYPE_ARRAY:
  202                         obj = prop_array_internalize(buf);
  203                         break;
  204                 default:
  205                         error = ENOTSUP;
  206                 }
  207                 (void) munmap(buf, pref->pref_len);
  208                 if (obj == NULL && error == 0)
  209                         error = EIO;
  210         }
  211 
  212  out:
  213         if (error == 0)
  214                 *objp = obj;
  215         return (error);
  216 }
  217 
  218 /*
  219  * prop_array_internalize_from_pref --
  220  *      Internalize a pref into a prop_array_t object.
  221  */
  222 bool
  223 prop_array_internalize_from_pref(const struct plistref *prefp,
  224                                  prop_array_t *arrayp)
  225 {
  226         int rv;
  227 
  228         rv = _prop_object_internalize_from_pref(prefp, PROP_TYPE_ARRAY,
  229             (prop_object_t *)arrayp);
  230         if (rv != 0)
  231                 errno = rv;     /* pass up error value in errno */
  232         return (rv == 0);
  233 }
  234 
  235 /*
  236  * prop_array_recv_syscall --
  237  *      Internalize an array received from the kernel as pref.
  238  */
  239 int
  240 prop_array_recv_syscall(const struct plistref *prefp,
  241                         prop_array_t *arrayp)
  242 {
  243         if (prop_array_internalize_from_pref(prefp, arrayp))
  244                 return 0;
  245         else
  246                 return errno;
  247 }
  248 
  249 /*
  250  * prop_dictionary_internalize_from_pref --
  251  *      Internalize a pref into a prop_dictionary_t object.
  252  */
  253 bool
  254 prop_dictionary_internalize_from_pref(const struct plistref *prefp,
  255                                       prop_dictionary_t *dictp)
  256 {
  257         int rv;
  258 
  259         rv = _prop_object_internalize_from_pref(prefp, PROP_TYPE_DICTIONARY,
  260             (prop_object_t *)dictp);
  261         if (rv != 0)
  262                 errno = rv;     /* pass up error value in errno */
  263         return (rv == 0);
  264 }
  265 
  266 /*
  267  * prop_dictionary_recv_syscall --
  268  *      Internalize a dictionary received from the kernel as pref.
  269  */
  270 int
  271 prop_dictionary_recv_syscall(const struct plistref *prefp,
  272                              prop_dictionary_t *dictp)
  273 {
  274         if (prop_dictionary_internalize_from_pref(prefp, dictp))
  275                 return 0;
  276         else
  277                 return errno;
  278 }
  279 
  280 
  281 /*
  282  * prop_array_recv_ioctl --
  283  *      Receive an array from the kernel using the specified ioctl.
  284  */
  285 int
  286 prop_array_recv_ioctl(int fd, unsigned long cmd, prop_array_t *arrayp)
  287 {
  288         int rv;
  289         struct plistref pref;
  290 
  291         rv = ioctl(fd, cmd, &pref);
  292         if (rv == -1)
  293                 return errno;
  294 
  295         rv = _prop_object_internalize_from_pref(&pref, PROP_TYPE_ARRAY,
  296                             (prop_object_t *)arrayp);
  297         if (rv != 0) {
  298                 errno = rv;     /* pass up error value in errno */
  299                 return rv;
  300         } else
  301                 return 0;
  302 }
  303 
  304 /*
  305  * prop_dictionary_recv_ioctl --
  306  *      Receive a dictionary from the kernel using the specified ioctl.
  307  */
  308 int
  309 prop_dictionary_recv_ioctl(int fd, unsigned long cmd, prop_dictionary_t *dictp)
  310 {
  311         int rv;
  312         struct plistref pref;
  313 
  314         rv = ioctl(fd, cmd, &pref);
  315         if (rv == -1)
  316                 return errno;
  317 
  318         rv = _prop_object_internalize_from_pref(&pref, PROP_TYPE_DICTIONARY,
  319                             (prop_object_t *)dictp);
  320         if (rv != 0) {
  321                 errno = rv;     /* pass up error value in errno */
  322                 return rv;
  323         } else
  324                 return 0;
  325 }
  326 
  327 /*
  328  * prop_dictionary_sendrecv_ioctl --
  329  *      Combination send/receive a dictionary to/from the kernel using
  330  *      the specified ioctl.
  331  */
  332 int
  333 prop_dictionary_sendrecv_ioctl(prop_dictionary_t dict, int fd,
  334                                unsigned long cmd, prop_dictionary_t *dictp)
  335 {
  336         struct plistref pref;
  337         char *buf;
  338         int error;
  339 
  340         error = _prop_object_externalize_to_pref(dict, &pref, &buf);
  341         if (error != 0) {
  342                 errno = error;
  343                 return error;
  344         }
  345 
  346         if (ioctl(fd, cmd, &pref) == -1)
  347                 error = errno;
  348         else
  349                 error = 0;
  350         
  351         free(buf);
  352 
  353         if (error != 0)
  354                 return error;
  355 
  356         error = _prop_object_internalize_from_pref(&pref, PROP_TYPE_DICTIONARY,
  357                             (prop_object_t *)dictp);
  358         if (error != 0) {
  359                 errno = error;     /* pass up error value in errno */
  360                 return error;
  361         } else
  362                 return 0;
  363 }
  364 #endif /* !_KERNEL && !_STANDALONE */
  365 
  366 #if defined(_KERNEL)
  367 #include <sys/param.h>
  368 #include <sys/mman.h>
  369 #include <sys/errno.h>
  370 #include <sys/malloc.h>
  371 #include <sys/systm.h>
  372 #include <sys/proc.h>
  373 #include <sys/resource.h>
  374 #include <sys/objcache.h>
  375 #include <sys/ioccom.h>
  376 #include <vm/vm.h>
  377 #include <vm/vm_extern.h>
  378 #include <vm/vm_param.h>
  379 
  380 #include "prop_object_impl.h"
  381 
  382 /* Arbitrary limit ioctl input to 64KB */
  383 unsigned int prop_object_copyin_limit = 65536;
  384 
  385 static int
  386 _prop_object_copyin(const struct plistref *pref, const prop_type_t type,
  387                           prop_object_t *objp)
  388 {
  389         prop_object_t obj = NULL;
  390         char *buf;
  391         int error;
  392 
  393         /*
  394          * Allocate an extra byte so we can guarantee NUL-termination.
  395          *
  396          * Allow malloc to fail in case pmap would be exhausted.
  397          */
  398         buf = kmalloc(pref->pref_len + 1, M_TEMP, M_WAITOK);
  399         error = copyin(pref->pref_plist, buf, pref->pref_len);
  400         if (error) {
  401                 kfree(buf, M_TEMP);
  402                 return (error);
  403         }
  404         buf[pref->pref_len] = '\0';
  405 
  406         switch (type) {
  407         case PROP_TYPE_ARRAY:
  408                 obj = prop_array_internalize(buf);
  409                 break;
  410         case PROP_TYPE_DICTIONARY:
  411                 obj = prop_dictionary_internalize(buf);
  412                 break;
  413         default:
  414                 error = ENOTSUP;
  415         }
  416 
  417         kfree(buf, M_TEMP);
  418         if (obj == NULL) {
  419                 if (error == 0)
  420                         error = EIO;
  421         } else {
  422                 *objp = obj;
  423         }
  424         return (error);
  425 }
  426 
  427 
  428 static int
  429 _prop_object_copyin_ioctl(const struct plistref *pref, const prop_type_t type,
  430                           const u_long cmd, prop_object_t *objp)
  431 {
  432         if ((cmd & IOC_IN) == 0)
  433                 return (EFAULT);
  434 
  435         return _prop_object_copyin(pref, type, objp);
  436 }
  437 
  438 /*
  439  * prop_array_copyin --
  440  *      Copy in an array passed as a syscall arg.
  441  */
  442 int
  443 prop_array_copyin(const struct plistref *pref, prop_array_t *arrayp)
  444 {
  445         return (_prop_object_copyin(pref, PROP_TYPE_ARRAY,
  446                                           (prop_object_t *)arrayp));
  447 }
  448 
  449 /*
  450  * prop_dictionary_copyin --
  451  *      Copy in a dictionary passed as a syscall arg.
  452  */
  453 int
  454 prop_dictionary_copyin(const struct plistref *pref, prop_dictionary_t *dictp)
  455 {
  456         return (_prop_object_copyin(pref, PROP_TYPE_DICTIONARY,
  457                                           (prop_object_t *)dictp));
  458 }
  459 
  460 
  461 /*
  462  * prop_array_copyin_ioctl --
  463  *      Copy in an array send with an ioctl.
  464  */
  465 int
  466 prop_array_copyin_ioctl(const struct plistref *pref, const u_long cmd,
  467                         prop_array_t *arrayp)
  468 {
  469         return (_prop_object_copyin_ioctl(pref, PROP_TYPE_ARRAY,
  470                                           cmd, (prop_object_t *)arrayp));
  471 }
  472 
  473 /*
  474  * prop_dictionary_copyin_ioctl --
  475  *      Copy in a dictionary sent with an ioctl.
  476  */
  477 int
  478 prop_dictionary_copyin_ioctl(const struct plistref *pref, const u_long cmd,
  479                              prop_dictionary_t *dictp)
  480 {
  481         return (_prop_object_copyin_ioctl(pref, PROP_TYPE_DICTIONARY,
  482                                           cmd, (prop_object_t *)dictp));
  483 }
  484 
  485 static int
  486 _prop_object_copyout(struct plistref *pref, prop_object_t obj)
  487 {
  488         struct proc *p = curproc;
  489         char *buf;
  490         size_t len, rlen;
  491         int error = 0;
  492         vm_offset_t uaddr;
  493 
  494         switch (prop_object_type(obj)) {
  495         case PROP_TYPE_ARRAY:
  496                 buf = prop_array_externalize(obj);
  497                 break;
  498         case PROP_TYPE_DICTIONARY:
  499                 buf = prop_dictionary_externalize(obj);
  500                 break;
  501         default:
  502                 return (ENOTSUP);
  503         }
  504         if (buf == NULL)
  505                 return (ENOMEM);
  506 
  507         len = strlen(buf) + 1;
  508         rlen = round_page(len);
  509 
  510         /*
  511          * See sys_mmap() in sys/uvm/uvm_mmap.c.
  512          * Let's act as if we were calling mmap(0, ...)
  513          */
  514 #if 0
  515         uaddr = p->p_emul->e_vm_default_addr(p,
  516             (vaddr_t)p->p_vmspace->vm_daddr, rlen);
  517 #endif
  518         uaddr = round_page((vm_offset_t)p->p_vmspace->vm_daddr + maxdsiz);
  519 
  520         error = vm_mmap(&p->p_vmspace->vm_map,
  521                          &uaddr, rlen,
  522                          VM_PROT_READ|VM_PROT_WRITE,
  523                          VM_PROT_READ|VM_PROT_WRITE,
  524                          MAP_PRIVATE|MAP_ANON,
  525                          NULL, 0);
  526         if (error == 0) {
  527                 error = copyout(buf, (char *)uaddr, len);
  528                 if (error == 0) {
  529                         pref->pref_plist = (char *)uaddr;
  530                         pref->pref_len   = len;
  531                 }
  532         }
  533 
  534         kfree(buf, M_TEMP);
  535 
  536         return (error);
  537 }
  538 
  539 /*
  540  * prop_array_copyout --
  541  *      Copy out an array to a syscall arg.
  542  */
  543 int
  544 prop_array_copyout(struct plistref *pref, prop_array_t array)
  545 {
  546         return (_prop_object_copyout(pref, array));
  547 }
  548 
  549 /*
  550  * prop_dictionary_copyout --
  551  *      Copy out a dictionary to a syscall arg.
  552  */
  553 int
  554 prop_dictionary_copyout(struct plistref *pref, prop_dictionary_t dict)
  555 {
  556         return (_prop_object_copyout(pref, dict));
  557 }
  558 
  559 static int
  560 _prop_object_copyout_ioctl(struct plistref *pref, const u_long cmd,
  561                            prop_object_t obj)
  562 {
  563         if ((cmd & IOC_OUT) == 0)
  564                 return (EFAULT);
  565         return _prop_object_copyout(pref, obj);
  566 }
  567 
  568 
  569 /*
  570  * prop_array_copyout_ioctl --
  571  *      Copy out an array being received with an ioctl.
  572  */
  573 int
  574 prop_array_copyout_ioctl(struct plistref *pref, const u_long cmd,
  575                          prop_array_t array)
  576 {
  577         return (_prop_object_copyout_ioctl(pref, cmd, array));
  578 }
  579 
  580 /*
  581  * prop_dictionary_copyout_ioctl --
  582  *      Copy out a dictionary being received with an ioctl.
  583  */
  584 int
  585 prop_dictionary_copyout_ioctl(struct plistref *pref, const u_long cmd,
  586                               prop_dictionary_t dict)
  587 {
  588         return (
  589             _prop_object_copyout_ioctl(pref, cmd, dict));
  590 }
  591 #endif /* _KERNEL */

Cache object: 8ef46e4eb51cbaea67fc3013b18857e2


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