1 /* $NetBSD: prop_kern.c,v 1.17 2011/09/30 22:08:18 jym Exp $ */
4 * Copyright (c) 2006, 2009 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/types.h>
34 #include <libprop/proplib.h>
36 #if !defined(_KERNEL) && !defined(_STANDALONE)
42 #include <sys/ioctl.h>
45 _prop_object_externalize_to_pref(prop_object_t obj, struct plistref *pref,
50 switch (prop_object_type(obj)) {
51 case PROP_TYPE_DICTIONARY:
52 buf = prop_dictionary_externalize(obj);
55 buf = prop_array_externalize(obj);
61 /* Assume we ran out of memory. */
64 pref->pref_plist = buf;
65 pref->pref_len = strlen(buf) + 1;
73 prop_array_externalize_to_pref(prop_array_t array, struct plistref *prefp)
78 rv = _prop_object_externalize_to_pref(array, prefp, &buf);
80 errno = rv; /* pass up error value in errno */
85 * prop_array_externalize_to_pref --
86 * Externalize an array into a plistref for sending to the kernel.
89 prop_array_send_syscall(prop_array_t array, struct plistref *prefp)
91 if (prop_array_externalize_to_pref(array, prefp))
98 prop_dictionary_externalize_to_pref(prop_dictionary_t dict,
99 struct plistref *prefp)
104 rv = _prop_object_externalize_to_pref(dict, prefp, &buf);
106 errno = rv; /* pass up error value in errno */
111 * prop_dictionary_externalize_to_pref --
112 * Externalize an dictionary into a plistref for sending to the kernel.
115 prop_dictionary_send_syscall(prop_dictionary_t dict,
116 struct plistref *prefp)
118 if (prop_dictionary_externalize_to_pref(dict, prefp))
125 _prop_object_send_ioctl(prop_object_t obj, int fd, unsigned long cmd)
127 struct plistref pref;
131 error = _prop_object_externalize_to_pref(obj, &pref, &buf);
135 if (ioctl(fd, cmd, &pref) == -1)
146 * prop_array_send_ioctl --
147 * Send an array to the kernel using the specified ioctl.
150 prop_array_send_ioctl(prop_array_t array, int fd, unsigned long cmd)
154 rv = _prop_object_send_ioctl(array, fd, cmd);
156 errno = rv; /* pass up error value in errno */
163 * prop_dictionary_send_ioctl --
164 * Send a dictionary to the kernel using the specified ioctl.
167 prop_dictionary_send_ioctl(prop_dictionary_t dict, int fd, unsigned long cmd)
171 rv = _prop_object_send_ioctl(dict, fd, cmd);
173 errno = rv; /* pass up error value in errno */
180 _prop_object_internalize_from_pref(const struct plistref *pref,
181 prop_type_t type, prop_object_t *objp)
183 prop_object_t obj = NULL;
187 if (pref->pref_len == 0) {
189 * This should never happen; we should always get the XML
190 * for an empty dictionary if it's really empty.
195 buf = pref->pref_plist;
196 buf[pref->pref_len - 1] = '\0'; /* extra insurance */
198 case PROP_TYPE_DICTIONARY:
199 obj = prop_dictionary_internalize(buf);
201 case PROP_TYPE_ARRAY:
202 obj = prop_array_internalize(buf);
207 (void) munmap(buf, pref->pref_len);
208 if (obj == NULL && error == 0)
219 * prop_array_internalize_from_pref --
220 * Internalize a pref into a prop_array_t object.
223 prop_array_internalize_from_pref(const struct plistref *prefp,
224 prop_array_t *arrayp)
228 rv = _prop_object_internalize_from_pref(prefp, PROP_TYPE_ARRAY,
229 (prop_object_t *)arrayp);
231 errno = rv; /* pass up error value in errno */
236 * prop_array_recv_syscall --
237 * Internalize an array received from the kernel as pref.
240 prop_array_recv_syscall(const struct plistref *prefp,
241 prop_array_t *arrayp)
243 if (prop_array_internalize_from_pref(prefp, arrayp))
250 * prop_dictionary_internalize_from_pref --
251 * Internalize a pref into a prop_dictionary_t object.
254 prop_dictionary_internalize_from_pref(const struct plistref *prefp,
255 prop_dictionary_t *dictp)
259 rv = _prop_object_internalize_from_pref(prefp, PROP_TYPE_DICTIONARY,
260 (prop_object_t *)dictp);
262 errno = rv; /* pass up error value in errno */
267 * prop_dictionary_recv_syscall --
268 * Internalize a dictionary received from the kernel as pref.
271 prop_dictionary_recv_syscall(const struct plistref *prefp,
272 prop_dictionary_t *dictp)
274 if (prop_dictionary_internalize_from_pref(prefp, dictp))
282 * prop_array_recv_ioctl --
283 * Receive an array from the kernel using the specified ioctl.
286 prop_array_recv_ioctl(int fd, unsigned long cmd, prop_array_t *arrayp)
289 struct plistref pref;
291 rv = ioctl(fd, cmd, &pref);
295 rv = _prop_object_internalize_from_pref(&pref, PROP_TYPE_ARRAY,
296 (prop_object_t *)arrayp);
298 errno = rv; /* pass up error value in errno */
305 * prop_dictionary_recv_ioctl --
306 * Receive a dictionary from the kernel using the specified ioctl.
309 prop_dictionary_recv_ioctl(int fd, unsigned long cmd, prop_dictionary_t *dictp)
312 struct plistref pref;
314 rv = ioctl(fd, cmd, &pref);
318 rv = _prop_object_internalize_from_pref(&pref, PROP_TYPE_DICTIONARY,
319 (prop_object_t *)dictp);
321 errno = rv; /* pass up error value in errno */
328 * prop_dictionary_sendrecv_ioctl --
329 * Combination send/receive a dictionary to/from the kernel using
330 * the specified ioctl.
333 prop_dictionary_sendrecv_ioctl(prop_dictionary_t dict, int fd,
334 unsigned long cmd, prop_dictionary_t *dictp)
336 struct plistref pref;
340 error = _prop_object_externalize_to_pref(dict, &pref, &buf);
346 if (ioctl(fd, cmd, &pref) == -1)
356 error = _prop_object_internalize_from_pref(&pref, PROP_TYPE_DICTIONARY,
357 (prop_object_t *)dictp);
359 errno = error; /* pass up error value in errno */
364 #endif /* !_KERNEL && !_STANDALONE */
367 #include <sys/param.h>
368 #include <sys/mman.h>
369 #include <sys/errno.h>
370 #include <sys/malloc.h>
371 #include <sys/systm.h>
372 #include <sys/proc.h>
373 #include <sys/resource.h>
374 #include <sys/objcache.h>
375 #include <sys/ioccom.h>
377 #include <vm/vm_extern.h>
378 #include <vm/vm_param.h>
380 #include "prop_object_impl.h"
382 /* Arbitrary limit ioctl input to 64KB */
383 unsigned int prop_object_copyin_limit = 65536;
386 _prop_object_copyin(const struct plistref *pref, const prop_type_t type,
389 prop_object_t obj = NULL;
394 * Allocate an extra byte so we can guarantee NUL-termination.
396 * Allow malloc to fail in case pmap would be exhausted.
398 buf = kmalloc(pref->pref_len + 1, M_TEMP, M_WAITOK);
399 error = copyin(pref->pref_plist, buf, pref->pref_len);
404 buf[pref->pref_len] = '\0';
407 case PROP_TYPE_ARRAY:
408 obj = prop_array_internalize(buf);
410 case PROP_TYPE_DICTIONARY:
411 obj = prop_dictionary_internalize(buf);
429 _prop_object_copyin_ioctl(const struct plistref *pref, const prop_type_t type,
430 const u_long cmd, prop_object_t *objp)
432 if ((cmd & IOC_IN) == 0)
435 return _prop_object_copyin(pref, type, objp);
439 * prop_array_copyin --
440 * Copy in an array passed as a syscall arg.
443 prop_array_copyin(const struct plistref *pref, prop_array_t *arrayp)
445 return (_prop_object_copyin(pref, PROP_TYPE_ARRAY,
446 (prop_object_t *)arrayp));
450 * prop_dictionary_copyin --
451 * Copy in a dictionary passed as a syscall arg.
454 prop_dictionary_copyin(const struct plistref *pref, prop_dictionary_t *dictp)
456 return (_prop_object_copyin(pref, PROP_TYPE_DICTIONARY,
457 (prop_object_t *)dictp));
462 * prop_array_copyin_ioctl --
463 * Copy in an array send with an ioctl.
466 prop_array_copyin_ioctl(const struct plistref *pref, const u_long cmd,
467 prop_array_t *arrayp)
469 return (_prop_object_copyin_ioctl(pref, PROP_TYPE_ARRAY,
470 cmd, (prop_object_t *)arrayp));
474 * prop_dictionary_copyin_ioctl --
475 * Copy in a dictionary sent with an ioctl.
478 prop_dictionary_copyin_ioctl(const struct plistref *pref, const u_long cmd,
479 prop_dictionary_t *dictp)
481 return (_prop_object_copyin_ioctl(pref, PROP_TYPE_DICTIONARY,
482 cmd, (prop_object_t *)dictp));
486 _prop_object_copyout(struct plistref *pref, prop_object_t obj)
488 struct proc *p = curproc;
494 switch (prop_object_type(obj)) {
495 case PROP_TYPE_ARRAY:
496 buf = prop_array_externalize(obj);
498 case PROP_TYPE_DICTIONARY:
499 buf = prop_dictionary_externalize(obj);
507 len = strlen(buf) + 1;
508 rlen = round_page(len);
511 * See sys_mmap() in sys/uvm/uvm_mmap.c.
512 * Let's act as if we were calling mmap(0, ...)
515 uaddr = p->p_emul->e_vm_default_addr(p,
516 (vaddr_t)p->p_vmspace->vm_daddr, rlen);
518 uaddr = round_page((vm_offset_t)p->p_vmspace->vm_daddr + maxdsiz);
520 error = vm_mmap(&p->p_vmspace->vm_map,
522 VM_PROT_READ|VM_PROT_WRITE,
523 VM_PROT_READ|VM_PROT_WRITE,
524 MAP_PRIVATE|MAP_ANON,
527 error = copyout(buf, (char *)uaddr, len);
529 pref->pref_plist = (char *)uaddr;
530 pref->pref_len = len;
540 * prop_array_copyout --
541 * Copy out an array to a syscall arg.
544 prop_array_copyout(struct plistref *pref, prop_array_t array)
546 return (_prop_object_copyout(pref, array));
550 * prop_dictionary_copyout --
551 * Copy out a dictionary to a syscall arg.
554 prop_dictionary_copyout(struct plistref *pref, prop_dictionary_t dict)
556 return (_prop_object_copyout(pref, dict));
560 _prop_object_copyout_ioctl(struct plistref *pref, const u_long cmd,
563 if ((cmd & IOC_OUT) == 0)
565 return _prop_object_copyout(pref, obj);
570 * prop_array_copyout_ioctl --
571 * Copy out an array being received with an ioctl.
574 prop_array_copyout_ioctl(struct plistref *pref, const u_long cmd,
577 return (_prop_object_copyout_ioctl(pref, cmd, array));
581 * prop_dictionary_copyout_ioctl --
582 * Copy out a dictionary being received with an ioctl.
585 prop_dictionary_copyout_ioctl(struct plistref *pref, const u_long cmd,
586 prop_dictionary_t dict)
589 _prop_object_copyout_ioctl(pref, cmd, dict));