secmodel_securelevel.c revision 1.17 1 /* $NetBSD: secmodel_securelevel.c,v 1.17 2009/10/06 04:28:10 elad Exp $ */
2 /*-
3 * Copyright (c) 2006 Elad Efrat <elad (at) NetBSD.org>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 /*
30 * This file contains kauth(9) listeners needed to implement the traditional
31 * NetBSD securelevel.
32 *
33 * The securelevel is a system-global indication on what operations are
34 * allowed or not. It affects all users, including root.
35 */
36
37 #include <sys/cdefs.h>
38 __KERNEL_RCSID(0, "$NetBSD: secmodel_securelevel.c,v 1.17 2009/10/06 04:28:10 elad Exp $");
39
40 #ifdef _KERNEL_OPT
41 #include "opt_insecure.h"
42 #endif /* _KERNEL_OPT */
43
44 #include <sys/types.h>
45 #include <sys/param.h>
46 #include <sys/kauth.h>
47
48 #include <sys/conf.h>
49 #include <sys/mount.h>
50 #include <sys/sysctl.h>
51 #include <sys/vnode.h>
52 #include <sys/module.h>
53 #include <sys/timevar.h>
54
55 #include <miscfs/specfs/specdev.h>
56
57 #include <secmodel/securelevel/securelevel.h>
58
59 MODULE(MODULE_CLASS_SECMODEL, securelevel, NULL);
60
61 static int securelevel;
62
63 static kauth_listener_t l_system, l_process, l_network, l_machdep, l_device,
64 l_vnode;
65
66 static struct sysctllog *securelevel_sysctl_log;
67
68 /*
69 * sysctl helper routine for securelevel. ensures that the value
70 * only rises unless the caller has pid 1 (assumed to be init).
71 */
72 int
73 secmodel_securelevel_sysctl(SYSCTLFN_ARGS)
74 {
75 int newsecurelevel, error;
76 struct sysctlnode node;
77
78 newsecurelevel = securelevel;
79 node = *rnode;
80 node.sysctl_data = &newsecurelevel;
81 error = sysctl_lookup(SYSCTLFN_CALL(&node));
82 if (error || newp == NULL)
83 return (error);
84
85 if (newsecurelevel < securelevel && l && l->l_proc->p_pid != 1)
86 return (EPERM);
87
88 securelevel = newsecurelevel;
89
90 return (error);
91 }
92
93 void
94 sysctl_security_securelevel_setup(struct sysctllog **clog)
95 {
96 const struct sysctlnode *rnode;
97
98 sysctl_createv(clog, 0, NULL, &rnode,
99 CTLFLAG_PERMANENT,
100 CTLTYPE_NODE, "security", NULL,
101 NULL, 0, NULL, 0,
102 CTL_SECURITY, CTL_EOL);
103
104 sysctl_createv(clog, 0, &rnode, &rnode,
105 CTLFLAG_PERMANENT,
106 CTLTYPE_NODE, "models", NULL,
107 NULL, 0, NULL, 0,
108 CTL_CREATE, CTL_EOL);
109
110 sysctl_createv(clog, 0, &rnode, &rnode,
111 CTLFLAG_PERMANENT,
112 CTLTYPE_NODE, "securelevel", NULL,
113 NULL, 0, NULL, 0,
114 CTL_CREATE, CTL_EOL);
115
116 sysctl_createv(clog, 0, &rnode, NULL,
117 CTLFLAG_PERMANENT,
118 CTLTYPE_STRING, "name", NULL,
119 NULL, 0, __UNCONST("Traditional NetBSD: Securelevel"), 0,
120 CTL_CREATE, CTL_EOL);
121
122 sysctl_createv(clog, 0, &rnode, NULL,
123 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
124 CTLTYPE_INT, "securelevel",
125 SYSCTL_DESCR("System security level"),
126 secmodel_securelevel_sysctl, 0, NULL, 0,
127 CTL_CREATE, CTL_EOL);
128
129 /* Compatibility: kern.securelevel */
130 sysctl_createv(clog, 0, NULL, NULL,
131 CTLFLAG_PERMANENT,
132 CTLTYPE_NODE, "kern", NULL,
133 NULL, 0, NULL, 0,
134 CTL_KERN, CTL_EOL);
135
136 sysctl_createv(clog, 0, NULL, NULL,
137 CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
138 CTLTYPE_INT, "securelevel",
139 SYSCTL_DESCR("System security level"),
140 secmodel_securelevel_sysctl, 0, NULL, 0,
141 CTL_KERN, KERN_SECURELVL, CTL_EOL);
142 }
143
144 void
145 secmodel_securelevel_init(void)
146 {
147 #ifdef INSECURE
148 securelevel = -1;
149 #else
150 securelevel = 0;
151 #endif /* INSECURE */
152 }
153
154 void
155 secmodel_securelevel_start(void)
156 {
157 l_system = kauth_listen_scope(KAUTH_SCOPE_SYSTEM,
158 secmodel_securelevel_system_cb, NULL);
159 l_process = kauth_listen_scope(KAUTH_SCOPE_PROCESS,
160 secmodel_securelevel_process_cb, NULL);
161 l_network = kauth_listen_scope(KAUTH_SCOPE_NETWORK,
162 secmodel_securelevel_network_cb, NULL);
163 l_machdep = kauth_listen_scope(KAUTH_SCOPE_MACHDEP,
164 secmodel_securelevel_machdep_cb, NULL);
165 l_device = kauth_listen_scope(KAUTH_SCOPE_DEVICE,
166 secmodel_securelevel_device_cb, NULL);
167 l_vnode = kauth_listen_scope(KAUTH_SCOPE_VNODE,
168 secmodel_securelevel_vnode_cb, NULL);
169 }
170
171 void
172 secmodel_securelevel_stop(void)
173 {
174 kauth_unlisten_scope(l_system);
175 kauth_unlisten_scope(l_process);
176 kauth_unlisten_scope(l_network);
177 kauth_unlisten_scope(l_machdep);
178 kauth_unlisten_scope(l_device);
179 kauth_unlisten_scope(l_vnode);
180 }
181
182 static int
183 securelevel_modcmd(modcmd_t cmd, void *arg)
184 {
185 int error = 0;
186
187 switch (cmd) {
188 case MODULE_CMD_INIT:
189 secmodel_securelevel_init();
190 secmodel_securelevel_start();
191 sysctl_security_securelevel_setup(&securelevel_sysctl_log);
192 break;
193
194 case MODULE_CMD_FINI:
195 sysctl_teardown(&securelevel_sysctl_log);
196 secmodel_securelevel_stop();
197 break;
198
199 case MODULE_CMD_AUTOUNLOAD:
200 error = EPERM;
201 break;
202
203 default:
204 error = ENOTTY;
205 break;
206 }
207
208 return (error);
209 }
210
211 /*
212 * kauth(9) listener
213 *
214 * Security model: Traditional NetBSD
215 * Scope: System
216 * Responsibility: Securelevel
217 */
218 int
219 secmodel_securelevel_system_cb(kauth_cred_t cred,
220 kauth_action_t action, void *cookie, void *arg0, void *arg1,
221 void *arg2, void *arg3)
222 {
223 int result;
224 enum kauth_system_req req;
225
226 result = KAUTH_RESULT_DEFER;
227 req = (enum kauth_system_req)arg0;
228
229 switch (action) {
230 case KAUTH_SYSTEM_CHSYSFLAGS:
231 if (securelevel > 0)
232 result = KAUTH_RESULT_DENY;
233 break;
234
235 case KAUTH_SYSTEM_TIME:
236 switch (req) {
237 case KAUTH_REQ_SYSTEM_TIME_RTCOFFSET:
238 if (securelevel > 0)
239 result = KAUTH_RESULT_DENY;
240 break;
241
242 case KAUTH_REQ_SYSTEM_TIME_SYSTEM: {
243 struct timespec *ts = arg1;
244 struct timespec *delta = arg2;
245
246 if (securelevel > 1 && time_wraps(ts, delta))
247 result = KAUTH_RESULT_DENY;
248
249 break;
250 }
251
252 default:
253 break;
254 }
255 break;
256
257 case KAUTH_SYSTEM_MODULE:
258 if (securelevel > 0)
259 result = KAUTH_RESULT_DENY;
260 break;
261
262 case KAUTH_SYSTEM_MOUNT:
263 switch (req) {
264 case KAUTH_REQ_SYSTEM_MOUNT_NEW:
265 if (securelevel > 1)
266 result = KAUTH_RESULT_DENY;
267
268 break;
269
270 case KAUTH_REQ_SYSTEM_MOUNT_UPDATE:
271 if (securelevel > 1) {
272 struct mount *mp = arg1;
273 u_long flags = (u_long)arg2;
274
275 /* Can only degrade from read/write to read-only. */
276 if (flags != (mp->mnt_flag | MNT_RDONLY | MNT_RELOAD |
277 MNT_FORCE | MNT_UPDATE))
278 result = KAUTH_RESULT_DENY;
279 }
280
281 break;
282
283 default:
284 break;
285 }
286
287 break;
288
289 case KAUTH_SYSTEM_SYSCTL:
290 switch (req) {
291 case KAUTH_REQ_SYSTEM_SYSCTL_ADD:
292 case KAUTH_REQ_SYSTEM_SYSCTL_DELETE:
293 case KAUTH_REQ_SYSTEM_SYSCTL_DESC:
294 if (securelevel > 0)
295 result = KAUTH_RESULT_DENY;
296 break;
297
298 default:
299 break;
300 }
301 break;
302
303 case KAUTH_SYSTEM_SETIDCORE:
304 if (securelevel > 0)
305 result = KAUTH_RESULT_DENY;
306 break;
307
308 case KAUTH_SYSTEM_DEBUG:
309 switch (req) {
310 case KAUTH_REQ_SYSTEM_DEBUG_IPKDB:
311 if (securelevel > 0)
312 result = KAUTH_RESULT_DENY;
313 break;
314
315 default:
316 break;
317 }
318 break;
319
320 default:
321 break;
322 }
323
324 return (result);
325 }
326
327 /*
328 * kauth(9) listener
329 *
330 * Security model: Traditional NetBSD
331 * Scope: Process
332 * Responsibility: Securelevel
333 */
334 int
335 secmodel_securelevel_process_cb(kauth_cred_t cred,
336 kauth_action_t action, void *cookie, void *arg0,
337 void *arg1, void *arg2, void *arg3)
338 {
339 struct proc *p;
340 int result;
341
342 result = KAUTH_RESULT_DEFER;
343 p = arg0;
344
345 switch (action) {
346 case KAUTH_PROCESS_PROCFS: {
347 enum kauth_process_req req;
348
349 req = (enum kauth_process_req)arg2;
350 switch (req) {
351 case KAUTH_REQ_PROCESS_PROCFS_READ:
352 break;
353
354 case KAUTH_REQ_PROCESS_PROCFS_RW:
355 case KAUTH_REQ_PROCESS_PROCFS_WRITE:
356 if ((p == initproc) && (securelevel > -1))
357 result = KAUTH_RESULT_DENY;
358
359 break;
360
361 default:
362 break;
363 }
364
365 break;
366 }
367
368 case KAUTH_PROCESS_PTRACE:
369 if ((p == initproc) && (securelevel >= 0))
370 result = KAUTH_RESULT_DENY;
371
372 break;
373
374 case KAUTH_PROCESS_CORENAME:
375 if (securelevel > 1)
376 result = KAUTH_RESULT_DENY;
377 break;
378
379 default:
380 break;
381 }
382
383 return (result);
384 }
385
386 /*
387 * kauth(9) listener
388 *
389 * Security model: Traditional NetBSD
390 * Scope: Network
391 * Responsibility: Securelevel
392 */
393 int
394 secmodel_securelevel_network_cb(kauth_cred_t cred,
395 kauth_action_t action, void *cookie, void *arg0,
396 void *arg1, void *arg2, void *arg3)
397 {
398 int result;
399 enum kauth_network_req req;
400
401 result = KAUTH_RESULT_DEFER;
402 req = (enum kauth_network_req)arg0;
403
404 switch (action) {
405 case KAUTH_NETWORK_FIREWALL:
406 switch (req) {
407 case KAUTH_REQ_NETWORK_FIREWALL_FW:
408 case KAUTH_REQ_NETWORK_FIREWALL_NAT:
409 if (securelevel > 1)
410 result = KAUTH_RESULT_DENY;
411 break;
412
413 default:
414 break;
415 }
416 break;
417
418 case KAUTH_NETWORK_FORWSRCRT:
419 if (securelevel > 0)
420 result = KAUTH_RESULT_DENY;
421 break;
422
423 default:
424 break;
425 }
426
427 return (result);
428 }
429
430 /*
431 * kauth(9) listener
432 *
433 * Security model: Traditional NetBSD
434 * Scope: Machdep
435 * Responsibility: Securelevel
436 */
437 int
438 secmodel_securelevel_machdep_cb(kauth_cred_t cred,
439 kauth_action_t action, void *cookie, void *arg0,
440 void *arg1, void *arg2, void *arg3)
441 {
442 int result;
443
444 result = KAUTH_RESULT_DEFER;
445
446 switch (action) {
447 case KAUTH_MACHDEP_IOPERM_SET:
448 case KAUTH_MACHDEP_IOPL:
449 if (securelevel > 0)
450 result = KAUTH_RESULT_DENY;
451 break;
452
453 case KAUTH_MACHDEP_UNMANAGEDMEM:
454 if (securelevel > 0)
455 result = KAUTH_RESULT_DENY;
456 break;
457
458 default:
459 break;
460 }
461
462 return (result);
463 }
464
465 /*
466 * kauth(9) listener
467 *
468 * Security model: Traditional NetBSD
469 * Scope: Device
470 * Responsibility: Securelevel
471 */
472 int
473 secmodel_securelevel_device_cb(kauth_cred_t cred,
474 kauth_action_t action, void *cookie, void *arg0,
475 void *arg1, void *arg2, void *arg3)
476 {
477 int result;
478
479 result = KAUTH_RESULT_DEFER;
480
481 switch (action) {
482 case KAUTH_DEVICE_RAWIO_SPEC: {
483 struct vnode *vp;
484 enum kauth_device_req req;
485
486 req = (enum kauth_device_req)arg0;
487 vp = arg1;
488
489 KASSERT(vp != NULL);
490
491 /* Handle /dev/mem and /dev/kmem. */
492 if (iskmemvp(vp)) {
493 switch (req) {
494 case KAUTH_REQ_DEVICE_RAWIO_SPEC_READ:
495 break;
496
497 case KAUTH_REQ_DEVICE_RAWIO_SPEC_WRITE:
498 case KAUTH_REQ_DEVICE_RAWIO_SPEC_RW:
499 if (securelevel > 0)
500 result = KAUTH_RESULT_DENY;
501
502 break;
503
504 default:
505 break;
506 }
507
508 break;
509 }
510
511 switch (req) {
512 case KAUTH_REQ_DEVICE_RAWIO_SPEC_READ:
513 break;
514
515 case KAUTH_REQ_DEVICE_RAWIO_SPEC_WRITE:
516 case KAUTH_REQ_DEVICE_RAWIO_SPEC_RW: {
517 int error;
518
519 error = rawdev_mounted(vp, NULL);
520
521 /* Not a disk. */
522 if (error == EINVAL)
523 break;
524
525 if (error && securelevel > 0)
526 result = KAUTH_RESULT_DENY;
527
528 if (securelevel > 1)
529 result = KAUTH_RESULT_DENY;
530
531 break;
532 }
533
534 default:
535 break;
536 }
537
538 break;
539 }
540
541 case KAUTH_DEVICE_RAWIO_PASSTHRU:
542 if (securelevel > 0) {
543 u_long bits;
544
545 bits = (u_long)arg0;
546
547 KASSERT(bits != 0);
548 KASSERT((bits & ~KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_ALL) == 0);
549
550 if (bits & ~KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_READCONF)
551 result = KAUTH_RESULT_DENY;
552 }
553
554 break;
555
556 case KAUTH_DEVICE_GPIO_PINSET:
557 if (securelevel > 0)
558 result = KAUTH_RESULT_DENY;
559 break;
560
561 default:
562 break;
563 }
564
565 return (result);
566 }
567
568 int
569 secmodel_securelevel_vnode_cb(kauth_cred_t cred, kauth_action_t action,
570 void *cookie, void *arg0, void *arg1, void *arg2, void *arg3)
571 {
572 int result;
573
574 result = KAUTH_RESULT_DEFER;
575
576 if ((action & KAUTH_VNODE_WRITE_SYSFLAGS) &&
577 (action & KAUTH_VNODE_HAS_SYSFLAGS)) {
578 if (securelevel > 0)
579 result = KAUTH_RESULT_DENY;
580 }
581
582 return (result);
583 }
584
585