1*f7c0aabfSriastradh /* $NetBSD: prop_kern.c,v 1.25 2022/08/03 21:13:46 riastradh Exp $ */
2434b7a76Sthorpej
3434b7a76Sthorpej /*-
46947118aSbad * Copyright (c) 2006, 2009 The NetBSD Foundation, Inc.
5434b7a76Sthorpej * All rights reserved.
6434b7a76Sthorpej *
7434b7a76Sthorpej * This code is derived from software contributed to The NetBSD Foundation
8434b7a76Sthorpej * by Jason R. Thorpe.
9434b7a76Sthorpej *
10434b7a76Sthorpej * Redistribution and use in source and binary forms, with or without
11434b7a76Sthorpej * modification, are permitted provided that the following conditions
12434b7a76Sthorpej * are met:
13434b7a76Sthorpej * 1. Redistributions of source code must retain the above copyright
14434b7a76Sthorpej * notice, this list of conditions and the following disclaimer.
15434b7a76Sthorpej * 2. Redistributions in binary form must reproduce the above copyright
16434b7a76Sthorpej * notice, this list of conditions and the following disclaimer in the
17434b7a76Sthorpej * documentation and/or other materials provided with the distribution.
18434b7a76Sthorpej *
19434b7a76Sthorpej * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20434b7a76Sthorpej * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21434b7a76Sthorpej * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22434b7a76Sthorpej * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23434b7a76Sthorpej * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24434b7a76Sthorpej * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25434b7a76Sthorpej * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26434b7a76Sthorpej * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27434b7a76Sthorpej * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28434b7a76Sthorpej * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29434b7a76Sthorpej * POSSIBILITY OF SUCH DAMAGE.
30434b7a76Sthorpej */
31434b7a76Sthorpej
32434b7a76Sthorpej #if defined(__NetBSD__)
33434b7a76Sthorpej
34434b7a76Sthorpej #include <sys/types.h>
35434b7a76Sthorpej #include <sys/ioctl.h>
36434b7a76Sthorpej
37434b7a76Sthorpej #include <prop/proplib.h>
38434b7a76Sthorpej
39434b7a76Sthorpej #if !defined(_KERNEL) && !defined(_STANDALONE)
4072729986Sdbj #include <sys/mman.h>
41434b7a76Sthorpej #include <errno.h>
42434b7a76Sthorpej #include <string.h>
43434b7a76Sthorpej #include <stdlib.h>
446cf1ffe9Sthorpej #include <stdio.h>
456cf1ffe9Sthorpej
466e6f1021Spooka #ifdef RUMP_ACTION
476e6f1021Spooka #include <rump/rump_syscalls.h>
486e6f1021Spooka #define ioctl(a,b,c) rump_sys_ioctl(a,b,c)
496e6f1021Spooka #endif
506e6f1021Spooka
516cf1ffe9Sthorpej static int
_prop_object_externalize_to_pref(prop_object_t obj,struct plistref * pref,char ** bufp)5214d305f3Sjym _prop_object_externalize_to_pref(prop_object_t obj, struct plistref *pref,
5314d305f3Sjym char **bufp)
546cf1ffe9Sthorpej {
556cf1ffe9Sthorpej char *buf;
566cf1ffe9Sthorpej
571aea07a3Sthorpej switch (prop_object_type(obj)) {
581aea07a3Sthorpej case PROP_TYPE_DICTIONARY:
591aea07a3Sthorpej buf = prop_dictionary_externalize(obj);
601aea07a3Sthorpej break;
611aea07a3Sthorpej case PROP_TYPE_ARRAY:
621aea07a3Sthorpej buf = prop_array_externalize(obj);
631aea07a3Sthorpej break;
641aea07a3Sthorpej default:
651aea07a3Sthorpej return (ENOTSUP);
661aea07a3Sthorpej }
676cf1ffe9Sthorpej if (buf == NULL) {
686cf1ffe9Sthorpej /* Assume we ran out of memory. */
696cf1ffe9Sthorpej return (ENOMEM);
706cf1ffe9Sthorpej }
716cf1ffe9Sthorpej pref->pref_plist = buf;
726cf1ffe9Sthorpej pref->pref_len = strlen(buf) + 1;
736cf1ffe9Sthorpej
746cf1ffe9Sthorpej *bufp = buf;
756cf1ffe9Sthorpej
766cf1ffe9Sthorpej return (0);
776cf1ffe9Sthorpej }
78434b7a76Sthorpej
796947118aSbad bool
prop_array_externalize_to_pref(prop_array_t array,struct plistref * prefp)806947118aSbad prop_array_externalize_to_pref(prop_array_t array, struct plistref *prefp)
816947118aSbad {
826947118aSbad char *buf;
836947118aSbad int rv;
846947118aSbad
856947118aSbad rv = _prop_object_externalize_to_pref(array, prefp, &buf);
866947118aSbad if (rv != 0)
876947118aSbad errno = rv; /* pass up error value in errno */
886947118aSbad return (rv == 0);
896947118aSbad }
906947118aSbad
916947118aSbad /*
9214d305f3Sjym * prop_array_externalize_to_pref --
9314d305f3Sjym * Externalize an array into a plistref for sending to the kernel.
946947118aSbad */
9514d305f3Sjym int
prop_array_send_syscall(prop_array_t array,struct plistref * prefp)9614d305f3Sjym prop_array_send_syscall(prop_array_t array, struct plistref *prefp)
9714d305f3Sjym {
9814d305f3Sjym if (prop_array_externalize_to_pref(array, prefp))
9914d305f3Sjym return 0;
10014d305f3Sjym else
10114d305f3Sjym return errno;
10214d305f3Sjym }
10314d305f3Sjym
1046947118aSbad bool
prop_dictionary_externalize_to_pref(prop_dictionary_t dict,struct plistref * prefp)10514d305f3Sjym prop_dictionary_externalize_to_pref(prop_dictionary_t dict,
10614d305f3Sjym struct plistref *prefp)
1076947118aSbad {
1086947118aSbad char *buf;
1096947118aSbad int rv;
1106947118aSbad
1116947118aSbad rv = _prop_object_externalize_to_pref(dict, prefp, &buf);
1126947118aSbad if (rv != 0)
1136947118aSbad errno = rv; /* pass up error value in errno */
1146947118aSbad return (rv == 0);
1156947118aSbad }
11614d305f3Sjym
11714d305f3Sjym /*
11814d305f3Sjym * prop_dictionary_externalize_to_pref --
11914d305f3Sjym * Externalize an dictionary into a plistref for sending to the kernel.
12014d305f3Sjym */
12114d305f3Sjym int
prop_dictionary_send_syscall(prop_dictionary_t dict,struct plistref * prefp)12214d305f3Sjym prop_dictionary_send_syscall(prop_dictionary_t dict,
12314d305f3Sjym struct plistref *prefp)
12414d305f3Sjym {
12514d305f3Sjym if (prop_dictionary_externalize_to_pref(dict, prefp))
12614d305f3Sjym return 0;
12714d305f3Sjym else
12814d305f3Sjym return errno;
12914d305f3Sjym }
1306947118aSbad
1311aea07a3Sthorpej static int
_prop_object_send_ioctl(prop_object_t obj,int fd,unsigned long cmd)1321aea07a3Sthorpej _prop_object_send_ioctl(prop_object_t obj, int fd, unsigned long cmd)
133434b7a76Sthorpej {
134434b7a76Sthorpej struct plistref pref;
135434b7a76Sthorpej char *buf;
136434b7a76Sthorpej int error;
137434b7a76Sthorpej
1386947118aSbad error = _prop_object_externalize_to_pref(obj, &pref, &buf);
1396cf1ffe9Sthorpej if (error)
1406cf1ffe9Sthorpej return (error);
141434b7a76Sthorpej
142434b7a76Sthorpej if (ioctl(fd, cmd, &pref) == -1)
143434b7a76Sthorpej error = errno;
144434b7a76Sthorpej else
145434b7a76Sthorpej error = 0;
146434b7a76Sthorpej
147434b7a76Sthorpej free(buf);
148434b7a76Sthorpej
149434b7a76Sthorpej return (error);
150434b7a76Sthorpej }
151434b7a76Sthorpej
1521aea07a3Sthorpej /*
1531aea07a3Sthorpej * prop_array_send_ioctl --
1541aea07a3Sthorpej * Send an array to the kernel using the specified ioctl.
1551aea07a3Sthorpej */
1561aea07a3Sthorpej int
prop_array_send_ioctl(prop_array_t array,int fd,unsigned long cmd)1571aea07a3Sthorpej prop_array_send_ioctl(prop_array_t array, int fd, unsigned long cmd)
1586cf1ffe9Sthorpej {
15914d305f3Sjym int rv;
1601aea07a3Sthorpej
16114d305f3Sjym rv = _prop_object_send_ioctl(array, fd, cmd);
16214d305f3Sjym if (rv != 0) {
16314d305f3Sjym errno = rv; /* pass up error value in errno */
16414d305f3Sjym return rv;
16514d305f3Sjym } else
16614d305f3Sjym return 0;
1671aea07a3Sthorpej }
1681aea07a3Sthorpej
1691aea07a3Sthorpej /*
1701aea07a3Sthorpej * prop_dictionary_send_ioctl --
1711aea07a3Sthorpej * Send a dictionary to the kernel using the specified ioctl.
1721aea07a3Sthorpej */
1731aea07a3Sthorpej int
prop_dictionary_send_ioctl(prop_dictionary_t dict,int fd,unsigned long cmd)1741aea07a3Sthorpej prop_dictionary_send_ioctl(prop_dictionary_t dict, int fd, unsigned long cmd)
1751aea07a3Sthorpej {
17614d305f3Sjym int rv;
1771aea07a3Sthorpej
17814d305f3Sjym rv = _prop_object_send_ioctl(dict, fd, cmd);
17914d305f3Sjym if (rv != 0) {
18014d305f3Sjym errno = rv; /* pass up error value in errno */
18114d305f3Sjym return rv;
18214d305f3Sjym } else
18314d305f3Sjym return 0;
1841aea07a3Sthorpej }
1851aea07a3Sthorpej
1861aea07a3Sthorpej static int
_prop_object_internalize_from_pref(const struct plistref * pref,prop_type_t type,prop_object_t * objp)18714d305f3Sjym _prop_object_internalize_from_pref(const struct plistref *pref,
18814d305f3Sjym prop_type_t type, prop_object_t *objp)
1891aea07a3Sthorpej {
1901aea07a3Sthorpej prop_object_t obj = NULL;
1916cf1ffe9Sthorpej char *buf;
1921aea07a3Sthorpej int error = 0;
1936cf1ffe9Sthorpej
1946cf1ffe9Sthorpej if (pref->pref_len == 0) {
1956cf1ffe9Sthorpej /*
1966cf1ffe9Sthorpej * This should never happen; we should always get the XML
1976cf1ffe9Sthorpej * for an empty dictionary if it's really empty.
1986cf1ffe9Sthorpej */
1996cf1ffe9Sthorpej error = EIO;
2006cf1ffe9Sthorpej goto out;
2016cf1ffe9Sthorpej } else {
2026cf1ffe9Sthorpej buf = pref->pref_plist;
2036cf1ffe9Sthorpej buf[pref->pref_len - 1] = '\0'; /* extra insurance */
2041aea07a3Sthorpej switch (type) {
2051aea07a3Sthorpej case PROP_TYPE_DICTIONARY:
2061aea07a3Sthorpej obj = prop_dictionary_internalize(buf);
2071aea07a3Sthorpej break;
2081aea07a3Sthorpej case PROP_TYPE_ARRAY:
2091aea07a3Sthorpej obj = prop_array_internalize(buf);
2101aea07a3Sthorpej break;
2111aea07a3Sthorpej default:
2121aea07a3Sthorpej error = ENOTSUP;
2131aea07a3Sthorpej }
2146cf1ffe9Sthorpej (void) munmap(buf, pref->pref_len);
2151aea07a3Sthorpej if (obj == NULL && error == 0)
2166cf1ffe9Sthorpej error = EIO;
2176cf1ffe9Sthorpej }
2186cf1ffe9Sthorpej
2196cf1ffe9Sthorpej out:
2206cf1ffe9Sthorpej if (error == 0)
2211aea07a3Sthorpej *objp = obj;
2226cf1ffe9Sthorpej return (error);
2236cf1ffe9Sthorpej }
2246cf1ffe9Sthorpej
225434b7a76Sthorpej /*
22614d305f3Sjym * prop_array_internalize_from_pref --
22714d305f3Sjym * Internalize a pref into a prop_array_t object.
22814d305f3Sjym */
22914d305f3Sjym bool
prop_array_internalize_from_pref(const struct plistref * prefp,prop_array_t * arrayp)23014d305f3Sjym prop_array_internalize_from_pref(const struct plistref *prefp,
23114d305f3Sjym prop_array_t *arrayp)
23214d305f3Sjym {
23314d305f3Sjym int rv;
23414d305f3Sjym
23514d305f3Sjym rv = _prop_object_internalize_from_pref(prefp, PROP_TYPE_ARRAY,
23614d305f3Sjym (prop_object_t *)arrayp);
23714d305f3Sjym if (rv != 0)
23814d305f3Sjym errno = rv; /* pass up error value in errno */
23914d305f3Sjym return (rv == 0);
24014d305f3Sjym }
24114d305f3Sjym
24214d305f3Sjym /*
24314d305f3Sjym * prop_array_recv_syscall --
24414d305f3Sjym * Internalize an array received from the kernel as pref.
24514d305f3Sjym */
24614d305f3Sjym int
prop_array_recv_syscall(const struct plistref * prefp,prop_array_t * arrayp)24714d305f3Sjym prop_array_recv_syscall(const struct plistref *prefp,
24814d305f3Sjym prop_array_t *arrayp)
24914d305f3Sjym {
25014d305f3Sjym if (prop_array_internalize_from_pref(prefp, arrayp))
25114d305f3Sjym return 0;
25214d305f3Sjym else
25314d305f3Sjym return errno;
25414d305f3Sjym }
25514d305f3Sjym
25614d305f3Sjym /*
25714d305f3Sjym * prop_dictionary_internalize_from_pref --
25814d305f3Sjym * Internalize a pref into a prop_dictionary_t object.
25914d305f3Sjym */
26014d305f3Sjym bool
prop_dictionary_internalize_from_pref(const struct plistref * prefp,prop_dictionary_t * dictp)26114d305f3Sjym prop_dictionary_internalize_from_pref(const struct plistref *prefp,
26214d305f3Sjym prop_dictionary_t *dictp)
26314d305f3Sjym {
26414d305f3Sjym int rv;
26514d305f3Sjym
26614d305f3Sjym rv = _prop_object_internalize_from_pref(prefp, PROP_TYPE_DICTIONARY,
26714d305f3Sjym (prop_object_t *)dictp);
26814d305f3Sjym if (rv != 0)
26914d305f3Sjym errno = rv; /* pass up error value in errno */
27014d305f3Sjym return (rv == 0);
27114d305f3Sjym }
27214d305f3Sjym
27314d305f3Sjym /*
27414d305f3Sjym * prop_dictionary_recv_syscall --
27514d305f3Sjym * Internalize a dictionary received from the kernel as pref.
27614d305f3Sjym */
27714d305f3Sjym int
prop_dictionary_recv_syscall(const struct plistref * prefp,prop_dictionary_t * dictp)27814d305f3Sjym prop_dictionary_recv_syscall(const struct plistref *prefp,
27914d305f3Sjym prop_dictionary_t *dictp)
28014d305f3Sjym {
28114d305f3Sjym if (prop_dictionary_internalize_from_pref(prefp, dictp))
28214d305f3Sjym return 0;
28314d305f3Sjym else
28414d305f3Sjym return errno;
28514d305f3Sjym }
28614d305f3Sjym
28714d305f3Sjym
28814d305f3Sjym /*
2891aea07a3Sthorpej * prop_array_recv_ioctl --
2901aea07a3Sthorpej * Receive an array from the kernel using the specified ioctl.
2911aea07a3Sthorpej */
2921aea07a3Sthorpej int
prop_array_recv_ioctl(int fd,unsigned long cmd,prop_array_t * arrayp)2931aea07a3Sthorpej prop_array_recv_ioctl(int fd, unsigned long cmd, prop_array_t *arrayp)
2941aea07a3Sthorpej {
29514d305f3Sjym int rv;
2961aea07a3Sthorpej struct plistref pref;
2971aea07a3Sthorpej
29814d305f3Sjym rv = ioctl(fd, cmd, &pref);
29914d305f3Sjym if (rv == -1)
30014d305f3Sjym return errno;
3011aea07a3Sthorpej
30214d305f3Sjym rv = _prop_object_internalize_from_pref(&pref, PROP_TYPE_ARRAY,
30314d305f3Sjym (prop_object_t *)arrayp);
30414d305f3Sjym if (rv != 0) {
30514d305f3Sjym errno = rv; /* pass up error value in errno */
30614d305f3Sjym return rv;
30714d305f3Sjym } else
30814d305f3Sjym return 0;
3091aea07a3Sthorpej }
3101aea07a3Sthorpej
3111aea07a3Sthorpej /*
312434b7a76Sthorpej * prop_dictionary_recv_ioctl --
313434b7a76Sthorpej * Receive a dictionary from the kernel using the specified ioctl.
314434b7a76Sthorpej */
315434b7a76Sthorpej int
prop_dictionary_recv_ioctl(int fd,unsigned long cmd,prop_dictionary_t * dictp)316434b7a76Sthorpej prop_dictionary_recv_ioctl(int fd, unsigned long cmd, prop_dictionary_t *dictp)
317434b7a76Sthorpej {
31814d305f3Sjym int rv;
319434b7a76Sthorpej struct plistref pref;
320434b7a76Sthorpej
32114d305f3Sjym rv = ioctl(fd, cmd, &pref);
32214d305f3Sjym if (rv == -1)
32314d305f3Sjym return errno;
324434b7a76Sthorpej
32514d305f3Sjym rv = _prop_object_internalize_from_pref(&pref, PROP_TYPE_DICTIONARY,
32614d305f3Sjym (prop_object_t *)dictp);
32714d305f3Sjym if (rv != 0) {
32814d305f3Sjym errno = rv; /* pass up error value in errno */
32914d305f3Sjym return rv;
33014d305f3Sjym } else
33114d305f3Sjym return 0;
3328e917281Sbouyer }
3338e917281Sbouyer
3348e917281Sbouyer /*
3356cf1ffe9Sthorpej * prop_dictionary_sendrecv_ioctl --
3366cf1ffe9Sthorpej * Combination send/receive a dictionary to/from the kernel using
3376cf1ffe9Sthorpej * the specified ioctl.
338434b7a76Sthorpej */
3396cf1ffe9Sthorpej int
prop_dictionary_sendrecv_ioctl(prop_dictionary_t dict,int fd,unsigned long cmd,prop_dictionary_t * dictp)3406cf1ffe9Sthorpej prop_dictionary_sendrecv_ioctl(prop_dictionary_t dict, int fd,
3416cf1ffe9Sthorpej unsigned long cmd, prop_dictionary_t *dictp)
3426cf1ffe9Sthorpej {
3436cf1ffe9Sthorpej struct plistref pref;
3446cf1ffe9Sthorpej char *buf;
3456cf1ffe9Sthorpej int error;
3466cf1ffe9Sthorpej
3476947118aSbad error = _prop_object_externalize_to_pref(dict, &pref, &buf);
34814d305f3Sjym if (error != 0) {
34914d305f3Sjym errno = error;
35014d305f3Sjym return error;
35114d305f3Sjym }
3526cf1ffe9Sthorpej
3536cf1ffe9Sthorpej if (ioctl(fd, cmd, &pref) == -1)
3546cf1ffe9Sthorpej error = errno;
3556cf1ffe9Sthorpej else
3566cf1ffe9Sthorpej error = 0;
357434b7a76Sthorpej
358434b7a76Sthorpej free(buf);
359434b7a76Sthorpej
36014d305f3Sjym if (error != 0)
36114d305f3Sjym return error;
362434b7a76Sthorpej
36314d305f3Sjym error = _prop_object_internalize_from_pref(&pref, PROP_TYPE_DICTIONARY,
36414d305f3Sjym (prop_object_t *)dictp);
36514d305f3Sjym if (error != 0) {
36614d305f3Sjym errno = error; /* pass up error value in errno */
36714d305f3Sjym return error;
36814d305f3Sjym } else
36914d305f3Sjym return 0;
370434b7a76Sthorpej }
371434b7a76Sthorpej #endif /* !_KERNEL && !_STANDALONE */
372434b7a76Sthorpej
373434b7a76Sthorpej #if defined(_KERNEL)
3746cf1ffe9Sthorpej #include <sys/param.h>
3759c80a283Sdogcow #include <sys/mman.h>
376434b7a76Sthorpej #include <sys/errno.h>
377434b7a76Sthorpej #include <sys/malloc.h>
378434b7a76Sthorpej #include <sys/systm.h>
3796cf1ffe9Sthorpej #include <sys/proc.h>
3806cf1ffe9Sthorpej #include <sys/resource.h>
381fbd53556Spooka #include <sys/pool.h>
3826cf1ffe9Sthorpej
3835550f063Schs #include <uvm/uvm_extern.h>
384434b7a76Sthorpej
385fbd53556Spooka #include "prop_object_impl.h"
386fbd53556Spooka
3870a17deccSchristos /* Arbitrary limit ioctl input to 128KB */
3880a17deccSchristos unsigned int prop_object_copyin_limit = 128 * 1024;
389e835604cSjoerg
390fbd53556Spooka /* initialize proplib for use in the kernel */
391fbd53556Spooka void
prop_kern_init(void)392fbd53556Spooka prop_kern_init(void)
393fbd53556Spooka {
394fbd53556Spooka __link_set_decl(prop_linkpools, struct prop_pool_init);
395fbd53556Spooka struct prop_pool_init * const *pi;
396fbd53556Spooka
397fbd53556Spooka __link_set_foreach(pi, prop_linkpools)
398fbd53556Spooka pool_init((*pi)->pp, (*pi)->size, 0, 0, 0, (*pi)->wchan,
399fbd53556Spooka &pool_allocator_nointr, IPL_NONE);
400fbd53556Spooka }
401fbd53556Spooka
4021aea07a3Sthorpej static int
_prop_object_copyin(const struct plistref * pref,const prop_type_t type,prop_object_t * objp,size_t lim)4036947118aSbad _prop_object_copyin(const struct plistref *pref, const prop_type_t type,
4042bb8f922Schristos prop_object_t *objp, size_t lim)
405434b7a76Sthorpej {
4061aea07a3Sthorpej prop_object_t obj = NULL;
407434b7a76Sthorpej char *buf;
408434b7a76Sthorpej int error;
409434b7a76Sthorpej
4102bb8f922Schristos if (pref->pref_len >= lim)
4110a17deccSchristos return E2BIG;
41235f7227aSchristos
413434b7a76Sthorpej /*
414434b7a76Sthorpej * Allocate an extra byte so we can guarantee NUL-termination.
415434b7a76Sthorpej */
4161df1fda9Sjdolecek buf = malloc(pref->pref_len + 1, M_TEMP, M_WAITOK);
417e835604cSjoerg if (buf == NULL)
418e835604cSjoerg return (ENOMEM);
4196cf1ffe9Sthorpej error = copyin(pref->pref_plist, buf, pref->pref_len);
420434b7a76Sthorpej if (error) {
421434b7a76Sthorpej free(buf, M_TEMP);
422434b7a76Sthorpej return (error);
423434b7a76Sthorpej }
424434b7a76Sthorpej buf[pref->pref_len] = '\0';
425434b7a76Sthorpej
4261aea07a3Sthorpej switch (type) {
4271aea07a3Sthorpej case PROP_TYPE_ARRAY:
4281aea07a3Sthorpej obj = prop_array_internalize(buf);
4291aea07a3Sthorpej break;
4301aea07a3Sthorpej case PROP_TYPE_DICTIONARY:
4311aea07a3Sthorpej obj = prop_dictionary_internalize(buf);
4321aea07a3Sthorpej break;
4331aea07a3Sthorpej default:
4341aea07a3Sthorpej error = ENOTSUP;
4351aea07a3Sthorpej }
436434b7a76Sthorpej
4371aea07a3Sthorpej free(buf, M_TEMP);
4381aea07a3Sthorpej if (obj == NULL) {
4391aea07a3Sthorpej if (error == 0)
4401aea07a3Sthorpej error = EIO;
4411aea07a3Sthorpej } else {
4421aea07a3Sthorpej *objp = obj;
4431aea07a3Sthorpej }
4441aea07a3Sthorpej return (error);
445434b7a76Sthorpej }
446434b7a76Sthorpej
4476947118aSbad
4486947118aSbad static int
_prop_object_copyin_ioctl(const struct plistref * pref,const prop_type_t type,const u_long cmd,prop_object_t * objp,size_t lim)4496947118aSbad _prop_object_copyin_ioctl(const struct plistref *pref, const prop_type_t type,
4502bb8f922Schristos const u_long cmd, prop_object_t *objp, size_t lim)
4516947118aSbad {
4526947118aSbad if ((cmd & IOC_IN) == 0)
4536947118aSbad return (EFAULT);
4546947118aSbad
4552bb8f922Schristos return _prop_object_copyin(pref, type, objp, lim);
4566947118aSbad }
4576947118aSbad
4586947118aSbad /*
4596947118aSbad * prop_array_copyin --
4606947118aSbad * Copy in an array passed as a syscall arg.
4616947118aSbad */
4626947118aSbad int
prop_array_copyin_size(const struct plistref * pref,prop_array_t * arrayp,size_t lim)4632bb8f922Schristos prop_array_copyin_size(const struct plistref *pref, prop_array_t *arrayp,
4642bb8f922Schristos size_t lim)
4652bb8f922Schristos {
4662bb8f922Schristos return _prop_object_copyin(pref, PROP_TYPE_ARRAY,
4672bb8f922Schristos (prop_object_t *)arrayp, lim);
4682bb8f922Schristos }
4692bb8f922Schristos
4702bb8f922Schristos int
prop_array_copyin(const struct plistref * pref,prop_array_t * arrayp)4716947118aSbad prop_array_copyin(const struct plistref *pref, prop_array_t *arrayp)
4726947118aSbad {
4732bb8f922Schristos return prop_array_copyin_size(pref, arrayp, prop_object_copyin_limit);
4746947118aSbad }
4756947118aSbad
4766947118aSbad /*
4776947118aSbad * prop_dictionary_copyin --
4786947118aSbad * Copy in a dictionary passed as a syscall arg.
4796947118aSbad */
4806947118aSbad int
prop_dictionary_copyin_size(const struct plistref * pref,prop_dictionary_t * dictp,size_t lim)4812bb8f922Schristos prop_dictionary_copyin_size(const struct plistref *pref,
4822bb8f922Schristos prop_dictionary_t *dictp, size_t lim)
4832bb8f922Schristos {
4842bb8f922Schristos return _prop_object_copyin(pref, PROP_TYPE_DICTIONARY,
4852bb8f922Schristos (prop_object_t *)dictp, lim);
4862bb8f922Schristos }
4872bb8f922Schristos
4882bb8f922Schristos int
prop_dictionary_copyin(const struct plistref * pref,prop_dictionary_t * dictp)4896947118aSbad prop_dictionary_copyin(const struct plistref *pref, prop_dictionary_t *dictp)
4906947118aSbad {
4912bb8f922Schristos return prop_dictionary_copyin_size(pref, dictp,
4922bb8f922Schristos prop_object_copyin_limit);
493045b7178Schristos }
4946947118aSbad
495434b7a76Sthorpej /*
4961aea07a3Sthorpej * prop_array_copyin_ioctl --
4971aea07a3Sthorpej * Copy in an array send with an ioctl.
498434b7a76Sthorpej */
499434b7a76Sthorpej int
prop_array_copyin_ioctl_size(const struct plistref * pref,const u_long cmd,prop_array_t * arrayp,size_t lim)5002bb8f922Schristos prop_array_copyin_ioctl_size(const struct plistref *pref, const u_long cmd,
5012bb8f922Schristos prop_array_t *arrayp, size_t lim)
5022bb8f922Schristos {
5032bb8f922Schristos return _prop_object_copyin_ioctl(pref, PROP_TYPE_ARRAY,
5042bb8f922Schristos cmd, (prop_object_t *)arrayp, lim);
5052bb8f922Schristos }
5062bb8f922Schristos
5072bb8f922Schristos int
prop_array_copyin_ioctl(const struct plistref * pref,const u_long cmd,prop_array_t * arrayp)5081aea07a3Sthorpej prop_array_copyin_ioctl(const struct plistref *pref, const u_long cmd,
5091aea07a3Sthorpej prop_array_t *arrayp)
5101aea07a3Sthorpej {
511548f2556Schristos return prop_array_copyin_ioctl_size(pref, cmd, arrayp,
5122bb8f922Schristos prop_object_copyin_limit);
5131aea07a3Sthorpej }
5141aea07a3Sthorpej
5151aea07a3Sthorpej /*
5161aea07a3Sthorpej * prop_dictionary_copyin_ioctl --
5171aea07a3Sthorpej * Copy in a dictionary sent with an ioctl.
5181aea07a3Sthorpej */
5191aea07a3Sthorpej int
prop_dictionary_copyin_ioctl_size(const struct plistref * pref,const u_long cmd,prop_dictionary_t * dictp,size_t lim)5202bb8f922Schristos prop_dictionary_copyin_ioctl_size(const struct plistref *pref, const u_long cmd,
5212bb8f922Schristos prop_dictionary_t *dictp, size_t lim)
5222bb8f922Schristos {
5232bb8f922Schristos return _prop_object_copyin_ioctl(pref, PROP_TYPE_DICTIONARY,
5242bb8f922Schristos cmd, (prop_object_t *)dictp, lim);
5252bb8f922Schristos }
5262bb8f922Schristos
5272bb8f922Schristos int
prop_dictionary_copyin_ioctl(const struct plistref * pref,const u_long cmd,prop_dictionary_t * dictp)5281aea07a3Sthorpej prop_dictionary_copyin_ioctl(const struct plistref *pref, const u_long cmd,
5291aea07a3Sthorpej prop_dictionary_t *dictp)
5301aea07a3Sthorpej {
531548f2556Schristos return prop_dictionary_copyin_ioctl_size(pref, cmd, dictp,
5322bb8f922Schristos prop_object_copyin_limit);
5331aea07a3Sthorpej }
5341aea07a3Sthorpej
5351aea07a3Sthorpej static int
_prop_object_copyout(struct plistref * pref,prop_object_t obj)5368e917281Sbouyer _prop_object_copyout(struct plistref *pref, prop_object_t obj)
537434b7a76Sthorpej {
5386cf1ffe9Sthorpej struct lwp *l = curlwp; /* XXX */
5396cf1ffe9Sthorpej struct proc *p = l->l_proc;
540434b7a76Sthorpej char *buf;
5415550f063Schs void *uaddr;
54200fbe2b7Scube size_t len, rlen;
543434b7a76Sthorpej int error = 0;
5446cf1ffe9Sthorpej
5451aea07a3Sthorpej switch (prop_object_type(obj)) {
5461aea07a3Sthorpej case PROP_TYPE_ARRAY:
5471aea07a3Sthorpej buf = prop_array_externalize(obj);
5481aea07a3Sthorpej break;
5491aea07a3Sthorpej case PROP_TYPE_DICTIONARY:
5501aea07a3Sthorpej buf = prop_dictionary_externalize(obj);
5511aea07a3Sthorpej break;
5521aea07a3Sthorpej default:
5531aea07a3Sthorpej return (ENOTSUP);
5541aea07a3Sthorpej }
555434b7a76Sthorpej if (buf == NULL)
556434b7a76Sthorpej return (ENOMEM);
557434b7a76Sthorpej
558434b7a76Sthorpej len = strlen(buf) + 1;
55900fbe2b7Scube rlen = round_page(len);
5605550f063Schs uaddr = NULL;
5615550f063Schs error = uvm_mmap_anon(p, &uaddr, rlen);
5626cf1ffe9Sthorpej if (error == 0) {
5635550f063Schs error = copyout(buf, uaddr, len);
5646cf1ffe9Sthorpej if (error == 0) {
5655550f063Schs pref->pref_plist = uaddr;
566434b7a76Sthorpej pref->pref_len = len;
5676cf1ffe9Sthorpej }
5686cf1ffe9Sthorpej }
569434b7a76Sthorpej
570434b7a76Sthorpej free(buf, M_TEMP);
571434b7a76Sthorpej
572434b7a76Sthorpej return (error);
573434b7a76Sthorpej }
5741aea07a3Sthorpej
5751aea07a3Sthorpej /*
5768e917281Sbouyer * prop_array_copyout --
5778e917281Sbouyer * Copy out an array to a syscall arg.
5788e917281Sbouyer */
5798e917281Sbouyer int
prop_array_copyout(struct plistref * pref,prop_array_t array)580e50fbcf3Sbouyer prop_array_copyout(struct plistref *pref, prop_array_t array)
5818e917281Sbouyer {
582e50fbcf3Sbouyer return (_prop_object_copyout(pref, array));
5838e917281Sbouyer }
5848e917281Sbouyer
5858e917281Sbouyer /*
5868e917281Sbouyer * prop_dictionary_copyout --
5878e917281Sbouyer * Copy out a dictionary to a syscall arg.
5888e917281Sbouyer */
5898e917281Sbouyer int
prop_dictionary_copyout(struct plistref * pref,prop_dictionary_t dict)590e50fbcf3Sbouyer prop_dictionary_copyout(struct plistref *pref, prop_dictionary_t dict)
5918e917281Sbouyer {
592e50fbcf3Sbouyer return (_prop_object_copyout(pref, dict));
5938e917281Sbouyer }
5948e917281Sbouyer
5958e917281Sbouyer static int
_prop_object_copyout_ioctl(struct plistref * pref,const u_long cmd,prop_object_t obj)5968e917281Sbouyer _prop_object_copyout_ioctl(struct plistref *pref, const u_long cmd,
5978e917281Sbouyer prop_object_t obj)
5988e917281Sbouyer {
5998e917281Sbouyer if ((cmd & IOC_OUT) == 0)
6008e917281Sbouyer return (EFAULT);
6018e917281Sbouyer return _prop_object_copyout(pref, obj);
6028e917281Sbouyer }
6038e917281Sbouyer
6048e917281Sbouyer
6058e917281Sbouyer /*
6061aea07a3Sthorpej * prop_array_copyout_ioctl --
6071aea07a3Sthorpej * Copy out an array being received with an ioctl.
6081aea07a3Sthorpej */
6091aea07a3Sthorpej int
prop_array_copyout_ioctl(struct plistref * pref,const u_long cmd,prop_array_t array)6101aea07a3Sthorpej prop_array_copyout_ioctl(struct plistref *pref, const u_long cmd,
6111aea07a3Sthorpej prop_array_t array)
6121aea07a3Sthorpej {
6131aea07a3Sthorpej return (_prop_object_copyout_ioctl(pref, cmd, array));
6141aea07a3Sthorpej }
6151aea07a3Sthorpej
6161aea07a3Sthorpej /*
6171aea07a3Sthorpej * prop_dictionary_copyout_ioctl --
6181aea07a3Sthorpej * Copy out a dictionary being received with an ioctl.
6191aea07a3Sthorpej */
6201aea07a3Sthorpej int
prop_dictionary_copyout_ioctl(struct plistref * pref,const u_long cmd,prop_dictionary_t dict)6211aea07a3Sthorpej prop_dictionary_copyout_ioctl(struct plistref *pref, const u_long cmd,
6221aea07a3Sthorpej prop_dictionary_t dict)
6231aea07a3Sthorpej {
6248e917281Sbouyer return (
6258e917281Sbouyer _prop_object_copyout_ioctl(pref, cmd, dict));
6261aea07a3Sthorpej }
627434b7a76Sthorpej #endif /* _KERNEL */
628434b7a76Sthorpej
629434b7a76Sthorpej #endif /* __NetBSD__ */
630