Commit 1a6b9f23 authored by Eric Paris's avatar Eric Paris Committed by Al Viro

[AUDIT] make audit=0 really stop audit messages

Some audit messages (namely configuration changes) are still emitted even if
the audit subsystem has been explicitly disabled.  This patch turns those
messages off as well.
Signed-off-by: default avatarEric Paris <eparis@redhat.com>
parent de6bbd1d
...@@ -66,9 +66,9 @@ ...@@ -66,9 +66,9 @@
* (Initialization happens after skb_init is called.) */ * (Initialization happens after skb_init is called.) */
static int audit_initialized; static int audit_initialized;
/* 0 - no auditing #define AUDIT_OFF 0
* 1 - auditing enabled #define AUDIT_ON 1
* 2 - auditing enabled and configuration is locked/unchangeable. */ #define AUDIT_LOCKED 2
int audit_enabled; int audit_enabled;
/* Default state when kernel boots without any parameters. */ /* Default state when kernel boots without any parameters. */
...@@ -240,152 +240,90 @@ void audit_log_lost(const char *message) ...@@ -240,152 +240,90 @@ void audit_log_lost(const char *message)
} }
} }
static int audit_set_rate_limit(int limit, uid_t loginuid, u32 sid) static int audit_log_config_change(char *function_name, int new, int old,
uid_t loginuid, u32 sid, int allow_changes)
{ {
int res, rc = 0, old = audit_rate_limit; struct audit_buffer *ab;
int rc = 0;
/* check if we are locked */
if (audit_enabled == 2)
res = 0;
else
res = 1;
ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
audit_log_format(ab, "%s=%d old=%d by auid=%u", function_name, new,
old, loginuid);
if (sid) { if (sid) {
char *ctx = NULL; char *ctx = NULL;
u32 len; u32 len;
if ((rc = selinux_sid_to_string(sid, &ctx, &len)) == 0) {
audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, rc = selinux_sid_to_string(sid, &ctx, &len);
"audit_rate_limit=%d old=%d by auid=%u" if (rc) {
" subj=%s res=%d", audit_log_format(ab, " sid=%u", sid);
limit, old, loginuid, ctx, res); allow_changes = 0; /* Something weird, deny request */
} else {
audit_log_format(ab, " subj=%s", ctx);
kfree(ctx); kfree(ctx);
} else }
res = 0; /* Something weird, deny request */
} }
audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, audit_log_format(ab, " res=%d", allow_changes);
"audit_rate_limit=%d old=%d by auid=%u res=%d", audit_log_end(ab);
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; return rc;
} }
static int audit_set_backlog_limit(int limit, uid_t loginuid, u32 sid) static int audit_do_config_change(char *function_name, int *to_change,
int new, uid_t loginuid, u32 sid)
{ {
int res, rc = 0, old = audit_backlog_limit; int allow_changes, rc = 0, old = *to_change;
/* check if we are locked */ /* check if we are locked */
if (audit_enabled == 2) if (audit_enabled == AUDIT_LOCKED)
res = 0; allow_changes = 0;
else else
res = 1; allow_changes = 1;
if (sid) { if (audit_enabled != AUDIT_OFF) {
char *ctx = NULL; rc = audit_log_config_change(function_name, new, old,
u32 len; loginuid, sid, allow_changes);
if ((rc = selinux_sid_to_string(sid, &ctx, &len)) == 0) { if (rc)
audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE, allow_changes = 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 we are allowed, make the change */
if (res == 1) if (allow_changes == 1)
audit_backlog_limit = limit; *to_change = new;
/* Not allowed, update reason */ /* Not allowed, update reason */
else if (rc == 0) else if (rc == 0)
rc = -EPERM; rc = -EPERM;
return rc; return rc;
} }
static int audit_set_enabled(int state, uid_t loginuid, u32 sid) static int audit_set_rate_limit(int limit, uid_t loginuid, u32 sid)
{ {
int res, rc = 0, old = audit_enabled; return audit_do_config_change("audit_rate_limit", &audit_rate_limit,
limit, loginuid, sid);
if (state < 0 || state > 2) }
return -EINVAL;
/* check if we are locked */ static int audit_set_backlog_limit(int limit, uid_t loginuid, u32 sid)
if (audit_enabled == 2) {
res = 0; return audit_do_config_change("audit_backlog_limit", &audit_backlog_limit,
else limit, loginuid, sid);
res = 1; }
if (sid) { static int audit_set_enabled(int state, uid_t loginuid, u32 sid)
char *ctx = NULL; {
u32 len; if (state < AUDIT_OFF || state > AUDIT_LOCKED)
if ((rc = selinux_sid_to_string(sid, &ctx, &len)) == 0) { return -EINVAL;
audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
"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 */ return audit_do_config_change("audit_enabled", &audit_enabled, state,
if (res == 1) loginuid, sid);
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) static int audit_set_failure(int state, uid_t loginuid, u32 sid)
{ {
int res, rc = 0, old = audit_failure;
if (state != AUDIT_FAIL_SILENT if (state != AUDIT_FAIL_SILENT
&& state != AUDIT_FAIL_PRINTK && state != AUDIT_FAIL_PRINTK
&& state != AUDIT_FAIL_PANIC) && state != AUDIT_FAIL_PANIC)
return -EINVAL; return -EINVAL;
/* check if we are locked */ return audit_do_config_change("audit_failure", &audit_failure, state,
if (audit_enabled == 2) loginuid, sid);
res = 0;
else
res = 1;
if (sid) {
char *ctx = NULL;
u32 len;
if ((rc = selinux_sid_to_string(sid, &ctx, &len)) == 0) {
audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
"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) static int kauditd_thread(void *dummy)
...@@ -634,23 +572,14 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) ...@@ -634,23 +572,14 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
if (err < 0) return err; if (err < 0) return err;
} }
if (status_get->mask & AUDIT_STATUS_PID) { if (status_get->mask & AUDIT_STATUS_PID) {
int old = audit_pid; int new_pid = status_get->pid;
if (sid) {
if ((err = selinux_sid_to_string( if (audit_enabled != AUDIT_OFF)
sid, &ctx, &len))) audit_log_config_change("audit_pid", new_pid,
return err; audit_pid, loginuid,
else sid, 1);
audit_log(NULL, GFP_KERNEL,
AUDIT_CONFIG_CHANGE, audit_pid = new_pid;
"audit_pid=%d old=%d by auid=%u subj=%s",
status_get->pid, old,
loginuid, ctx);
kfree(ctx);
} else
audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
"audit_pid=%d old=%d by auid=%u",
status_get->pid, old, loginuid);
audit_pid = status_get->pid;
} }
if (status_get->mask & AUDIT_STATUS_RATE_LIMIT) if (status_get->mask & AUDIT_STATUS_RATE_LIMIT)
err = audit_set_rate_limit(status_get->rate_limit, err = audit_set_rate_limit(status_get->rate_limit,
...@@ -709,7 +638,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) ...@@ -709,7 +638,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
case AUDIT_DEL: case AUDIT_DEL:
if (nlmsg_len(nlh) < sizeof(struct audit_rule)) if (nlmsg_len(nlh) < sizeof(struct audit_rule))
return -EINVAL; return -EINVAL;
if (audit_enabled == 2) { if (audit_enabled == AUDIT_LOCKED) {
ab = audit_log_start(NULL, GFP_KERNEL, ab = audit_log_start(NULL, GFP_KERNEL,
AUDIT_CONFIG_CHANGE); AUDIT_CONFIG_CHANGE);
if (ab) { if (ab) {
...@@ -743,7 +672,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh) ...@@ -743,7 +672,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
case AUDIT_DEL_RULE: case AUDIT_DEL_RULE:
if (nlmsg_len(nlh) < sizeof(struct audit_rule_data)) if (nlmsg_len(nlh) < sizeof(struct audit_rule_data))
return -EINVAL; return -EINVAL;
if (audit_enabled == 2) { if (audit_enabled == AUDIT_LOCKED) {
ab = audit_log_start(NULL, GFP_KERNEL, ab = audit_log_start(NULL, GFP_KERNEL,
AUDIT_CONFIG_CHANGE); AUDIT_CONFIG_CHANGE);
if (ab) { if (ab) {
......
...@@ -95,6 +95,8 @@ extern struct inotify_handle *audit_ih; ...@@ -95,6 +95,8 @@ extern struct inotify_handle *audit_ih;
/* Inotify events we care about. */ /* Inotify events we care about. */
#define AUDIT_IN_WATCH IN_MOVE|IN_CREATE|IN_DELETE|IN_DELETE_SELF|IN_MOVE_SELF #define AUDIT_IN_WATCH IN_MOVE|IN_CREATE|IN_DELETE|IN_DELETE_SELF|IN_MOVE_SELF
extern int audit_enabled;
void audit_free_parent(struct inotify_watch *i_watch) void audit_free_parent(struct inotify_watch *i_watch)
{ {
struct audit_parent *parent; struct audit_parent *parent;
...@@ -974,7 +976,6 @@ static void audit_update_watch(struct audit_parent *parent, ...@@ -974,7 +976,6 @@ static void audit_update_watch(struct audit_parent *parent,
struct audit_watch *owatch, *nwatch, *nextw; struct audit_watch *owatch, *nwatch, *nextw;
struct audit_krule *r, *nextr; struct audit_krule *r, *nextr;
struct audit_entry *oentry, *nentry; struct audit_entry *oentry, *nentry;
struct audit_buffer *ab;
mutex_lock(&audit_filter_mutex); mutex_lock(&audit_filter_mutex);
list_for_each_entry_safe(owatch, nextw, &parent->watches, wlist) { list_for_each_entry_safe(owatch, nextw, &parent->watches, wlist) {
...@@ -1014,13 +1015,18 @@ static void audit_update_watch(struct audit_parent *parent, ...@@ -1014,13 +1015,18 @@ static void audit_update_watch(struct audit_parent *parent,
call_rcu(&oentry->rcu, audit_free_rule_rcu); call_rcu(&oentry->rcu, audit_free_rule_rcu);
} }
ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); if (audit_enabled) {
audit_log_format(ab, "op=updated rules specifying path="); struct audit_buffer *ab;
audit_log_untrustedstring(ab, owatch->path); ab = audit_log_start(NULL, GFP_KERNEL,
audit_log_format(ab, " with dev=%u ino=%lu\n", dev, ino); AUDIT_CONFIG_CHANGE);
audit_log_format(ab, " list=%d res=1", r->listnr); audit_log_format(ab,
audit_log_end(ab); "op=updated rules specifying path=");
audit_log_untrustedstring(ab, owatch->path);
audit_log_format(ab, " with dev=%u ino=%lu\n",
dev, ino);
audit_log_format(ab, " list=%d res=1", r->listnr);
audit_log_end(ab);
}
audit_remove_watch(owatch); audit_remove_watch(owatch);
goto add_watch_to_parent; /* event applies to a single watch */ goto add_watch_to_parent; /* event applies to a single watch */
} }
...@@ -1039,25 +1045,28 @@ static void audit_remove_parent_watches(struct audit_parent *parent) ...@@ -1039,25 +1045,28 @@ static void audit_remove_parent_watches(struct audit_parent *parent)
struct audit_watch *w, *nextw; struct audit_watch *w, *nextw;
struct audit_krule *r, *nextr; struct audit_krule *r, *nextr;
struct audit_entry *e; struct audit_entry *e;
struct audit_buffer *ab;
mutex_lock(&audit_filter_mutex); mutex_lock(&audit_filter_mutex);
parent->flags |= AUDIT_PARENT_INVALID; parent->flags |= AUDIT_PARENT_INVALID;
list_for_each_entry_safe(w, nextw, &parent->watches, wlist) { list_for_each_entry_safe(w, nextw, &parent->watches, wlist) {
list_for_each_entry_safe(r, nextr, &w->rules, rlist) { list_for_each_entry_safe(r, nextr, &w->rules, rlist) {
e = container_of(r, struct audit_entry, rule); e = container_of(r, struct audit_entry, rule);
if (audit_enabled) {
ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); struct audit_buffer *ab;
audit_log_format(ab, "op=remove rule path="); ab = audit_log_start(NULL, GFP_KERNEL,
audit_log_untrustedstring(ab, w->path); AUDIT_CONFIG_CHANGE);
if (r->filterkey) { audit_log_format(ab, "op=remove rule path=");
audit_log_format(ab, " key="); audit_log_untrustedstring(ab, w->path);
audit_log_untrustedstring(ab, r->filterkey); if (r->filterkey) {
} else audit_log_format(ab, " key=");
audit_log_format(ab, " key=(null)"); audit_log_untrustedstring(ab,
audit_log_format(ab, " list=%d res=1", r->listnr); r->filterkey);
audit_log_end(ab); } else
audit_log_format(ab, " key=(null)");
audit_log_format(ab, " list=%d res=1",
r->listnr);
audit_log_end(ab);
}
list_del(&r->rlist); list_del(&r->rlist);
list_del_rcu(&e->list); list_del_rcu(&e->list);
call_rcu(&e->rcu, audit_free_rule_rcu); call_rcu(&e->rcu, audit_free_rule_rcu);
...@@ -1495,6 +1504,9 @@ static void audit_log_rule_change(uid_t loginuid, u32 sid, char *action, ...@@ -1495,6 +1504,9 @@ static void audit_log_rule_change(uid_t loginuid, u32 sid, char *action,
{ {
struct audit_buffer *ab; struct audit_buffer *ab;
if (!audit_enabled)
return;
ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE); ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
if (!ab) if (!ab)
return; return;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment