* 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
* (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. */
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_sid_to_string(sid, &ctx, &len)))
- return rc;
- else
+ if ((rc = selinux_sid_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_sid_to_string(sid, &ctx, &len)))
- return rc;
- else
+ if ((rc = selinux_sid_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_sid_to_string(sid, &ctx, &len)))
- return rc;
- else
+ if ((rc = selinux_sid_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_sid_to_string(sid, &ctx, &len)))
- return rc;
- else
+ 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",
- 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)
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_sid_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,
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_sid_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,