]> Pileus Git - ~andy/linux/blobdiff - kernel/audit.c
AUDIT: Allow login in non-init namespaces
[~andy/linux] / kernel / audit.c
index ef5bd63f5cb8b2f196427a76be9794f25973896e..95a20f3f52f1c9f35b7d6aa2cb0a8b7c05fdbc69 100644 (file)
@@ -41,6 +41,8 @@
  * Example user-space utilities: http://people.redhat.com/sgrubb/audit/
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/init.h>
 #include <asm/types.h>
 #include <linux/atomic.h>
@@ -77,16 +79,16 @@ static int  audit_initialized;
 #define AUDIT_OFF      0
 #define AUDIT_ON       1
 #define AUDIT_LOCKED   2
-int            audit_enabled;
-int            audit_ever_enabled;
+u32            audit_enabled;
+u32            audit_ever_enabled;
 
 EXPORT_SYMBOL_GPL(audit_enabled);
 
 /* Default state when kernel boots without any parameters. */
-static int     audit_default;
+static u32     audit_default;
 
 /* If auditing cannot proceed, audit_failure selects what happens. */
-static int     audit_failure = AUDIT_FAIL_PRINTK;
+static u32     audit_failure = AUDIT_FAIL_PRINTK;
 
 /*
  * If audit records are to be written to the netlink socket, audit_pid
@@ -99,14 +101,14 @@ static __u32       audit_nlk_portid;
 /* If audit_rate_limit is non-zero, limit the rate of sending audit records
  * to that number per second.  This prevents DoS attacks, but results in
  * audit records being dropped. */
-static int     audit_rate_limit;
+static u32     audit_rate_limit;
 
 /* Number of outstanding audit_buffers allowed.
  * When set to zero, this means unlimited. */
-static int     audit_backlog_limit = 64;
+static u32     audit_backlog_limit = 64;
 #define AUDIT_BACKLOG_WAIT_TIME (60 * HZ)
-static int     audit_backlog_wait_time = AUDIT_BACKLOG_WAIT_TIME;
-static int     audit_backlog_wait_overflow = 0;
+static u32     audit_backlog_wait_time = AUDIT_BACKLOG_WAIT_TIME;
+static u32     audit_backlog_wait_overflow = 0;
 
 /* The identity of the user shutting down the audit system. */
 kuid_t         audit_sig_uid = INVALID_UID;
@@ -180,7 +182,7 @@ struct audit_buffer {
 
 struct audit_reply {
        __u32 portid;
-       pid_t pid;
+       struct net *net;        
        struct sk_buff *skb;
 };
 
@@ -194,13 +196,12 @@ static void audit_set_portid(struct audit_buffer *ab, __u32 portid)
 
 void audit_panic(const char *message)
 {
-       switch (audit_failure)
-       {
+       switch (audit_failure) {
        case AUDIT_FAIL_SILENT:
                break;
        case AUDIT_FAIL_PRINTK:
                if (printk_ratelimit())
-                       printk(KERN_ERR "audit: %s\n", message);
+                       pr_err("%s\n", message);
                break;
        case AUDIT_FAIL_PANIC:
                /* test audit_pid since printk is always losey, why bother? */
@@ -271,9 +272,7 @@ void audit_log_lost(const char *message)
 
        if (print) {
                if (printk_ratelimit())
-                       printk(KERN_WARNING
-                               "audit: audit_lost=%d audit_rate_limit=%d "
-                               "audit_backlog_limit=%d\n",
+                       pr_warn("audit_lost=%u audit_rate_limit=%u audit_backlog_limit=%u\n",
                                atomic_read(&audit_lost),
                                audit_rate_limit,
                                audit_backlog_limit);
@@ -281,7 +280,7 @@ void audit_log_lost(const char *message)
        }
 }
 
-static int audit_log_config_change(char *function_name, int new, int old,
+static int audit_log_config_change(char *function_name, u32 new, u32 old,
                                   int allow_changes)
 {
        struct audit_buffer *ab;
@@ -290,7 +289,7 @@ static int audit_log_config_change(char *function_name, int new, int old,
        ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
        if (unlikely(!ab))
                return rc;
-       audit_log_format(ab, "%s=%d old=%d", function_name, new, old);
+       audit_log_format(ab, "%s=%u old=%u", function_name, new, old);
        audit_log_session_info(ab);
        rc = audit_log_task_context(ab);
        if (rc)
@@ -300,9 +299,10 @@ static int audit_log_config_change(char *function_name, int new, int old,
        return rc;
 }
 
-static int audit_do_config_change(char *function_name, int *to_change, int new)
+static int audit_do_config_change(char *function_name, u32 *to_change, u32 new)
 {
-       int allow_changes, rc = 0, old = *to_change;
+       int allow_changes, rc = 0;
+       u32 old = *to_change;
 
        /* check if we are locked */
        if (audit_enabled == AUDIT_LOCKED)
@@ -325,23 +325,23 @@ static int audit_do_config_change(char *function_name, int *to_change, int new)
        return rc;
 }
 
-static int audit_set_rate_limit(int limit)
+static int audit_set_rate_limit(u32 limit)
 {
        return audit_do_config_change("audit_rate_limit", &audit_rate_limit, limit);
 }
 
-static int audit_set_backlog_limit(int limit)
+static int audit_set_backlog_limit(u32 limit)
 {
        return audit_do_config_change("audit_backlog_limit", &audit_backlog_limit, limit);
 }
 
-static int audit_set_backlog_wait_time(int timeout)
+static int audit_set_backlog_wait_time(u32 timeout)
 {
        return audit_do_config_change("audit_backlog_wait_time",
                                      &audit_backlog_wait_time, timeout);
 }
 
-static int audit_set_enabled(int state)
+static int audit_set_enabled(u32 state)
 {
        int rc;
        if (state < AUDIT_OFF || state > AUDIT_LOCKED)
@@ -354,7 +354,7 @@ static int audit_set_enabled(int state)
        return rc;
 }
 
-static int audit_set_failure(int state)
+static int audit_set_failure(u32 state)
 {
        if (state != AUDIT_FAIL_SILENT
            && state != AUDIT_FAIL_PRINTK
@@ -394,7 +394,7 @@ static void audit_printk_skb(struct sk_buff *skb)
 
        if (nlh->nlmsg_type != AUDIT_EOE) {
                if (printk_ratelimit())
-                       printk(KERN_NOTICE "type=%d %s\n", nlh->nlmsg_type, data);
+                       pr_notice("type=%d %s\n", nlh->nlmsg_type, data);
                else
                        audit_log_lost("printk limit exceeded\n");
        }
@@ -411,7 +411,7 @@ static void kauditd_send_skb(struct sk_buff *skb)
        if (err < 0) {
                BUG_ON(err != -ECONNREFUSED); /* Shouldn't happen */
                if (audit_pid) {
-                       printk(KERN_ERR "audit: *NO* daemon at audit_pid=%d\n", audit_pid);
+                       pr_err("*NO* daemon at audit_pid=%d\n", audit_pid);
                        audit_log_lost("auditd disappeared\n");
                        audit_pid = 0;
                        audit_sock = NULL;
@@ -500,7 +500,7 @@ int audit_send_list(void *_dest)
 {
        struct audit_netlink_list *dest = _dest;
        struct sk_buff *skb;
-       struct net *net = get_net_ns_by_pid(dest->pid);
+       struct net *net = dest->net;
        struct audit_net *aunet = net_generic(net, audit_net_id);
 
        /* wait for parent to finish and send an ACK */
@@ -510,6 +510,7 @@ int audit_send_list(void *_dest)
        while ((skb = __skb_dequeue(&dest->q)) != NULL)
                netlink_unicast(aunet->nlsk, skb, dest->portid, 0);
 
+       put_net(net);
        kfree(dest);
 
        return 0;
@@ -543,7 +544,7 @@ out_kfree_skb:
 static int audit_send_reply_thread(void *arg)
 {
        struct audit_reply *reply = (struct audit_reply *)arg;
-       struct net *net = get_net_ns_by_pid(reply->pid);
+       struct net *net = reply->net;
        struct audit_net *aunet = net_generic(net, audit_net_id);
 
        mutex_lock(&audit_cmd_mutex);
@@ -552,12 +553,13 @@ static int audit_send_reply_thread(void *arg)
        /* Ignore failure. It'll only happen if the sender goes away,
           because our timeout is set to infinite. */
        netlink_unicast(aunet->nlsk , reply->skb, reply->portid, 0);
+       put_net(net);
        kfree(reply);
        return 0;
 }
 /**
  * audit_send_reply - send an audit reply message via netlink
- * @portid: netlink port to which to send reply
+ * @request_skb: skb of request we are replying to (used to target the reply)
  * @seq: sequence number
  * @type: audit message type
  * @done: done (last) flag
@@ -568,9 +570,11 @@ static int audit_send_reply_thread(void *arg)
  * Allocates an skb, builds the netlink message, and sends it to the port id.
  * No failure notifications.
  */
-static void audit_send_reply(__u32 portid, int seq, int type, int done,
+static void audit_send_reply(struct sk_buff *request_skb, int seq, int type, int done,
                             int multi, const void *payload, int size)
 {
+       u32 portid = NETLINK_CB(request_skb).portid;
+       struct net *net = sock_net(NETLINK_CB(request_skb).sk);
        struct sk_buff *skb;
        struct task_struct *tsk;
        struct audit_reply *reply = kmalloc(sizeof(struct audit_reply),
@@ -583,8 +587,8 @@ static void audit_send_reply(__u32 portid, int seq, int type, int done,
        if (!skb)
                goto out;
 
+       reply->net = get_net(net);
        reply->portid = portid;
-       reply->pid = task_pid_vnr(current);
        reply->skb = skb;
 
        tsk = kthread_run(audit_send_reply_thread, reply, "audit_send_reply");
@@ -604,9 +608,19 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type)
        int err = 0;
 
        /* Only support the initial namespaces for now. */
+       /*
+        * We return ECONNREFUSED because it tricks userspace into thinking
+        * that audit was not configured into the kernel.  Lots of users
+        * configure their PAM stack (because that's what the distro does)
+        * to reject login if unable to send messages to audit.  If we return
+        * ECONNREFUSED the PAM stack thinks the kernel does not have audit
+        * configured in and will let login proceed.  If we return EPERM
+        * userspace will reject all logins.  This should be removed when we
+        * support non init namespaces!!
+        */
        if ((current_user_ns() != &init_user_ns) ||
            (task_active_pid_ns(current) != &init_pid_ns))
-               return -EPERM;
+               return -ECONNREFUSED;
 
        switch (msg_type) {
        case AUDIT_LIST:
@@ -673,8 +687,7 @@ static int audit_get_feature(struct sk_buff *skb)
 
        seq = nlmsg_hdr(skb)->nlmsg_seq;
 
-       audit_send_reply(NETLINK_CB(skb).portid, seq, AUDIT_GET, 0, 0,
-                        &af, sizeof(af));
+       audit_send_reply(skb, seq, AUDIT_GET, 0, 0, &af, sizeof(af));
 
        return 0;
 }
@@ -688,7 +701,8 @@ static void audit_log_feature_change(int which, u32 old_feature, u32 new_feature
                return;
 
        ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_FEATURE_CHANGE);
-       audit_log_format(ab, "feature=%s old=%d new=%d old_lock=%d new_lock=%d res=%d",
+       audit_log_task_info(ab, current);
+       audit_log_format(ab, "feature=%s old=%u new=%u old_lock=%u new_lock=%u res=%d",
                         audit_feature_names[which], !!old_feature, !!new_feature,
                         !!old_lock, !!new_lock, res);
        audit_log_end(ab);
@@ -791,10 +805,9 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                s.backlog_limit         = audit_backlog_limit;
                s.lost                  = atomic_read(&audit_lost);
                s.backlog               = skb_queue_len(&audit_skb_queue);
-               s.version               = 2;
+               s.version               = AUDIT_VERSION_LATEST;
                s.backlog_wait_time     = audit_backlog_wait_time;
-               audit_send_reply(NETLINK_CB(skb).portid, seq, AUDIT_GET, 0, 0,
-                                &s, sizeof(s));
+               audit_send_reply(skb, seq, AUDIT_GET, 0, 0, &s, sizeof(s));
                break;
        }
        case AUDIT_SET: {
@@ -833,22 +846,15 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                        if (err < 0)
                                return err;
                }
-               switch (s.version) {
-               /* add future vers # cases immediately below and allow
-                * to fall through */
-               case 2:
-                       if (s.mask & AUDIT_STATUS_BACKLOG_WAIT_TIME) {
-                               if (sizeof(s) > (size_t)nlh->nlmsg_len)
-                                       return -EINVAL;
-                               if (s.backlog_wait_time < 0 ||
-                                   s.backlog_wait_time > 10*AUDIT_BACKLOG_WAIT_TIME)
-                                       return -EINVAL;
-                               err = audit_set_backlog_wait_time(s.backlog_wait_time);
-                               if (err < 0)
-                                       return err;
-                       }
-               default:
-                       break;
+               if (s.mask & AUDIT_STATUS_BACKLOG_WAIT_TIME) {
+                       if (sizeof(s) > (size_t)nlh->nlmsg_len)
+                               return -EINVAL;
+                       if (s.backlog_wait_time < 0 ||
+                           s.backlog_wait_time > 10*AUDIT_BACKLOG_WAIT_TIME)
+                               return -EINVAL;
+                       err = audit_set_backlog_wait_time(s.backlog_wait_time);
+                       if (err < 0)
+                               return err;
                }
                break;
        }
@@ -911,7 +917,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                                           seq, data, nlmsg_len(nlh));
                break;
        case AUDIT_LIST_RULES:
-               err = audit_list_rules_send(NETLINK_CB(skb).portid, seq);
+               err = audit_list_rules_send(skb, seq);
                break;
        case AUDIT_TRIM:
                audit_trim_trees();
@@ -976,8 +982,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                        memcpy(sig_data->ctx, ctx, len);
                        security_release_secctx(ctx, len);
                }
-               audit_send_reply(NETLINK_CB(skb).portid, seq, AUDIT_SIGNAL_INFO,
-                               0, 0, sig_data, sizeof(*sig_data) + len);
+               audit_send_reply(skb, seq, AUDIT_SIGNAL_INFO, 0, 0,
+                                sig_data, sizeof(*sig_data) + len);
                kfree(sig_data);
                break;
        case AUDIT_TTY_GET: {
@@ -989,43 +995,37 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                s.log_passwd = tsk->signal->audit_tty_log_passwd;
                spin_unlock(&tsk->sighand->siglock);
 
-               audit_send_reply(NETLINK_CB(skb).portid, seq,
-                                AUDIT_TTY_GET, 0, 0, &s, sizeof(s));
+               audit_send_reply(skb, seq, AUDIT_TTY_GET, 0, 0, &s, sizeof(s));
                break;
        }
        case AUDIT_TTY_SET: {
                struct audit_tty_status s, old;
                struct task_struct *tsk = current;
                struct audit_buffer     *ab;
-               int res = 0;
+
+               memset(&s, 0, sizeof(s));
+               /* guard against past and future API changes */
+               memcpy(&s, data, min_t(size_t, sizeof(s), nlmsg_len(nlh)));
+               /* check if new data is valid */
+               if ((s.enabled != 0 && s.enabled != 1) ||
+                   (s.log_passwd != 0 && s.log_passwd != 1))
+                       err = -EINVAL;
 
                spin_lock(&tsk->sighand->siglock);
                old.enabled = tsk->signal->audit_tty;
                old.log_passwd = tsk->signal->audit_tty_log_passwd;
+               if (!err) {
+                       tsk->signal->audit_tty = s.enabled;
+                       tsk->signal->audit_tty_log_passwd = s.log_passwd;
+               }
                spin_unlock(&tsk->sighand->siglock);
 
-               memset(&s, 0, sizeof(s));
-               /* guard against past and future API changes */
-               memcpy(&s, data, min_t(size_t, sizeof(s), nlmsg_len(nlh)));
-               if ((s.enabled == 0 || s.enabled == 1) &&
-                   (s.log_passwd == 0 || s.log_passwd == 1))
-                       res = 1;
                audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE);
-               audit_log_format(ab, " op=tty_set"
-                                " old-enabled=%d old-log_passwd=%d"
-                                " new-enabled=%d new-log_passwd=%d"
-                                " res=%d",
-                                old.enabled, old.log_passwd,
-                                s.enabled, s.log_passwd,
-                                res);
+               audit_log_format(ab, " op=tty_set old-enabled=%d new-enabled=%d"
+                                " old-log_passwd=%d new-log_passwd=%d res=%d",
+                                old.enabled, s.enabled, old.log_passwd,
+                                s.log_passwd, !err);
                audit_log_end(ab);
-               if (res) {
-                       spin_lock(&tsk->sighand->siglock);
-                       tsk->signal->audit_tty = s.enabled;
-                       tsk->signal->audit_tty_log_passwd = s.log_passwd;
-                       spin_unlock(&tsk->sighand->siglock);
-               } else
-                       return -EINVAL;
                break;
        }
        default:
@@ -1079,8 +1079,6 @@ static int __net_init audit_net_init(struct net *net)
 
        struct audit_net *aunet = net_generic(net, audit_net_id);
 
-       pr_info("audit: initializing netlink socket in namespace\n");
-
        aunet->nlsk = netlink_kernel_create(net, NETLINK_AUDIT, &cfg);
        if (aunet->nlsk == NULL) {
                audit_panic("cannot initialize netlink socket in namespace");
@@ -1104,7 +1102,7 @@ static void __net_exit audit_net_exit(struct net *net)
        netlink_kernel_release(sock);
 }
 
-static struct pernet_operations __net_initdata audit_net_ops = {
+static struct pernet_operations audit_net_ops __net_initdata = {
        .init = audit_net_init,
        .exit = audit_net_exit,
        .id = &audit_net_id,
@@ -1119,8 +1117,8 @@ static int __init audit_init(void)
        if (audit_initialized == AUDIT_DISABLED)
                return 0;
 
-       pr_info("audit: initializing netlink subsys (%s)\n",
-              audit_default ? "enabled" : "disabled");
+       pr_info("initializing netlink subsys (%s)\n",
+               audit_default ? "enabled" : "disabled");
        register_pernet_subsys(&audit_net_ops);
 
        skb_queue_head_init(&audit_skb_queue);
@@ -1145,7 +1143,7 @@ static int __init audit_enable(char *str)
        if (!audit_default)
                audit_initialized = AUDIT_DISABLED;
 
-       pr_info("audit: %s\n", audit_default ?
+       pr_info("%s\n", audit_default ?
                "enabled (after initialization)" : "disabled (until reboot)");
 
        return 1;
@@ -1156,16 +1154,17 @@ __setup("audit=", audit_enable);
  * audit_backlog_limit=<n> */
 static int __init audit_backlog_limit_set(char *str)
 {
-       long int audit_backlog_limit_arg;
+       u32 audit_backlog_limit_arg;
+
        pr_info("audit_backlog_limit: ");
-       if (kstrtol(str, 0, &audit_backlog_limit_arg)) {
-               printk("using default of %d, unable to parse %s\n",
-                      audit_backlog_limit, str);
+       if (kstrtouint(str, 0, &audit_backlog_limit_arg)) {
+               pr_cont("using default of %u, unable to parse %s\n",
+                       audit_backlog_limit, str);
                return 1;
        }
-       if (audit_backlog_limit_arg >= 0)
-               audit_backlog_limit = (int)audit_backlog_limit_arg;
-       printk("%d\n", audit_backlog_limit);
+
+       audit_backlog_limit = audit_backlog_limit_arg;
+       pr_cont("%d\n", audit_backlog_limit);
 
        return 1;
 }
@@ -1280,21 +1279,20 @@ static inline void audit_get_stamp(struct audit_context *ctx,
 /*
  * Wait for auditd to drain the queue a little
  */
-static unsigned long wait_for_auditd(unsigned long sleep_time)
+static long wait_for_auditd(long sleep_time)
 {
-       unsigned long timeout = sleep_time;
        DECLARE_WAITQUEUE(wait, current);
        set_current_state(TASK_UNINTERRUPTIBLE);
        add_wait_queue_exclusive(&audit_backlog_wait, &wait);
 
        if (audit_backlog_limit &&
            skb_queue_len(&audit_skb_queue) > audit_backlog_limit)
-               timeout = schedule_timeout(sleep_time);
+               sleep_time = schedule_timeout(sleep_time);
 
        __set_current_state(TASK_RUNNING);
        remove_wait_queue(&audit_backlog_wait, &wait);
 
-       return timeout;
+       return sleep_time;
 }
 
 /**
@@ -1338,22 +1336,19 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
        while (audit_backlog_limit
               && skb_queue_len(&audit_skb_queue) > audit_backlog_limit + reserve) {
                if (gfp_mask & __GFP_WAIT && audit_backlog_wait_time) {
-                       unsigned long sleep_time;
+                       long sleep_time;
 
-                       sleep_time = timeout_start + audit_backlog_wait_time -
-                                       jiffies;
-                       if ((long)sleep_time > 0) {
+                       sleep_time = timeout_start + audit_backlog_wait_time - jiffies;
+                       if (sleep_time > 0) {
                                sleep_time = wait_for_auditd(sleep_time);
-                               if ((long)sleep_time > 0)
+                               if (sleep_time > 0)
                                        continue;
                        }
                }
                if (audit_rate_check() && printk_ratelimit())
-                       printk(KERN_WARNING
-                              "audit: audit_backlog=%d > "
-                              "audit_backlog_limit=%d\n",
-                              skb_queue_len(&audit_skb_queue),
-                              audit_backlog_limit);
+                       pr_warn("audit_backlog=%d > audit_backlog_limit=%d\n",
+                               skb_queue_len(&audit_skb_queue),
+                               audit_backlog_limit);
                audit_log_lost("backlog limit exceeded");
                audit_backlog_wait_time = audit_backlog_wait_overflow;
                wake_up(&audit_backlog_wait);
@@ -1479,7 +1474,6 @@ void audit_log_n_hex(struct audit_buffer *ab, const unsigned char *buf,
        int i, avail, new_len;
        unsigned char *ptr;
        struct sk_buff *skb;
-       static const unsigned char *hex = "0123456789ABCDEF";
 
        if (!ab)
                return;
@@ -1497,10 +1491,8 @@ void audit_log_n_hex(struct audit_buffer *ab, const unsigned char *buf,
        }
 
        ptr = skb_tail_pointer(skb);
-       for (i=0; i<len; i++) {
-               *ptr++ = hex[(buf[i] & 0xF0)>>4]; /* Upper nibble */
-               *ptr++ = hex[buf[i] & 0x0F];      /* Lower nibble */
-       }
+       for (i = 0; i < len; i++)
+               ptr = hex_byte_pack_upper(ptr, buf[i]);
        *ptr = 0;
        skb_put(skb, len << 1); /* new string is twice the old string */
 }