aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorSteve Grubb <sgrubb redhat com>2007-01-19 14:39:55 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2007-02-17 21:30:12 -0500
commit6a01b07fae482f9b34491b317056c89d3b96ca2e (patch)
treeb3e80a8147101db29dcc18596ea20b1fcbeef6ad /kernel
parenta17b4ad778e1857944f5a1df95fb7758cd5cc58d (diff)
[PATCH] audit config lockdown
The following patch adds a new mode to the audit system. It uses the audit_enabled config option to introduce the idea of audit enabled, but configuration is immutable. Any attempt to change the configuration while in this mode is audited. To change the audit rules, you'd need to reboot the machine. To use this option, you'd need a modified version of auditctl and use "-e 2". This is intended to go at the end of the audit.rules file for people that want an immutable configuration. This patch also adds "res=" to a number of configuration commands that did not have it before. Signed-off-by: Steve Grubb <sgrubb@redhat.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/audit.c216
1 files changed, 157 insertions, 59 deletions
diff --git a/kernel/audit.c b/kernel/audit.c
index d9b690ac684b..76c9a11b72d6 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -2,7 +2,7 @@
2 * Gateway between the kernel (e.g., selinux) and the user-space audit daemon. 2 * Gateway between the kernel (e.g., selinux) and the user-space audit daemon.
3 * System-call specific features have moved to auditsc.c 3 * System-call specific features have moved to auditsc.c
4 * 4 *
5 * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina. 5 * Copyright 2003-2007 Red Hat Inc., Durham, North Carolina.
6 * All Rights Reserved. 6 * All Rights Reserved.
7 * 7 *
8 * This program is free software; you can redistribute it and/or modify 8 * This program is free software; you can redistribute it and/or modify
@@ -65,7 +65,9 @@
65 * (Initialization happens after skb_init is called.) */ 65 * (Initialization happens after skb_init is called.) */
66static int audit_initialized; 66static int audit_initialized;
67 67
68/* No syscall auditing will take place unless audit_enabled != 0. */ 68/* 0 - no auditing
69 * 1 - auditing enabled
70 * 2 - auditing enabled and configuration is locked/unchangeable. */
69int audit_enabled; 71int audit_enabled;
70 72
71/* Default state when kernel boots without any parameters. */ 73/* Default state when kernel boots without any parameters. */
@@ -239,102 +241,150 @@ void audit_log_lost(const char *message)
239 241
240static int audit_set_rate_limit(int limit, uid_t loginuid, u32 sid) 242static int audit_set_rate_limit(int limit, uid_t loginuid, u32 sid)
241{ 243{
242 int old = audit_rate_limit; 244 int res, rc = 0, old = audit_rate_limit;
245
246 /* check if we are locked */
247 if (audit_enabled == 2)
248 res = 0;
249 else
250 res = 1;
243 251
244 if (sid) { 252 if (sid) {
245 char *ctx = NULL; 253 char *ctx = NULL;
246 u32 len; 254 u32 len;
247 int rc; 255 if ((rc = selinux_sid_to_string(sid, &ctx, &len)) == 0) {
248 if ((rc = selinux_sid_to_string(sid, &ctx, &len)))
249 return rc;
250 else
251 audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, 256 audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
252 "audit_rate_limit=%d old=%d by auid=%u subj=%s", 257 "audit_rate_limit=%d old=%d by auid=%u"
253 limit, old, loginuid, ctx); 258 " subj=%s res=%d",
254 kfree(ctx); 259 limit, old, loginuid, ctx, res);
255 } else 260 kfree(ctx);
256 audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, 261 } else
257 "audit_rate_limit=%d old=%d by auid=%u", 262 res = 0; /* Something weird, deny request */
258 limit, old, loginuid); 263 }
259 audit_rate_limit = limit; 264 audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
260 return 0; 265 "audit_rate_limit=%d old=%d by auid=%u res=%d",
266 limit, old, loginuid, res);
267
268 /* If we are allowed, make the change */
269 if (res == 1)
270 audit_rate_limit = limit;
271 /* Not allowed, update reason */
272 else if (rc == 0)
273 rc = -EPERM;
274 return rc;
261} 275}
262 276
263static int audit_set_backlog_limit(int limit, uid_t loginuid, u32 sid) 277static int audit_set_backlog_limit(int limit, uid_t loginuid, u32 sid)
264{ 278{
265 int old = audit_backlog_limit; 279 int res, rc = 0, old = audit_backlog_limit;
280
281 /* check if we are locked */
282 if (audit_enabled == 2)
283 res = 0;
284 else
285 res = 1;
266 286
267 if (sid) { 287 if (sid) {
268 char *ctx = NULL; 288 char *ctx = NULL;
269 u32 len; 289 u32 len;
270 int rc; 290 if ((rc = selinux_sid_to_string(sid, &ctx, &len)) == 0) {
271 if ((rc = selinux_sid_to_string(sid, &ctx, &len)))
272 return rc;
273 else
274 audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, 291 audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
275 "audit_backlog_limit=%d old=%d by auid=%u subj=%s", 292 "audit_backlog_limit=%d old=%d by auid=%u"
276 limit, old, loginuid, ctx); 293 " subj=%s res=%d",
277 kfree(ctx); 294 limit, old, loginuid, ctx, res);
278 } else 295 kfree(ctx);
279 audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, 296 } else
280 "audit_backlog_limit=%d old=%d by auid=%u", 297 res = 0; /* Something weird, deny request */
281 limit, old, loginuid); 298 }
282 audit_backlog_limit = limit; 299 audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
283 return 0; 300 "audit_backlog_limit=%d old=%d by auid=%u res=%d",
301 limit, old, loginuid, res);
302
303 /* If we are allowed, make the change */
304 if (res == 1)
305 audit_backlog_limit = limit;
306 /* Not allowed, update reason */
307 else if (rc == 0)
308 rc = -EPERM;
309 return rc;
284} 310}
285 311
286static int audit_set_enabled(int state, uid_t loginuid, u32 sid) 312static int audit_set_enabled(int state, uid_t loginuid, u32 sid)
287{ 313{
288 int old = audit_enabled; 314 int res, rc = 0, old = audit_enabled;
289 315
290 if (state != 0 && state != 1) 316 if (state < 0 || state > 2)
291 return -EINVAL; 317 return -EINVAL;
292 318
319 /* check if we are locked */
320 if (audit_enabled == 2)
321 res = 0;
322 else
323 res = 1;
324
293 if (sid) { 325 if (sid) {
294 char *ctx = NULL; 326 char *ctx = NULL;
295 u32 len; 327 u32 len;
296 int rc; 328 if ((rc = selinux_sid_to_string(sid, &ctx, &len)) == 0) {
297 if ((rc = selinux_sid_to_string(sid, &ctx, &len)))
298 return rc;
299 else
300 audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, 329 audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
301 "audit_enabled=%d old=%d by auid=%u subj=%s", 330 "audit_enabled=%d old=%d by auid=%u"
302 state, old, loginuid, ctx); 331 " subj=%s res=%d",
303 kfree(ctx); 332 state, old, loginuid, ctx, res);
304 } else 333 kfree(ctx);
305 audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, 334 } else
306 "audit_enabled=%d old=%d by auid=%u", 335 res = 0; /* Something weird, deny request */
307 state, old, loginuid); 336 }
308 audit_enabled = state; 337 audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
309 return 0; 338 "audit_enabled=%d old=%d by auid=%u res=%d",
339 state, old, loginuid, res);
340
341 /* If we are allowed, make the change */
342 if (res == 1)
343 audit_enabled = state;
344 /* Not allowed, update reason */
345 else if (rc == 0)
346 rc = -EPERM;
347 return rc;
310} 348}
311 349
312static int audit_set_failure(int state, uid_t loginuid, u32 sid) 350static int audit_set_failure(int state, uid_t loginuid, u32 sid)
313{ 351{
314 int old = audit_failure; 352 int res, rc = 0, old = audit_failure;
315 353
316 if (state != AUDIT_FAIL_SILENT 354 if (state != AUDIT_FAIL_SILENT
317 && state != AUDIT_FAIL_PRINTK 355 && state != AUDIT_FAIL_PRINTK
318 && state != AUDIT_FAIL_PANIC) 356 && state != AUDIT_FAIL_PANIC)
319 return -EINVAL; 357 return -EINVAL;
320 358
359 /* check if we are locked */
360 if (audit_enabled == 2)
361 res = 0;
362 else
363 res = 1;
364
321 if (sid) { 365 if (sid) {
322 char *ctx = NULL; 366 char *ctx = NULL;
323 u32 len; 367 u32 len;
324 int rc; 368 if ((rc = selinux_sid_to_string(sid, &ctx, &len)) == 0) {
325 if ((rc = selinux_sid_to_string(sid, &ctx, &len)))
326 return rc;
327 else
328 audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, 369 audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
329 "audit_failure=%d old=%d by auid=%u subj=%s", 370 "audit_failure=%d old=%d by auid=%u"
330 state, old, loginuid, ctx); 371 " subj=%s res=%d",
331 kfree(ctx); 372 state, old, loginuid, ctx, res);
332 } else 373 kfree(ctx);
333 audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, 374 } else
334 "audit_failure=%d old=%d by auid=%u", 375 res = 0; /* Something weird, deny request */
335 state, old, loginuid); 376 }
336 audit_failure = state; 377 audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
337 return 0; 378 "audit_failure=%d old=%d by auid=%u res=%d",
379 state, old, loginuid, res);
380
381 /* If we are allowed, make the change */
382 if (res == 1)
383 audit_failure = state;
384 /* Not allowed, update reason */
385 else if (rc == 0)
386 rc = -EPERM;
387 return rc;
338} 388}
339 389
340static int kauditd_thread(void *dummy) 390static int kauditd_thread(void *dummy)
@@ -599,6 +649,30 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
599 case AUDIT_DEL: 649 case AUDIT_DEL:
600 if (nlmsg_len(nlh) < sizeof(struct audit_rule)) 650 if (nlmsg_len(nlh) < sizeof(struct audit_rule))
601 return -EINVAL; 651 return -EINVAL;
652 if (audit_enabled == 2) {
653 ab = audit_log_start(NULL, GFP_KERNEL,
654 AUDIT_CONFIG_CHANGE);
655 if (ab) {
656 audit_log_format(ab,
657 "pid=%d uid=%u auid=%u",
658 pid, uid, loginuid);
659 if (sid) {
660 if (selinux_sid_to_string(
661 sid, &ctx, &len)) {
662 audit_log_format(ab,
663 " ssid=%u", sid);
664 /* Maybe call audit_panic? */
665 } else
666 audit_log_format(ab,
667 " subj=%s", ctx);
668 kfree(ctx);
669 }
670 audit_log_format(ab, " audit_enabled=%d res=0",
671 audit_enabled);
672 audit_log_end(ab);
673 }
674 return -EPERM;
675 }
602 /* fallthrough */ 676 /* fallthrough */
603 case AUDIT_LIST: 677 case AUDIT_LIST:
604 err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid, 678 err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid,
@@ -609,6 +683,30 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
609 case AUDIT_DEL_RULE: 683 case AUDIT_DEL_RULE:
610 if (nlmsg_len(nlh) < sizeof(struct audit_rule_data)) 684 if (nlmsg_len(nlh) < sizeof(struct audit_rule_data))
611 return -EINVAL; 685 return -EINVAL;
686 if (audit_enabled == 2) {
687 ab = audit_log_start(NULL, GFP_KERNEL,
688 AUDIT_CONFIG_CHANGE);
689 if (ab) {
690 audit_log_format(ab,
691 "pid=%d uid=%u auid=%u",
692 pid, uid, loginuid);
693 if (sid) {
694 if (selinux_sid_to_string(
695 sid, &ctx, &len)) {
696 audit_log_format(ab,
697 " ssid=%u", sid);
698 /* Maybe call audit_panic? */
699 } else
700 audit_log_format(ab,
701 " subj=%s", ctx);
702 kfree(ctx);
703 }
704 audit_log_format(ab, " audit_enabled=%d res=0",
705 audit_enabled);
706 audit_log_end(ab);
707 }
708 return -EPERM;
709 }
612 /* fallthrough */ 710 /* fallthrough */
613 case AUDIT_LIST_RULES: 711 case AUDIT_LIST_RULES:
614 err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid, 712 err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid,