xref: /netbsd/common/lib/libprop/prop_kern.c (revision f7c0aabf)
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