]> git.saurik.com Git - apple/xnu.git/blame - bsd/kern/kern_panicinfo.c
xnu-1699.26.8.tar.gz
[apple/xnu.git] / bsd / kern / kern_panicinfo.c
CommitLineData
9bccf70c 1/*
2d21ac55 2 * Copyright (c) 2002-2006 Apple Computer, Inc. All rights reserved.
9bccf70c 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
9bccf70c 5 *
2d21ac55
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
8f6c56a5 14 *
2d21ac55
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
8f6c56a5 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
9bccf70c
A
27 */
28
29#include <sys/param.h>
30#include <sys/fcntl.h>
31#include <sys/malloc.h>
9bccf70c 32#include <sys/proc.h>
9bccf70c
A
33#include <sys/sysctl.h>
34#include <sys/vnode.h>
35#include <sys/vm.h>
91447636 36#include <sys/systm.h>
9bccf70c 37
91447636 38#include <mach/mach_types.h>
9bccf70c 39#include <mach/kern_return.h>
91447636
A
40#include <kern/kern_types.h>
41#include <vm/vm_kern.h>
9bccf70c 42
9bccf70c 43
91447636
A
44/* prototypes not exported by osfmk/console. */
45extern void panic_dialog_test( void );
7ddcb079 46extern void noroot_icon_test(void);
91447636
A
47extern int panic_dialog_set_image( const unsigned char * ptr, unsigned int size );
48extern void panic_dialog_get_image( unsigned char ** ptr, unsigned int * size );
9bccf70c 49
91447636 50/* make the compiler happy */
6d2010ae 51static int sysctl_dopanicinfo SYSCTL_HANDLER_ARGS;
9bccf70c 52
9bccf70c 53
91447636 54#define PANIC_IMAGE_SIZE_LIMIT (32 * 4096) /* 128K - Maximum amount of memory consumed for the panic UI */
9bccf70c 55
91447636
A
56/* Local data */
57static int image_size_limit = PANIC_IMAGE_SIZE_LIMIT;
9bccf70c 58
6d2010ae
A
59/* XXX Should be STATIC for dtrace debugging.. */
60static int
61sysctl_dopanicinfo SYSCTL_HANDLER_ARGS
9bccf70c 62{
6d2010ae
A
63 __unused int cmd = oidp->oid_arg2; /* subcommand*/
64 int *name = arg1; /* oid element argument vector */
65 int namelen = arg2; /* number of oid element arguments */
66 user_addr_t oldp = req->oldptr; /* user buffer copy out address */
67 size_t *oldlenp = &req->oldlen; /* user buffer copy out size */
68 user_addr_t newp = req->newptr; /* user buffer copy in address */
69 size_t newlen = req->newlen; /* user buffer copy in size */
9bccf70c 70 int error = 0;
6d2010ae
A
71 proc_t p = current_proc();
72
91447636
A
73 vm_offset_t newimage = (vm_offset_t )NULL;
74 kern_return_t kret;
75 unsigned char * prev_image_ptr;
76 unsigned int prev_image_size;
77
9bccf70c
A
78 /* all sysctl names at this level are terminal */
79 if (namelen != 1)
80 return (ENOTDIR); /* overloaded */
81
6d2010ae
A
82 /* must be super user to muck with image */
83 if ( (error = proc_suser(p)) )
91447636
A
84 return (error);
85
9bccf70c
A
86 switch (name[0]) {
87 default:
91447636
A
88 return (ENOTSUP);
89
90 case KERN_PANICINFO_TEST:
91
92 panic_dialog_test();
6d2010ae 93 break;
91447636 94
7ddcb079
A
95 case KERN_PANICINFO_NOROOT_TEST:
96 printf("Testing noroot icon \n");
97
98 noroot_icon_test();
99 break;
100
9bccf70c 101 case KERN_PANICINFO_MAXSIZE:
91447636
A
102
103 /* return the image size limits */
104
105 newlen = 0;
106 newp = USER_ADDR_NULL;
107
108 error = sysctl_int(oldp, oldlenp, newp, newlen, &image_size_limit);
109
6d2010ae 110 break;
9bccf70c 111
91447636
A
112 case KERN_PANICINFO_IMAGE:
113
114 /* If we have a new image, allocate wired kernel memory and copy it in from user space */
115 if ( newp != USER_ADDR_NULL ) {
116
117 /* check the length of the incoming image before allocating space for it. */
6d2010ae
A
118 if ( newlen > (size_t)image_size_limit ) {
119 error = ENOMEM;
120 break;
121 }
91447636
A
122
123 /* allocate some kernel wired memory for the new image */
b0d623f7 124 kret = kmem_alloc(kernel_map, &newimage, (vm_size_t)round_page(newlen));
91447636
A
125
126 if (kret != KERN_SUCCESS) {
127 switch (kret) {
128 default:
129 error = EINVAL;
130 break;
131 case KERN_NO_SPACE:
132 case KERN_RESOURCE_SHORTAGE:
133 error = ENOMEM;
134 break;
135 case KERN_PROTECTION_FAILURE:
136 error = EPERM;
137 break;
138 }
6d2010ae 139 break;
91447636
A
140 }
141
142 /* copy the image in from user space */
143 if ( (error = copyin(newp, (char *) newimage, newlen)) )
9bccf70c
A
144 goto errout;
145
91447636
A
146 } else { /* setup to make the default image active */
147
148 newimage = (vm_offset_t )NULL;
149 newlen = 0;
150 }
151
152 /* get the current image location and size */
153 panic_dialog_get_image( &prev_image_ptr, &prev_image_size );
154
155 /* did the caller request a copy of the previous image ? */
156 if ( oldp != USER_ADDR_NULL ) {
157 if ( *oldlenp < prev_image_size ) {
158 error = ERANGE;
159 goto errout;
9bccf70c
A
160 }
161
91447636
A
162 /* copy the image to user space or zero the size if the default image is active */
163 if ( prev_image_ptr != NULL ) {
164 if ( (error = copyout( prev_image_ptr, oldp, prev_image_size )) )
165 goto errout;
9bccf70c 166
91447636
A
167 *oldlenp = prev_image_size;
168 }
169 else /* tell the user that the default image is active */
170 *oldlenp = 0;
171 }
9bccf70c 172
91447636
A
173 /* Make the new image active, or reactivate the default image.
174 But, handle the special case of asking for the current image
175 without changing the current image.
176 */
9bccf70c 177
91447636
A
178 if ( !(oldp && newp == USER_ADDR_NULL) ) {
179 if ( (error = panic_dialog_set_image( (unsigned char *) newimage, newlen )) )
180 goto errout;
9bccf70c 181
91447636
A
182 /* free the wired memory used by the previous image */
183 if ( prev_image_ptr != NULL ) {
b0d623f7
A
184 (void)kmem_free(kernel_map, (vm_offset_t) prev_image_ptr, (vm_size_t)round_page(prev_image_size));
185 printf("Panic UI memory freed (%p)\n", (void *)round_page(prev_image_size));
91447636 186 }
9bccf70c 187 }
91447636 188
6d2010ae 189 break;
91447636 190
9bccf70c 191errout:
91447636 192 if ( newimage != (vm_offset_t )NULL )
b0d623f7 193 (void)kmem_free(kernel_map, newimage, (vm_size_t)round_page(newlen));
91447636 194
6d2010ae 195 break;
9bccf70c 196 }
6d2010ae
A
197
198 /* adjust index so we return the right required/consumed amount */
199 if (!error)
200 req->oldidx += req->oldlen;
201
202 return (error);
9bccf70c 203}
6d2010ae
A
204SYSCTL_PROC(_kern, KERN_PANICINFO, panicinfo, CTLTYPE_NODE|CTLFLAG_RW | CTLFLAG_LOCKED | CTLFLAG_ANYBODY,
205 0, /* Pointer argument (arg1) */
206 0, /* Integer argument (arg2) */
207 sysctl_dopanicinfo, /* Handler function */
208 NULL, /* Data pointer */
209 "");