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
));