Print this page
XXX Rearchitect and replace interrupt distribution
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/uadmin/uadmin.c
+++ new/usr/src/cmd/uadmin/uadmin.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
23 23 */
24 24
25 25 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
26 26 /* All Rights Reserved */
27 27
28 28
29 29
30 30 #include <errno.h>
31 31 #include <fcntl.h>
32 32 #include <stdio.h>
33 33 #include <stdlib.h>
34 34 #include <string.h>
35 35 #include <strings.h>
36 36 #include <signal.h>
37 37 #include <unistd.h>
38 38 #ifdef __i386
39 39 #include <libscf_priv.h>
40 40 #endif /* __i386 */
41 41
42 42 #include <bsm/adt.h>
43 43 #include <bsm/adt_event.h>
44 44
45 45 #include <sys/types.h>
46 46 #include <sys/uadmin.h>
47 47 #include <sys/wait.h>
48 48
49 49 #define SMF_RST "/etc/svc/volatile/resetting"
50 50 #define RETRY_COUNT 15 /* number of 1 sec retries for audit(1M) to complete */
51 51
52 52 static const char *Usage = "Usage: %s cmd fcn [mdep]\n";
53 53
54 54 static int closeout_audit(int, int);
55 55 static int turnoff_auditd(void);
56 56 static void wait_for_auqueue();
57 57 static int change_audit_file(void);
58 58
59 59 int
60 60 main(int argc, char *argv[])
61 61 {
62 62 int cmd, fcn;
63 63 uintptr_t mdep = NULL;
64 64 sigset_t set;
65 65 adt_session_data_t *ah; /* audit session handle */
66 66 adt_event_data_t *event = NULL; /* event to be generated */
67 67 au_event_t event_id;
68 68 enum adt_uadmin_fcn fcn_id;
69 69
70 70 if (argc < 3 || argc > 4) {
71 71 (void) fprintf(stderr, Usage, argv[0]);
72 72 return (1);
73 73 }
74 74
75 75 (void) sigfillset(&set);
76 76 (void) sigprocmask(SIG_BLOCK, &set, NULL);
77 77
78 78 cmd = atoi(argv[1]);
79 79 fcn = atoi(argv[2]);
80 80 if (argc == 4) { /* mdep argument given */
81 81 if (cmd != A_REBOOT && cmd != A_SHUTDOWN && cmd != A_DUMP &&
82 82 cmd != A_FREEZE) {
83 83 (void) fprintf(stderr, "%s: mdep argument not "
84 84 "allowed for this cmd value\n", argv[0]);
85 85 (void) fprintf(stderr, Usage, argv[0]);
86 86 return (1);
87 87 } else {
88 88 mdep = (uintptr_t)argv[3];
89 89 }
90 90 }
91 91
92 92 /* set up audit session and event */
93 93 if (adt_start_session(&ah, NULL, ADT_USE_PROC_DATA) != 0) {
94 94 (void) fprintf(stderr, "%s: can't start audit session\n",
95 95 argv[0]);
96 96 }
97 97 switch (cmd) {
98 98 case A_SHUTDOWN:
99 99 event_id = ADT_uadmin_shutdown;
100 100 break;
101 101 case A_REBOOT:
102 102 event_id = ADT_uadmin_reboot;
103 103 break;
104 104 case A_DUMP:
105 105 event_id = ADT_uadmin_dump;
106 106 break;
107 107 case A_REMOUNT:
108 108 event_id = ADT_uadmin_remount;
109 109 break;
110 110 case A_FREEZE:
111 111 event_id = ADT_uadmin_freeze;
↓ open down ↓ |
111 lines elided |
↑ open up ↑ |
112 112 break;
113 113 case A_FTRACE:
114 114 event_id = ADT_uadmin_ftrace;
115 115 break;
116 116 case A_CONFIG:
117 117 event_id = ADT_uadmin_config;
118 118 break;
119 119 case A_SWAPCTL:
120 120 event_id = ADT_uadmin_swapctl;
121 121 break;
122 + case A_INTRD:
123 + event_id = ADT_uadmin_intrd;
124 + break;
122 125 default:
123 126 event_id = 0;
124 127 }
125 128 if ((event_id != 0) &&
126 129 (event = adt_alloc_event(ah, event_id)) == NULL) {
127 130 (void) fprintf(stderr, "%s: can't allocate audit event\n",
128 131 argv[0]);
129 132 }
130 133 switch (fcn) {
131 134 case AD_HALT:
132 135 fcn_id = ADT_UADMIN_FCN_AD_HALT;
133 136 break;
134 137 case AD_POWEROFF:
135 138 fcn_id = ADT_UADMIN_FCN_AD_POWEROFF;
136 139 break;
137 140 case AD_BOOT:
138 141 fcn_id = ADT_UADMIN_FCN_AD_BOOT;
139 142 break;
140 143 case AD_IBOOT:
141 144 fcn_id = ADT_UADMIN_FCN_AD_IBOOT;
142 145 break;
143 146 case AD_SBOOT:
144 147 fcn_id = ADT_UADMIN_FCN_AD_SBOOT;
145 148 break;
146 149 case AD_SIBOOT:
147 150 fcn_id = ADT_UADMIN_FCN_AD_SIBOOT;
148 151 break;
149 152 case AD_NOSYNC:
150 153 fcn_id = ADT_UADMIN_FCN_AD_NOSYNC;
151 154 break;
152 155 case AD_FASTREBOOT:
153 156 #ifdef __i386
154 157 fcn_id = ADT_UADMIN_FCN_AD_FASTREBOOT;
155 158 mdep = NULL; /* Ignore all arguments */
156 159 #else /* __i386 */
157 160 fcn = AD_BOOT;
158 161 fcn_id = ADT_UADMIN_FCN_AD_BOOT;
159 162 #endif /* __i386 */
160 163 break;
161 164 case AD_FASTREBOOT_DRYRUN:
162 165 fcn_id = ADT_UADMIN_FCN_AD_FASTREBOOT_DRYRUN;
163 166 mdep = NULL; /* Ignore all arguments */
164 167 break;
165 168 default:
166 169 fcn_id = 0;
167 170 }
168 171 if (cmd == A_FREEZE) {
169 172 switch (fcn) {
170 173 case AD_SUSPEND_TO_DISK:
171 174 fcn_id = ADT_UADMIN_FCN_AD_SUSPEND_TO_DISK;
172 175 break;
173 176 case AD_CHECK_SUSPEND_TO_DISK:
174 177 fcn_id = ADT_UADMIN_FCN_AD_CHECK_SUSPEND_TO_DISK;
175 178 break;
176 179 case AD_FORCE:
177 180 fcn_id = ADT_UADMIN_FCN_AD_FORCE;
178 181 break;
179 182 case AD_SUSPEND_TO_RAM:
180 183 fcn_id = ADT_UADMIN_FCN_AD_SUSPEND_TO_RAM;
181 184 break;
182 185 case AD_CHECK_SUSPEND_TO_RAM:
183 186 fcn_id = ADT_UADMIN_FCN_AD_CHECK_SUSPEND_TO_RAM;
184 187 break;
185 188 case AD_REUSEINIT:
186 189 fcn_id = ADT_UADMIN_FCN_AD_REUSEINIT;
187 190 break;
188 191 case AD_REUSABLE:
189 192 fcn_id = ADT_UADMIN_FCN_AD_REUSABLE;
190 193 break;
191 194 case AD_REUSEFINI:
192 195 fcn_id = ADT_UADMIN_FCN_AD_REUSEFINI;
193 196 break;
194 197 }
195 198 } else if (cmd == A_FTRACE) {
196 199 switch (fcn) {
197 200 case AD_FTRACE_START:
198 201 fcn_id = ADT_UADMIN_FCN_AD_FTRACE_START;
199 202 break;
200 203 case AD_FTRACE_STOP:
201 204 fcn_id = ADT_UADMIN_FCN_AD_FTRACE_STOP;
202 205 break;
203 206 }
204 207 #ifdef __i386
205 208 } else if (cmd == A_CONFIG) {
206 209 uint8_t boot_config = 0;
207 210 uint8_t boot_config_ovr = 0;
208 211
209 212 switch (fcn) {
210 213 case AD_UPDATE_BOOT_CONFIG:
211 214 fcn_id = ADT_UADMIN_FCN_AD_UPDATE_BOOT_CONFIG;
212 215 scf_get_boot_config(&boot_config);
213 216 boot_config_ovr = boot_config;
214 217 scf_get_boot_config_ovr(&boot_config_ovr);
215 218 boot_config &= boot_config_ovr;
216 219 mdep = (uintptr_t)(&boot_config);
217 220 break;
218 221 }
219 222 #endif /* __i386 */
220 223 }
221 224
222 225 if (geteuid() == 0) {
223 226 if (event != NULL) {
224 227 switch (cmd) {
225 228 case A_SHUTDOWN:
226 229 event->adt_uadmin_shutdown.fcn = fcn_id;
227 230 event->adt_uadmin_shutdown.mdep = (char *)mdep;
228 231 break;
229 232 case A_REBOOT:
230 233 event->adt_uadmin_reboot.fcn = fcn_id;
231 234 event->adt_uadmin_reboot.mdep = (char *)mdep;
232 235 break;
233 236 case A_DUMP:
234 237 event->adt_uadmin_dump.fcn = fcn_id;
235 238 event->adt_uadmin_dump.mdep = (char *)mdep;
236 239 break;
237 240 case A_REMOUNT:
238 241 /* no parameters */
239 242 break;
240 243 case A_FREEZE:
241 244 event->adt_uadmin_freeze.fcn = fcn_id;
242 245 event->adt_uadmin_freeze.mdep = (char *)mdep;
243 246 break;
244 247 case A_FTRACE:
↓ open down ↓ |
113 lines elided |
↑ open up ↑ |
245 248 event->adt_uadmin_ftrace.fcn = fcn_id;
246 249 event->adt_uadmin_ftrace.mdep = (char *)mdep;
247 250 break;
248 251 case A_CONFIG:
249 252 event->adt_uadmin_config.fcn = fcn_id;
250 253 event->adt_uadmin_config.mdep = (char *)mdep;
251 254 break;
252 255 case A_SWAPCTL:
253 256 event->adt_uadmin_swapctl.fcn = fcn_id;
254 257 break;
258 + case A_INTRD:
259 + event->adt_uadmin_intrd.fcn = fcn_id;
260 + break;
255 261 }
256 262
257 263 if (adt_put_event(event, ADT_SUCCESS, 0) != 0) {
258 264 (void) fprintf(stderr,
259 265 "%s: can't put audit event\n", argv[0]);
260 266 }
261 267 /*
262 268 * allow audit record to be processed in the kernel
263 269 * audit queue
264 270 */
265 271 wait_for_auqueue();
266 272 }
267 273
268 274 if (closeout_audit(cmd, fcn) == -1)
269 275 (void) fprintf(stderr, "%s: can't turn off auditd\n",
270 276 argv[0]);
271 277
272 278 if (cmd == A_SHUTDOWN || cmd == A_REBOOT)
273 279 (void) creat(SMF_RST, 0777);
274 280 }
275 281
276 282 (void) adt_free_event(event);
277 283 if (uadmin(cmd, fcn, mdep) < 0) {
278 284 perror("uadmin");
279 285
280 286 (void) unlink(SMF_RST);
281 287
282 288 return (1);
283 289 }
284 290
285 291 /* If returning from a suspend, audit thaw */
286 292 if ((cmd == A_FREEZE) &&
287 293 ((fcn == AD_FORCE) ||
288 294 (fcn == AD_REUSABLE) ||
289 295 (fcn == AD_SUSPEND_TO_DISK) ||
290 296 (fcn == AD_SUSPEND_TO_RAM))) {
291 297 if ((event = adt_alloc_event(ah, ADT_uadmin_thaw)) == NULL) {
292 298 (void) fprintf(stderr, "%s: can't allocate thaw audit "
293 299 "event\n", argv[0]);
294 300 }
295 301 event->adt_uadmin_thaw.fcn = fcn_id;
296 302 if (adt_put_event(event, ADT_SUCCESS, 0) != 0) {
297 303 (void) fprintf(stderr, "%s: can't put thaw audit "
298 304 "event\n", argv[0]);
299 305 }
300 306 (void) adt_free_event(event);
301 307 }
302 308 (void) adt_end_session(ah);
303 309
304 310 return (0);
305 311 }
306 312
307 313 static int
308 314 closeout_audit(int cmd, int fcn)
309 315 {
310 316 if (!adt_audit_state(AUC_AUDITING)) {
311 317 /* auditd not running, just return */
312 318 return (0);
313 319 }
314 320 switch (cmd) {
315 321 case A_SHUTDOWN:
316 322 switch (fcn) {
317 323 case AD_FASTREBOOT_DRYRUN:
318 324 /* No system discontinuity, don't turn off auditd */
319 325 return (0);
320 326 default:
321 327 break; /* For all the other shutdown functions */
322 328 }
323 329 /* FALLTHROUGH */
324 330 case A_REBOOT:
325 331 case A_DUMP:
326 332 /* system shutting down, turn off auditd */
327 333 return (turnoff_auditd());
328 334 case A_REMOUNT:
329 335 case A_SWAPCTL:
330 336 case A_FTRACE:
331 337 case A_CONFIG:
332 338 /* No system discontinuity, don't turn off auditd */
333 339 return (0);
334 340 case A_FREEZE:
335 341 switch (fcn) {
336 342 case AD_CHECK_SUSPEND_TO_DISK: /* AD_CHECK */
337 343 case AD_CHECK_SUSPEND_TO_RAM:
338 344 case AD_REUSEINIT:
339 345 case AD_REUSEFINI:
340 346 /* No system discontinuity, don't turn off auditd */
341 347 return (0);
342 348 case AD_REUSABLE:
343 349 case AD_SUSPEND_TO_DISK: /* AD_COMPRESS */
344 350 case AD_SUSPEND_TO_RAM:
345 351 case AD_FORCE:
346 352 /* suspend the system, change audit files */
347 353 return (change_audit_file());
348 354 default:
349 355 return (0); /* not an audit error */
350 356 }
351 357 default:
352 358 return (0); /* not an audit error */
353 359 }
354 360 }
355 361
356 362 static int
357 363 turnoff_auditd(void)
358 364 {
359 365 int rc;
360 366 int retries = RETRY_COUNT;
361 367
362 368 if ((rc = (int)fork()) == 0) {
363 369 (void) execl("/usr/sbin/audit", "audit", "-T", NULL);
364 370 (void) fprintf(stderr, "error disabling auditd: %s\n",
365 371 strerror(errno));
366 372 _exit(-1);
367 373 } else if (rc == -1) {
368 374 (void) fprintf(stderr, "error disabling auditd: %s\n",
369 375 strerror(errno));
370 376 return (-1);
371 377 }
372 378
373 379 /*
374 380 * wait for auditd to finish its work. auditd will change the
375 381 * auditstart from AUC_AUDITING (auditd up and running) to
376 382 * AUC_NOAUDIT. Other states are errors, so we're done as well.
377 383 */
378 384 do {
379 385 int auditstate;
380 386
381 387 rc = -1;
382 388 if ((auditon(A_GETCOND, (caddr_t)&auditstate,
383 389 sizeof (auditstate)) == 0) &&
384 390 (auditstate == AUC_AUDITING)) {
385 391 retries--;
386 392 (void) sleep(1);
387 393 } else {
388 394 rc = 0;
389 395 }
390 396 } while ((rc != 0) && (retries != 0));
391 397
392 398 return (rc);
393 399 }
394 400
395 401 static int
396 402 change_audit_file(void)
397 403 {
398 404 pid_t pid;
399 405
400 406 if ((pid = fork()) == 0) {
401 407 (void) execl("/usr/sbin/audit", "audit", "-n", NULL);
402 408 (void) fprintf(stderr, "error changing audit files: %s\n",
403 409 strerror(errno));
404 410 _exit(-1);
405 411 } else if (pid == -1) {
406 412 (void) fprintf(stderr, "error changing audit files: %s\n",
407 413 strerror(errno));
408 414 return (-1);
409 415 } else {
410 416 pid_t rc;
411 417 int retries = RETRY_COUNT;
412 418
413 419 /*
414 420 * Wait for audit(1M) -n process to complete
415 421 *
416 422 */
417 423 do {
418 424 if ((rc = waitpid(pid, NULL, WNOHANG)) == pid) {
419 425 return (0);
420 426 } else if (rc == -1) {
421 427 return (-1);
422 428 } else {
423 429 (void) sleep(1);
424 430 retries--;
425 431 }
426 432
427 433 } while (retries != 0);
428 434 }
429 435 return (-1);
430 436 }
431 437
432 438 static void
433 439 wait_for_auqueue()
434 440 {
435 441 au_stat_t au_stat;
436 442 int retries = 10;
437 443
438 444 while (retries-- && auditon(A_GETSTAT, (caddr_t)&au_stat, NULL) == 0) {
439 445 if (au_stat.as_enqueue == au_stat.as_written) {
440 446 break;
441 447 }
442 448 (void) sleep(1);
443 449 }
444 450 }
↓ open down ↓ |
180 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX