1*0a6a1f1dSLionel Sambuc /* $NetBSD: prop_kern.c,v 1.19 2015/05/11 16:48:34 christos Exp $ */
26b6d114aSBen Gras
36b6d114aSBen Gras /*-
46b6d114aSBen Gras * Copyright (c) 2006, 2009 The NetBSD Foundation, Inc.
56b6d114aSBen Gras * All rights reserved.
66b6d114aSBen Gras *
76b6d114aSBen Gras * This code is derived from software contributed to The NetBSD Foundation
86b6d114aSBen Gras * by Jason R. Thorpe.
96b6d114aSBen Gras *
106b6d114aSBen Gras * Redistribution and use in source and binary forms, with or without
116b6d114aSBen Gras * modification, are permitted provided that the following conditions
126b6d114aSBen Gras * are met:
136b6d114aSBen Gras * 1. Redistributions of source code must retain the above copyright
146b6d114aSBen Gras * notice, this list of conditions and the following disclaimer.
156b6d114aSBen Gras * 2. Redistributions in binary form must reproduce the above copyright
166b6d114aSBen Gras * notice, this list of conditions and the following disclaimer in the
176b6d114aSBen Gras * documentation and/or other materials provided with the distribution.
186b6d114aSBen Gras *
196b6d114aSBen Gras * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
206b6d114aSBen Gras * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
216b6d114aSBen Gras * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
226b6d114aSBen Gras * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
236b6d114aSBen Gras * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
246b6d114aSBen Gras * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
256b6d114aSBen Gras * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
266b6d114aSBen Gras * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
276b6d114aSBen Gras * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
286b6d114aSBen Gras * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
296b6d114aSBen Gras * POSSIBILITY OF SUCH DAMAGE.
306b6d114aSBen Gras */
316b6d114aSBen Gras
326b6d114aSBen Gras #if defined(__NetBSD__)
336b6d114aSBen Gras
346b6d114aSBen Gras #include <sys/types.h>
356b6d114aSBen Gras #include <sys/ioctl.h>
366b6d114aSBen Gras
376b6d114aSBen Gras #include <prop/proplib.h>
386b6d114aSBen Gras
396b6d114aSBen Gras #if !defined(_KERNEL) && !defined(_STANDALONE)
406b6d114aSBen Gras #include <sys/mman.h>
416b6d114aSBen Gras #include <errno.h>
426b6d114aSBen Gras #include <string.h>
436b6d114aSBen Gras #include <stdlib.h>
446b6d114aSBen Gras #include <stdio.h>
456b6d114aSBen Gras
466b6d114aSBen Gras #ifdef RUMP_ACTION
476b6d114aSBen Gras #include <rump/rump_syscalls.h>
486b6d114aSBen Gras #define ioctl(a,b,c) rump_sys_ioctl(a,b,c)
496b6d114aSBen Gras #endif
506b6d114aSBen Gras
516b6d114aSBen Gras static int
_prop_object_externalize_to_pref(prop_object_t obj,struct plistref * pref,char ** bufp)526b6d114aSBen Gras _prop_object_externalize_to_pref(prop_object_t obj, struct plistref *pref,
536b6d114aSBen Gras char **bufp)
546b6d114aSBen Gras {
556b6d114aSBen Gras char *buf;
566b6d114aSBen Gras
576b6d114aSBen Gras switch (prop_object_type(obj)) {
586b6d114aSBen Gras case PROP_TYPE_DICTIONARY:
596b6d114aSBen Gras buf = prop_dictionary_externalize(obj);
606b6d114aSBen Gras break;
616b6d114aSBen Gras case PROP_TYPE_ARRAY:
626b6d114aSBen Gras buf = prop_array_externalize(obj);
636b6d114aSBen Gras break;
646b6d114aSBen Gras default:
656b6d114aSBen Gras return (ENOTSUP);
666b6d114aSBen Gras }
676b6d114aSBen Gras if (buf == NULL) {
686b6d114aSBen Gras /* Assume we ran out of memory. */
696b6d114aSBen Gras return (ENOMEM);
706b6d114aSBen Gras }
716b6d114aSBen Gras pref->pref_plist = buf;
726b6d114aSBen Gras pref->pref_len = strlen(buf) + 1;
736b6d114aSBen Gras
746b6d114aSBen Gras *bufp = buf;
756b6d114aSBen Gras
766b6d114aSBen Gras return (0);
776b6d114aSBen Gras }
786b6d114aSBen Gras
796b6d114aSBen Gras bool
prop_array_externalize_to_pref(prop_array_t array,struct plistref * prefp)806b6d114aSBen Gras prop_array_externalize_to_pref(prop_array_t array, struct plistref *prefp)
816b6d114aSBen Gras {
826b6d114aSBen Gras char *buf;
836b6d114aSBen Gras int rv;
846b6d114aSBen Gras
856b6d114aSBen Gras rv = _prop_object_externalize_to_pref(array, prefp, &buf);
866b6d114aSBen Gras if (rv != 0)
876b6d114aSBen Gras errno = rv; /* pass up error value in errno */
886b6d114aSBen Gras return (rv == 0);
896b6d114aSBen Gras }
906b6d114aSBen Gras
916b6d114aSBen Gras /*
926b6d114aSBen Gras * prop_array_externalize_to_pref --
936b6d114aSBen Gras * Externalize an array into a plistref for sending to the kernel.
946b6d114aSBen Gras */
956b6d114aSBen Gras int
prop_array_send_syscall(prop_array_t array,struct plistref * prefp)966b6d114aSBen Gras prop_array_send_syscall(prop_array_t array, struct plistref *prefp)
976b6d114aSBen Gras {
986b6d114aSBen Gras if (prop_array_externalize_to_pref(array, prefp))
996b6d114aSBen Gras return 0;
1006b6d114aSBen Gras else
1016b6d114aSBen Gras return errno;
1026b6d114aSBen Gras }
1036b6d114aSBen Gras
1046b6d114aSBen Gras bool
prop_dictionary_externalize_to_pref(prop_dictionary_t dict,struct plistref * prefp)1056b6d114aSBen Gras prop_dictionary_externalize_to_pref(prop_dictionary_t dict,
1066b6d114aSBen Gras struct plistref *prefp)
1076b6d114aSBen Gras {
1086b6d114aSBen Gras char *buf;
1096b6d114aSBen Gras int rv;
1106b6d114aSBen Gras
1116b6d114aSBen Gras rv = _prop_object_externalize_to_pref(dict, prefp, &buf);
1126b6d114aSBen Gras if (rv != 0)
1136b6d114aSBen Gras errno = rv; /* pass up error value in errno */
1146b6d114aSBen Gras return (rv == 0);
1156b6d114aSBen Gras }
1166b6d114aSBen Gras
1176b6d114aSBen Gras /*
1186b6d114aSBen Gras * prop_dictionary_externalize_to_pref --
1196b6d114aSBen Gras * Externalize an dictionary into a plistref for sending to the kernel.
1206b6d114aSBen Gras */
1216b6d114aSBen Gras int
prop_dictionary_send_syscall(prop_dictionary_t dict,struct plistref * prefp)1226b6d114aSBen Gras prop_dictionary_send_syscall(prop_dictionary_t dict,
1236b6d114aSBen Gras struct plistref *prefp)
1246b6d114aSBen Gras {
1256b6d114aSBen Gras if (prop_dictionary_externalize_to_pref(dict, prefp))
1266b6d114aSBen Gras return 0;
1276b6d114aSBen Gras else
1286b6d114aSBen Gras return errno;
1296b6d114aSBen Gras }
1306b6d114aSBen Gras
1316b6d114aSBen Gras static int
_prop_object_send_ioctl(prop_object_t obj,int fd,unsigned long cmd)1326b6d114aSBen Gras _prop_object_send_ioctl(prop_object_t obj, int fd, unsigned long cmd)
1336b6d114aSBen Gras {
1346b6d114aSBen Gras struct plistref pref;
1356b6d114aSBen Gras char *buf;
1366b6d114aSBen Gras int error;
1376b6d114aSBen Gras
1386b6d114aSBen Gras error = _prop_object_externalize_to_pref(obj, &pref, &buf);
1396b6d114aSBen Gras if (error)
1406b6d114aSBen Gras return (error);
1416b6d114aSBen Gras
1426b6d114aSBen Gras if (ioctl(fd, cmd, &pref) == -1)
1436b6d114aSBen Gras error = errno;
1446b6d114aSBen Gras else
1456b6d114aSBen Gras error = 0;
1466b6d114aSBen Gras
1476b6d114aSBen Gras free(buf);
1486b6d114aSBen Gras
1496b6d114aSBen Gras return (error);
1506b6d114aSBen Gras }
1516b6d114aSBen Gras
1526b6d114aSBen Gras /*
1536b6d114aSBen Gras * prop_array_send_ioctl --
1546b6d114aSBen Gras * Send an array to the kernel using the specified ioctl.
1556b6d114aSBen Gras */
1566b6d114aSBen Gras int
prop_array_send_ioctl(prop_array_t array,int fd,unsigned long cmd)1576b6d114aSBen Gras prop_array_send_ioctl(prop_array_t array, int fd, unsigned long cmd)
1586b6d114aSBen Gras {
1596b6d114aSBen Gras int rv;
1606b6d114aSBen Gras
1616b6d114aSBen Gras rv = _prop_object_send_ioctl(array, fd, cmd);
1626b6d114aSBen Gras if (rv != 0) {
1636b6d114aSBen Gras errno = rv; /* pass up error value in errno */
1646b6d114aSBen Gras return rv;
1656b6d114aSBen Gras } else
1666b6d114aSBen Gras return 0;
1676b6d114aSBen Gras }
1686b6d114aSBen Gras
1696b6d114aSBen Gras /*
1706b6d114aSBen Gras * prop_dictionary_send_ioctl --
1716b6d114aSBen Gras * Send a dictionary to the kernel using the specified ioctl.
1726b6d114aSBen Gras */
1736b6d114aSBen Gras int
prop_dictionary_send_ioctl(prop_dictionary_t dict,int fd,unsigned long cmd)1746b6d114aSBen Gras prop_dictionary_send_ioctl(prop_dictionary_t dict, int fd, unsigned long cmd)
1756b6d114aSBen Gras {
1766b6d114aSBen Gras int rv;
1776b6d114aSBen Gras
1786b6d114aSBen Gras rv = _prop_object_send_ioctl(dict, fd, cmd);
1796b6d114aSBen Gras if (rv != 0) {
1806b6d114aSBen Gras errno = rv; /* pass up error value in errno */
1816b6d114aSBen Gras return rv;
1826b6d114aSBen Gras } else
1836b6d114aSBen Gras return 0;
1846b6d114aSBen Gras }
1856b6d114aSBen Gras
1866b6d114aSBen Gras static int
_prop_object_internalize_from_pref(const struct plistref * pref,prop_type_t type,prop_object_t * objp)1876b6d114aSBen Gras _prop_object_internalize_from_pref(const struct plistref *pref,
1886b6d114aSBen Gras prop_type_t type, prop_object_t *objp)
1896b6d114aSBen Gras {
1906b6d114aSBen Gras prop_object_t obj = NULL;
1916b6d114aSBen Gras char *buf;
1926b6d114aSBen Gras int error = 0;
1936b6d114aSBen Gras
1946b6d114aSBen Gras if (pref->pref_len == 0) {
1956b6d114aSBen Gras /*
1966b6d114aSBen Gras * This should never happen; we should always get the XML
1976b6d114aSBen Gras * for an empty dictionary if it's really empty.
1986b6d114aSBen Gras */
1996b6d114aSBen Gras error = EIO;
2006b6d114aSBen Gras goto out;
2016b6d114aSBen Gras } else {
2026b6d114aSBen Gras buf = pref->pref_plist;
2036b6d114aSBen Gras buf[pref->pref_len - 1] = '\0'; /* extra insurance */
2046b6d114aSBen Gras switch (type) {
2056b6d114aSBen Gras case PROP_TYPE_DICTIONARY:
2066b6d114aSBen Gras obj = prop_dictionary_internalize(buf);
2076b6d114aSBen Gras break;
2086b6d114aSBen Gras case PROP_TYPE_ARRAY:
2096b6d114aSBen Gras obj = prop_array_internalize(buf);
2106b6d114aSBen Gras break;
2116b6d114aSBen Gras default:
2126b6d114aSBen Gras error = ENOTSUP;
2136b6d114aSBen Gras }
2146b6d114aSBen Gras (void) munmap(buf, pref->pref_len);
2156b6d114aSBen Gras if (obj == NULL && error == 0)
2166b6d114aSBen Gras error = EIO;
2176b6d114aSBen Gras }
2186b6d114aSBen Gras
2196b6d114aSBen Gras out:
2206b6d114aSBen Gras if (error == 0)
2216b6d114aSBen Gras *objp = obj;
2226b6d114aSBen Gras return (error);
2236b6d114aSBen Gras }
2246b6d114aSBen Gras
2256b6d114aSBen Gras /*
2266b6d114aSBen Gras * prop_array_internalize_from_pref --
2276b6d114aSBen Gras * Internalize a pref into a prop_array_t object.
2286b6d114aSBen Gras */
2296b6d114aSBen Gras bool
prop_array_internalize_from_pref(const struct plistref * prefp,prop_array_t * arrayp)2306b6d114aSBen Gras prop_array_internalize_from_pref(const struct plistref *prefp,
2316b6d114aSBen Gras prop_array_t *arrayp)
2326b6d114aSBen Gras {
2336b6d114aSBen Gras int rv;
2346b6d114aSBen Gras
2356b6d114aSBen Gras rv = _prop_object_internalize_from_pref(prefp, PROP_TYPE_ARRAY,
2366b6d114aSBen Gras (prop_object_t *)arrayp);
2376b6d114aSBen Gras if (rv != 0)
2386b6d114aSBen Gras errno = rv; /* pass up error value in errno */
2396b6d114aSBen Gras return (rv == 0);
2406b6d114aSBen Gras }
2416b6d114aSBen Gras
2426b6d114aSBen Gras /*
2436b6d114aSBen Gras * prop_array_recv_syscall --
2446b6d114aSBen Gras * Internalize an array received from the kernel as pref.
2456b6d114aSBen Gras */
2466b6d114aSBen Gras int
prop_array_recv_syscall(const struct plistref * prefp,prop_array_t * arrayp)2476b6d114aSBen Gras prop_array_recv_syscall(const struct plistref *prefp,
2486b6d114aSBen Gras prop_array_t *arrayp)
2496b6d114aSBen Gras {
2506b6d114aSBen Gras if (prop_array_internalize_from_pref(prefp, arrayp))
2516b6d114aSBen Gras return 0;
2526b6d114aSBen Gras else
2536b6d114aSBen Gras return errno;
2546b6d114aSBen Gras }
2556b6d114aSBen Gras
2566b6d114aSBen Gras /*
2576b6d114aSBen Gras * prop_dictionary_internalize_from_pref --
2586b6d114aSBen Gras * Internalize a pref into a prop_dictionary_t object.
2596b6d114aSBen Gras */
2606b6d114aSBen Gras bool
prop_dictionary_internalize_from_pref(const struct plistref * prefp,prop_dictionary_t * dictp)2616b6d114aSBen Gras prop_dictionary_internalize_from_pref(const struct plistref *prefp,
2626b6d114aSBen Gras prop_dictionary_t *dictp)
2636b6d114aSBen Gras {
2646b6d114aSBen Gras int rv;
2656b6d114aSBen Gras
2666b6d114aSBen Gras rv = _prop_object_internalize_from_pref(prefp, PROP_TYPE_DICTIONARY,
2676b6d114aSBen Gras (prop_object_t *)dictp);
2686b6d114aSBen Gras if (rv != 0)
2696b6d114aSBen Gras errno = rv; /* pass up error value in errno */
2706b6d114aSBen Gras return (rv == 0);
2716b6d114aSBen Gras }
2726b6d114aSBen Gras
2736b6d114aSBen Gras /*
2746b6d114aSBen Gras * prop_dictionary_recv_syscall --
2756b6d114aSBen Gras * Internalize a dictionary received from the kernel as pref.
2766b6d114aSBen Gras */
2776b6d114aSBen Gras int
prop_dictionary_recv_syscall(const struct plistref * prefp,prop_dictionary_t * dictp)2786b6d114aSBen Gras prop_dictionary_recv_syscall(const struct plistref *prefp,
2796b6d114aSBen Gras prop_dictionary_t *dictp)
2806b6d114aSBen Gras {
2816b6d114aSBen Gras if (prop_dictionary_internalize_from_pref(prefp, dictp))
2826b6d114aSBen Gras return 0;
2836b6d114aSBen Gras else
2846b6d114aSBen Gras return errno;
2856b6d114aSBen Gras }
2866b6d114aSBen Gras
2876b6d114aSBen Gras
2886b6d114aSBen Gras /*
2896b6d114aSBen Gras * prop_array_recv_ioctl --
2906b6d114aSBen Gras * Receive an array from the kernel using the specified ioctl.
2916b6d114aSBen Gras */
2926b6d114aSBen Gras int
prop_array_recv_ioctl(int fd,unsigned long cmd,prop_array_t * arrayp)2936b6d114aSBen Gras prop_array_recv_ioctl(int fd, unsigned long cmd, prop_array_t *arrayp)
2946b6d114aSBen Gras {
2956b6d114aSBen Gras int rv;
2966b6d114aSBen Gras struct plistref pref;
2976b6d114aSBen Gras
2986b6d114aSBen Gras rv = ioctl(fd, cmd, &pref);
2996b6d114aSBen Gras if (rv == -1)
3006b6d114aSBen Gras return errno;
3016b6d114aSBen Gras
3026b6d114aSBen Gras rv = _prop_object_internalize_from_pref(&pref, PROP_TYPE_ARRAY,
3036b6d114aSBen Gras (prop_object_t *)arrayp);
3046b6d114aSBen Gras if (rv != 0) {
3056b6d114aSBen Gras errno = rv; /* pass up error value in errno */
3066b6d114aSBen Gras return rv;
3076b6d114aSBen Gras } else
3086b6d114aSBen Gras return 0;
3096b6d114aSBen Gras }
3106b6d114aSBen Gras
3116b6d114aSBen Gras /*
3126b6d114aSBen Gras * prop_dictionary_recv_ioctl --
3136b6d114aSBen Gras * Receive a dictionary from the kernel using the specified ioctl.
3146b6d114aSBen Gras */
3156b6d114aSBen Gras int
prop_dictionary_recv_ioctl(int fd,unsigned long cmd,prop_dictionary_t * dictp)3166b6d114aSBen Gras prop_dictionary_recv_ioctl(int fd, unsigned long cmd, prop_dictionary_t *dictp)
3176b6d114aSBen Gras {
3186b6d114aSBen Gras int rv;
3196b6d114aSBen Gras struct plistref pref;
3206b6d114aSBen Gras
3216b6d114aSBen Gras rv = ioctl(fd, cmd, &pref);
3226b6d114aSBen Gras if (rv == -1)
3236b6d114aSBen Gras return errno;
3246b6d114aSBen Gras
3256b6d114aSBen Gras rv = _prop_object_internalize_from_pref(&pref, PROP_TYPE_DICTIONARY,
3266b6d114aSBen Gras (prop_object_t *)dictp);
3276b6d114aSBen Gras if (rv != 0) {
3286b6d114aSBen Gras errno = rv; /* pass up error value in errno */
3296b6d114aSBen Gras return rv;
3306b6d114aSBen Gras } else
3316b6d114aSBen Gras return 0;
3326b6d114aSBen Gras }
3336b6d114aSBen Gras
3346b6d114aSBen Gras /*
3356b6d114aSBen Gras * prop_dictionary_sendrecv_ioctl --
3366b6d114aSBen Gras * Combination send/receive a dictionary to/from the kernel using
3376b6d114aSBen Gras * the specified ioctl.
3386b6d114aSBen Gras */
3396b6d114aSBen Gras int
prop_dictionary_sendrecv_ioctl(prop_dictionary_t dict,int fd,unsigned long cmd,prop_dictionary_t * dictp)3406b6d114aSBen Gras prop_dictionary_sendrecv_ioctl(prop_dictionary_t dict, int fd,
3416b6d114aSBen Gras unsigned long cmd, prop_dictionary_t *dictp)
3426b6d114aSBen Gras {
3436b6d114aSBen Gras struct plistref pref;
3446b6d114aSBen Gras char *buf;
3456b6d114aSBen Gras int error;
3466b6d114aSBen Gras
3476b6d114aSBen Gras error = _prop_object_externalize_to_pref(dict, &pref, &buf);
3486b6d114aSBen Gras if (error != 0) {
3496b6d114aSBen Gras errno = error;
3506b6d114aSBen Gras return error;
3516b6d114aSBen Gras }
3526b6d114aSBen Gras
3536b6d114aSBen Gras if (ioctl(fd, cmd, &pref) == -1)
3546b6d114aSBen Gras error = errno;
3556b6d114aSBen Gras else
3566b6d114aSBen Gras error = 0;
3576b6d114aSBen Gras
3586b6d114aSBen Gras free(buf);
3596b6d114aSBen Gras
3606b6d114aSBen Gras if (error != 0)
3616b6d114aSBen Gras return error;
3626b6d114aSBen Gras
3636b6d114aSBen Gras error = _prop_object_internalize_from_pref(&pref, PROP_TYPE_DICTIONARY,
3646b6d114aSBen Gras (prop_object_t *)dictp);
3656b6d114aSBen Gras if (error != 0) {
3666b6d114aSBen Gras errno = error; /* pass up error value in errno */
3676b6d114aSBen Gras return error;
3686b6d114aSBen Gras } else
3696b6d114aSBen Gras return 0;
3706b6d114aSBen Gras }
3716b6d114aSBen Gras #endif /* !_KERNEL && !_STANDALONE */
3726b6d114aSBen Gras
3736b6d114aSBen Gras #if defined(_KERNEL)
3746b6d114aSBen Gras #include <sys/param.h>
3756b6d114aSBen Gras #include <sys/mman.h>
3766b6d114aSBen Gras #include <sys/errno.h>
3776b6d114aSBen Gras #include <sys/malloc.h>
3786b6d114aSBen Gras #include <sys/systm.h>
3796b6d114aSBen Gras #include <sys/proc.h>
3806b6d114aSBen Gras #include <sys/resource.h>
3816b6d114aSBen Gras #include <sys/pool.h>
3826b6d114aSBen Gras
383*0a6a1f1dSLionel Sambuc #include <uvm/uvm_extern.h>
3846b6d114aSBen Gras
3856b6d114aSBen Gras #include "prop_object_impl.h"
3866b6d114aSBen Gras
3876b6d114aSBen Gras /* Arbitrary limit ioctl input to 64KB */
3886b6d114aSBen Gras unsigned int prop_object_copyin_limit = 65536;
3896b6d114aSBen Gras
3906b6d114aSBen Gras /* initialize proplib for use in the kernel */
3916b6d114aSBen Gras void
prop_kern_init(void)3926b6d114aSBen Gras prop_kern_init(void)
3936b6d114aSBen Gras {
3946b6d114aSBen Gras __link_set_decl(prop_linkpools, struct prop_pool_init);
3956b6d114aSBen Gras struct prop_pool_init * const *pi;
3966b6d114aSBen Gras
3976b6d114aSBen Gras __link_set_foreach(pi, prop_linkpools)
3986b6d114aSBen Gras pool_init((*pi)->pp, (*pi)->size, 0, 0, 0, (*pi)->wchan,
3996b6d114aSBen Gras &pool_allocator_nointr, IPL_NONE);
4006b6d114aSBen Gras }
4016b6d114aSBen Gras
4026b6d114aSBen Gras static int
_prop_object_copyin(const struct plistref * pref,const prop_type_t type,prop_object_t * objp)4036b6d114aSBen Gras _prop_object_copyin(const struct plistref *pref, const prop_type_t type,
4046b6d114aSBen Gras prop_object_t *objp)
4056b6d114aSBen Gras {
4066b6d114aSBen Gras prop_object_t obj = NULL;
4076b6d114aSBen Gras char *buf;
4086b6d114aSBen Gras int error;
4096b6d114aSBen Gras
410*0a6a1f1dSLionel Sambuc if (pref->pref_len >= prop_object_copyin_limit)
411*0a6a1f1dSLionel Sambuc return EINVAL;
412*0a6a1f1dSLionel Sambuc
4136b6d114aSBen Gras /*
4146b6d114aSBen Gras * Allocate an extra byte so we can guarantee NUL-termination.
4156b6d114aSBen Gras *
4166b6d114aSBen Gras * Allow malloc to fail in case pmap would be exhausted.
4176b6d114aSBen Gras */
4186b6d114aSBen Gras buf = malloc(pref->pref_len + 1, M_TEMP, M_WAITOK | M_CANFAIL);
4196b6d114aSBen Gras if (buf == NULL)
4206b6d114aSBen Gras return (ENOMEM);
4216b6d114aSBen Gras error = copyin(pref->pref_plist, buf, pref->pref_len);
4226b6d114aSBen Gras if (error) {
4236b6d114aSBen Gras free(buf, M_TEMP);
4246b6d114aSBen Gras return (error);
4256b6d114aSBen Gras }
4266b6d114aSBen Gras buf[pref->pref_len] = '\0';
4276b6d114aSBen Gras
4286b6d114aSBen Gras switch (type) {
4296b6d114aSBen Gras case PROP_TYPE_ARRAY:
4306b6d114aSBen Gras obj = prop_array_internalize(buf);
4316b6d114aSBen Gras break;
4326b6d114aSBen Gras case PROP_TYPE_DICTIONARY:
4336b6d114aSBen Gras obj = prop_dictionary_internalize(buf);
4346b6d114aSBen Gras break;
4356b6d114aSBen Gras default:
4366b6d114aSBen Gras error = ENOTSUP;
4376b6d114aSBen Gras }
4386b6d114aSBen Gras
4396b6d114aSBen Gras free(buf, M_TEMP);
4406b6d114aSBen Gras if (obj == NULL) {
4416b6d114aSBen Gras if (error == 0)
4426b6d114aSBen Gras error = EIO;
4436b6d114aSBen Gras } else {
4446b6d114aSBen Gras *objp = obj;
4456b6d114aSBen Gras }
4466b6d114aSBen Gras return (error);
4476b6d114aSBen Gras }
4486b6d114aSBen Gras
4496b6d114aSBen Gras
4506b6d114aSBen Gras static int
_prop_object_copyin_ioctl(const struct plistref * pref,const prop_type_t type,const u_long cmd,prop_object_t * objp)4516b6d114aSBen Gras _prop_object_copyin_ioctl(const struct plistref *pref, const prop_type_t type,
4526b6d114aSBen Gras const u_long cmd, prop_object_t *objp)
4536b6d114aSBen Gras {
4546b6d114aSBen Gras if ((cmd & IOC_IN) == 0)
4556b6d114aSBen Gras return (EFAULT);
4566b6d114aSBen Gras
4576b6d114aSBen Gras return _prop_object_copyin(pref, type, objp);
4586b6d114aSBen Gras }
4596b6d114aSBen Gras
4606b6d114aSBen Gras /*
4616b6d114aSBen Gras * prop_array_copyin --
4626b6d114aSBen Gras * Copy in an array passed as a syscall arg.
4636b6d114aSBen Gras */
4646b6d114aSBen Gras int
prop_array_copyin(const struct plistref * pref,prop_array_t * arrayp)4656b6d114aSBen Gras prop_array_copyin(const struct plistref *pref, prop_array_t *arrayp)
4666b6d114aSBen Gras {
4676b6d114aSBen Gras return (_prop_object_copyin(pref, PROP_TYPE_ARRAY,
4686b6d114aSBen Gras (prop_object_t *)arrayp));
4696b6d114aSBen Gras }
4706b6d114aSBen Gras
4716b6d114aSBen Gras /*
4726b6d114aSBen Gras * prop_dictionary_copyin --
4736b6d114aSBen Gras * Copy in a dictionary passed as a syscall arg.
4746b6d114aSBen Gras */
4756b6d114aSBen Gras int
prop_dictionary_copyin(const struct plistref * pref,prop_dictionary_t * dictp)4766b6d114aSBen Gras prop_dictionary_copyin(const struct plistref *pref, prop_dictionary_t *dictp)
4776b6d114aSBen Gras {
4786b6d114aSBen Gras return (_prop_object_copyin(pref, PROP_TYPE_DICTIONARY,
4796b6d114aSBen Gras (prop_object_t *)dictp));
4806b6d114aSBen Gras }
4816b6d114aSBen Gras
4826b6d114aSBen Gras
4836b6d114aSBen Gras /*
4846b6d114aSBen Gras * prop_array_copyin_ioctl --
4856b6d114aSBen Gras * Copy in an array send with an ioctl.
4866b6d114aSBen Gras */
4876b6d114aSBen Gras int
prop_array_copyin_ioctl(const struct plistref * pref,const u_long cmd,prop_array_t * arrayp)4886b6d114aSBen Gras prop_array_copyin_ioctl(const struct plistref *pref, const u_long cmd,
4896b6d114aSBen Gras prop_array_t *arrayp)
4906b6d114aSBen Gras {
4916b6d114aSBen Gras return (_prop_object_copyin_ioctl(pref, PROP_TYPE_ARRAY,
4926b6d114aSBen Gras cmd, (prop_object_t *)arrayp));
4936b6d114aSBen Gras }
4946b6d114aSBen Gras
4956b6d114aSBen Gras /*
4966b6d114aSBen Gras * prop_dictionary_copyin_ioctl --
4976b6d114aSBen Gras * Copy in a dictionary sent with an ioctl.
4986b6d114aSBen Gras */
4996b6d114aSBen Gras int
prop_dictionary_copyin_ioctl(const struct plistref * pref,const u_long cmd,prop_dictionary_t * dictp)5006b6d114aSBen Gras prop_dictionary_copyin_ioctl(const struct plistref *pref, const u_long cmd,
5016b6d114aSBen Gras prop_dictionary_t *dictp)
5026b6d114aSBen Gras {
5036b6d114aSBen Gras return (_prop_object_copyin_ioctl(pref, PROP_TYPE_DICTIONARY,
5046b6d114aSBen Gras cmd, (prop_object_t *)dictp));
5056b6d114aSBen Gras }
5066b6d114aSBen Gras
5076b6d114aSBen Gras static int
_prop_object_copyout(struct plistref * pref,prop_object_t obj)5086b6d114aSBen Gras _prop_object_copyout(struct plistref *pref, prop_object_t obj)
5096b6d114aSBen Gras {
5106b6d114aSBen Gras struct lwp *l = curlwp; /* XXX */
5116b6d114aSBen Gras struct proc *p = l->l_proc;
5126b6d114aSBen Gras char *buf;
513*0a6a1f1dSLionel Sambuc void *uaddr;
5146b6d114aSBen Gras size_t len, rlen;
5156b6d114aSBen Gras int error = 0;
5166b6d114aSBen Gras
5176b6d114aSBen Gras switch (prop_object_type(obj)) {
5186b6d114aSBen Gras case PROP_TYPE_ARRAY:
5196b6d114aSBen Gras buf = prop_array_externalize(obj);
5206b6d114aSBen Gras break;
5216b6d114aSBen Gras case PROP_TYPE_DICTIONARY:
5226b6d114aSBen Gras buf = prop_dictionary_externalize(obj);
5236b6d114aSBen Gras break;
5246b6d114aSBen Gras default:
5256b6d114aSBen Gras return (ENOTSUP);
5266b6d114aSBen Gras }
5276b6d114aSBen Gras if (buf == NULL)
5286b6d114aSBen Gras return (ENOMEM);
5296b6d114aSBen Gras
5306b6d114aSBen Gras len = strlen(buf) + 1;
5316b6d114aSBen Gras rlen = round_page(len);
532*0a6a1f1dSLionel Sambuc uaddr = NULL;
533*0a6a1f1dSLionel Sambuc error = uvm_mmap_anon(p, &uaddr, rlen);
5346b6d114aSBen Gras if (error == 0) {
535*0a6a1f1dSLionel Sambuc error = copyout(buf, uaddr, len);
5366b6d114aSBen Gras if (error == 0) {
537*0a6a1f1dSLionel Sambuc pref->pref_plist = uaddr;
5386b6d114aSBen Gras pref->pref_len = len;
5396b6d114aSBen Gras }
5406b6d114aSBen Gras }
5416b6d114aSBen Gras
5426b6d114aSBen Gras free(buf, M_TEMP);
5436b6d114aSBen Gras
5446b6d114aSBen Gras return (error);
5456b6d114aSBen Gras }
5466b6d114aSBen Gras
5476b6d114aSBen Gras /*
5486b6d114aSBen Gras * prop_array_copyout --
5496b6d114aSBen Gras * Copy out an array to a syscall arg.
5506b6d114aSBen Gras */
5516b6d114aSBen Gras int
prop_array_copyout(struct plistref * pref,prop_array_t array)5526b6d114aSBen Gras prop_array_copyout(struct plistref *pref, prop_array_t array)
5536b6d114aSBen Gras {
5546b6d114aSBen Gras return (_prop_object_copyout(pref, array));
5556b6d114aSBen Gras }
5566b6d114aSBen Gras
5576b6d114aSBen Gras /*
5586b6d114aSBen Gras * prop_dictionary_copyout --
5596b6d114aSBen Gras * Copy out a dictionary to a syscall arg.
5606b6d114aSBen Gras */
5616b6d114aSBen Gras int
prop_dictionary_copyout(struct plistref * pref,prop_dictionary_t dict)5626b6d114aSBen Gras prop_dictionary_copyout(struct plistref *pref, prop_dictionary_t dict)
5636b6d114aSBen Gras {
5646b6d114aSBen Gras return (_prop_object_copyout(pref, dict));
5656b6d114aSBen Gras }
5666b6d114aSBen Gras
5676b6d114aSBen Gras static int
_prop_object_copyout_ioctl(struct plistref * pref,const u_long cmd,prop_object_t obj)5686b6d114aSBen Gras _prop_object_copyout_ioctl(struct plistref *pref, const u_long cmd,
5696b6d114aSBen Gras prop_object_t obj)
5706b6d114aSBen Gras {
5716b6d114aSBen Gras if ((cmd & IOC_OUT) == 0)
5726b6d114aSBen Gras return (EFAULT);
5736b6d114aSBen Gras return _prop_object_copyout(pref, obj);
5746b6d114aSBen Gras }
5756b6d114aSBen Gras
5766b6d114aSBen Gras
5776b6d114aSBen Gras /*
5786b6d114aSBen Gras * prop_array_copyout_ioctl --
5796b6d114aSBen Gras * Copy out an array being received with an ioctl.
5806b6d114aSBen Gras */
5816b6d114aSBen Gras int
prop_array_copyout_ioctl(struct plistref * pref,const u_long cmd,prop_array_t array)5826b6d114aSBen Gras prop_array_copyout_ioctl(struct plistref *pref, const u_long cmd,
5836b6d114aSBen Gras prop_array_t array)
5846b6d114aSBen Gras {
5856b6d114aSBen Gras return (_prop_object_copyout_ioctl(pref, cmd, array));
5866b6d114aSBen Gras }
5876b6d114aSBen Gras
5886b6d114aSBen Gras /*
5896b6d114aSBen Gras * prop_dictionary_copyout_ioctl --
5906b6d114aSBen Gras * Copy out a dictionary being received with an ioctl.
5916b6d114aSBen Gras */
5926b6d114aSBen Gras int
prop_dictionary_copyout_ioctl(struct plistref * pref,const u_long cmd,prop_dictionary_t dict)5936b6d114aSBen Gras prop_dictionary_copyout_ioctl(struct plistref *pref, const u_long cmd,
5946b6d114aSBen Gras prop_dictionary_t dict)
5956b6d114aSBen Gras {
5966b6d114aSBen Gras return (
5976b6d114aSBen Gras _prop_object_copyout_ioctl(pref, cmd, dict));
5986b6d114aSBen Gras }
5996b6d114aSBen Gras #endif /* _KERNEL */
6006b6d114aSBen Gras
6016b6d114aSBen Gras #endif /* __NetBSD__ */
602