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