* [PATCH] audit config lockdown
@ 2007-01-19 19:39 Steve Grubb
2007-01-19 19:48 ` Casey Schaufler
2007-01-27 8:13 ` Steve Beattie
0 siblings, 2 replies; 4+ messages in thread
From: Steve Grubb @ 2007-01-19 19:39 UTC (permalink / raw)
To: Linux Audit
Hi,
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>
diff -urp linux-2.6.18.x86_64.orig/kernel/audit.c linux-2.6.18.x86_64/kernel/audit.c
--- linux-2.6.18.x86_64.orig/kernel/audit.c 2007-01-19 13:17:56.000000000 -0500
+++ linux-2.6.18.x86_64/kernel/audit.c 2007-01-19 13:18:50.000000000 -0500
@@ -2,7 +2,7 @@
* Gateway between the kernel (e.g., selinux) and the user-space audit daemon.
* System-call specific features have moved to auditsc.c
*
- * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina.
+ * Copyright 2003-2007 Red Hat Inc., Durham, North Carolina.
* All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify
@@ -64,7 +64,9 @@
* (Initialization happens after skb_init is called.) */
static int audit_initialized;
-/* No syscall auditing will take place unless audit_enabled != 0. */
+/* 0 - no auditing
+ * 1 - auditing enabled
+ * 2 - auditing enabled and configuration is locked/unchangeable. */
int audit_enabled;
/* Default state when kernel boots without any parameters. */
@@ -238,102 +240,150 @@ void audit_log_lost(const char *message)
static int audit_set_rate_limit(int limit, uid_t loginuid, u32 sid)
{
- int old = audit_rate_limit;
+ int res, rc = 0, old = audit_rate_limit;
+
+ /* check if we are locked */
+ if (audit_enabled == 2)
+ res = 0;
+ else
+ res = 1;
if (sid) {
char *ctx = NULL;
u32 len;
- int rc;
- if ((rc = selinux_ctxid_to_string(sid, &ctx, &len)))
- return rc;
- else
+ if ((rc = selinux_ctxid_to_string(sid, &ctx, &len)) == 0) {
audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
- "audit_rate_limit=%d old=%d by auid=%u subj=%s",
- limit, old, loginuid, ctx);
- kfree(ctx);
- } else
- audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
- "audit_rate_limit=%d old=%d by auid=%u",
- limit, old, loginuid);
- audit_rate_limit = limit;
- return 0;
+ "audit_rate_limit=%d old=%d by auid=%u"
+ " subj=%s res=%d",
+ limit, old, loginuid, ctx, res);
+ kfree(ctx);
+ } else
+ res = 0; /* Something weird, deny request */
+ }
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ "audit_rate_limit=%d old=%d by auid=%u res=%d",
+ limit, old, loginuid, res);
+
+ /* If we are allowed, make the change */
+ if (res == 1)
+ audit_rate_limit = limit;
+ /* Not allowed, update reason */
+ else if (rc == 0)
+ rc = -EPERM;
+ return rc;
}
static int audit_set_backlog_limit(int limit, uid_t loginuid, u32 sid)
{
- int old = audit_backlog_limit;
+ int res, rc = 0, old = audit_backlog_limit;
+
+ /* check if we are locked */
+ if (audit_enabled == 2)
+ res = 0;
+ else
+ res = 1;
if (sid) {
char *ctx = NULL;
u32 len;
- int rc;
- if ((rc = selinux_ctxid_to_string(sid, &ctx, &len)))
- return rc;
- else
+ if ((rc = selinux_ctxid_to_string(sid, &ctx, &len)) == 0) {
audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
- "audit_backlog_limit=%d old=%d by auid=%u subj=%s",
- limit, old, loginuid, ctx);
- kfree(ctx);
- } else
- audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
- "audit_backlog_limit=%d old=%d by auid=%u",
- limit, old, loginuid);
- audit_backlog_limit = limit;
- return 0;
+ "audit_backlog_limit=%d old=%d by auid=%u"
+ " subj=%s res=%d",
+ limit, old, loginuid, ctx, res);
+ kfree(ctx);
+ } else
+ res = 0; /* Something weird, deny request */
+ }
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ "audit_backlog_limit=%d old=%d by auid=%u res=%d",
+ limit, old, loginuid, res);
+
+ /* If we are allowed, make the change */
+ if (res == 1)
+ audit_backlog_limit = limit;
+ /* Not allowed, update reason */
+ else if (rc == 0)
+ rc = -EPERM;
+ return rc;
}
static int audit_set_enabled(int state, uid_t loginuid, u32 sid)
{
- int old = audit_enabled;
+ int res, rc = 0, old = audit_enabled;
- if (state != 0 && state != 1)
+ if (state < 0 || state > 2)
return -EINVAL;
+ /* check if we are locked */
+ if (audit_enabled == 2)
+ res = 0;
+ else
+ res = 1;
+
if (sid) {
char *ctx = NULL;
u32 len;
- int rc;
- if ((rc = selinux_ctxid_to_string(sid, &ctx, &len)))
- return rc;
- else
+ if ((rc = selinux_ctxid_to_string(sid, &ctx, &len)) == 0) {
audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
- "audit_enabled=%d old=%d by auid=%u subj=%s",
- state, old, loginuid, ctx);
- kfree(ctx);
- } else
- audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
- "audit_enabled=%d old=%d by auid=%u",
- state, old, loginuid);
- audit_enabled = state;
- return 0;
+ "audit_enabled=%d old=%d by auid=%u"
+ " subj=%s res=%d",
+ state, old, loginuid, ctx, res);
+ kfree(ctx);
+ } else
+ res = 0; /* Something weird, deny request */
+ }
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ "audit_enabled=%d old=%d by auid=%u res=%d",
+ state, old, loginuid, res);
+
+ /* If we are allowed, make the change */
+ if (res == 1)
+ audit_enabled = state;
+ /* Not allowed, update reason */
+ else if (rc == 0)
+ rc = -EPERM;
+ return rc;
}
static int audit_set_failure(int state, uid_t loginuid, u32 sid)
{
- int old = audit_failure;
+ int res, rc = 0, old = audit_failure;
if (state != AUDIT_FAIL_SILENT
&& state != AUDIT_FAIL_PRINTK
&& state != AUDIT_FAIL_PANIC)
return -EINVAL;
+ /* check if we are locked */
+ if (audit_enabled == 2)
+ res = 0;
+ else
+ res = 1;
+
if (sid) {
char *ctx = NULL;
u32 len;
- int rc;
- if ((rc = selinux_ctxid_to_string(sid, &ctx, &len)))
- return rc;
- else
+ if ((rc = selinux_ctxid_to_string(sid, &ctx, &len)) == 0) {
audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
- "audit_failure=%d old=%d by auid=%u subj=%s",
- state, old, loginuid, ctx);
- kfree(ctx);
- } else
- audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
- "audit_failure=%d old=%d by auid=%u",
- state, old, loginuid);
- audit_failure = state;
- return 0;
+ "audit_failure=%d old=%d by auid=%u"
+ " subj=%s res=%d",
+ state, old, loginuid, ctx, res);
+ kfree(ctx);
+ } else
+ res = 0; /* Something weird, deny request */
+ }
+ audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
+ "audit_failure=%d old=%d by auid=%u res=%d",
+ state, old, loginuid, res);
+
+ /* If we are allowed, make the change */
+ if (res == 1)
+ audit_failure = state;
+ /* Not allowed, update reason */
+ else if (rc == 0)
+ rc = -EPERM;
+ return rc;
}
static int kauditd_thread(void *dummy)
@@ -597,6 +647,30 @@ static int audit_receive_msg(struct sk_b
case AUDIT_DEL:
if (nlmsg_len(nlh) < sizeof(struct audit_rule))
return -EINVAL;
+ if (audit_enabled == 2) {
+ ab = audit_log_start(NULL, GFP_KERNEL,
+ AUDIT_CONFIG_CHANGE);
+ if (ab) {
+ audit_log_format(ab,
+ "pid=%d uid=%u auid=%u",
+ pid, uid, loginuid);
+ if (sid) {
+ if (selinux_ctxid_to_string(
+ sid, &ctx, &len)) {
+ audit_log_format(ab,
+ " ssid=%u", sid);
+ /* Maybe call audit_panic? */
+ } else
+ audit_log_format(ab,
+ " subj=%s", ctx);
+ kfree(ctx);
+ }
+ audit_log_format(ab, " audit_enabled=%d res=0",
+ audit_enabled);
+ audit_log_end(ab);
+ }
+ return -EPERM;
+ }
/* fallthrough */
case AUDIT_LIST:
err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid,
@@ -607,6 +681,30 @@ static int audit_receive_msg(struct sk_b
case AUDIT_DEL_RULE:
if (nlmsg_len(nlh) < sizeof(struct audit_rule_data))
return -EINVAL;
+ if (audit_enabled == 2) {
+ ab = audit_log_start(NULL, GFP_KERNEL,
+ AUDIT_CONFIG_CHANGE);
+ if (ab) {
+ audit_log_format(ab,
+ "pid=%d uid=%u auid=%u",
+ pid, uid, loginuid);
+ if (sid) {
+ if (selinux_ctxid_to_string(
+ sid, &ctx, &len)) {
+ audit_log_format(ab,
+ " ssid=%u", sid);
+ /* Maybe call audit_panic? */
+ } else
+ audit_log_format(ab,
+ " subj=%s", ctx);
+ kfree(ctx);
+ }
+ audit_log_format(ab, " audit_enabled=%d res=0",
+ audit_enabled);
+ audit_log_end(ab);
+ }
+ return -EPERM;
+ }
/* fallthrough */
case AUDIT_LIST_RULES:
err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid,
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH] audit config lockdown
2007-01-19 19:39 [PATCH] audit config lockdown Steve Grubb
@ 2007-01-19 19:48 ` Casey Schaufler
2007-01-27 8:13 ` Steve Beattie
1 sibling, 0 replies; 4+ messages in thread
From: Casey Schaufler @ 2007-01-19 19:48 UTC (permalink / raw)
To: Steve Grubb, Linux Audit
--- Steve Grubb <sgrubb@redhat.com> wrote:
> Hi,
>
> 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.
I don't expect it to be popular, but I like it.
Casey Schaufler
casey@schaufler-ca.com
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] audit config lockdown
2007-01-19 19:39 [PATCH] audit config lockdown Steve Grubb
2007-01-19 19:48 ` Casey Schaufler
@ 2007-01-27 8:13 ` Steve Beattie
2007-01-27 13:05 ` Steve Grubb
1 sibling, 1 reply; 4+ messages in thread
From: Steve Beattie @ 2007-01-27 8:13 UTC (permalink / raw)
To: Linux Audit
[-- Attachment #1.1: Type: text/plain, Size: 1196 bytes --]
On Fri, Jan 19, 2007 at 02:39:55PM -0500, Steve Grubb wrote:
> 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.
Seems reasonable to me. Just a couple of comments.
> This patch also adds "res=" to a number of configuration commands that did not
> have it before.
The res= idiom is unfamiliar to me, seems like an is_xxx name
(is_allowed?) would make it clear what the intent is for.
> @@ -64,7 +64,9 @@
> * (Initialization happens after skb_init is called.) */
> static int audit_initialized;
>
> -/* No syscall auditing will take place unless audit_enabled != 0. */
> +/* 0 - no auditing
> + * 1 - auditing enabled
> + * 2 - auditing enabled and configuration is locked/unchangeable. */
> int audit_enabled;
You probably want a #define or enum for these values, rather than
using magic numbers.
Thanks.
--
Steve Beattie
SUSE Labs, Novell Inc.
<sbeattie@suse.de>
http://NxNW.org/~steve/
[-- Attachment #1.2: Type: application/pgp-signature, Size: 189 bytes --]
[-- Attachment #2: Type: text/plain, Size: 0 bytes --]
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] audit config lockdown
2007-01-27 8:13 ` Steve Beattie
@ 2007-01-27 13:05 ` Steve Grubb
0 siblings, 0 replies; 4+ messages in thread
From: Steve Grubb @ 2007-01-27 13:05 UTC (permalink / raw)
To: linux-audit
On Saturday 27 January 2007 03:13, Steve Beattie wrote:
> > This patch also adds "res=" to a number of configuration commands that
> > did not have it before.
>
> The res= idiom is unfamiliar to me, seems like an is_xxx name
> (is_allowed?) would make it clear what the intent is for.
"res" is an abbreviation for results. We have to know the outcome of the
command - was it successful or not.
-Steve
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2007-01-27 13:05 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-01-19 19:39 [PATCH] audit config lockdown Steve Grubb
2007-01-19 19:48 ` Casey Schaufler
2007-01-27 8:13 ` Steve Beattie
2007-01-27 13:05 ` Steve Grubb
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox