]> Pileus Git - ~andy/linux/blobdiff - kernel/audit.c
audit: rework AUDIT_TTY_SET to only grab spin_lock once
[~andy/linux] / kernel / audit.c
index b27b7063654ce79298a88a3c2cb4c3cd93838ec3..b1d24a035ec998c24f27ac192c5a448823fd65a3 100644 (file)
@@ -688,6 +688,7 @@ 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_task_info(ab, current);
        audit_log_format(ab, "feature=%s old=%d new=%d old_lock=%d new_lock=%d res=%d",
                         audit_feature_names[which], !!old_feature, !!new_feature,
                         !!old_lock, !!new_lock, res);
@@ -791,7 +792,7 @@ 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));
@@ -821,7 +822,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                                audit_log_config_change("audit_pid", new_pid, audit_pid, 1);
                        audit_pid = new_pid;
                        audit_nlk_portid = NETLINK_CB(skb).portid;
-                       audit_sock = NETLINK_CB(skb).sk;
+                       audit_sock = skb->sk;
                }
                if (s.mask & AUDIT_STATUS_RATE_LIMIT) {
                        err = audit_set_rate_limit(s.rate_limit);
@@ -833,22 +834,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;
        }
@@ -997,19 +991,24 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                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"
@@ -1017,15 +1016,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                                 " res=%d",
                                 old.enabled, old.log_passwd,
                                 s.enabled, s.log_passwd,
-                                res);
+                                !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:
@@ -1280,21 +1272,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,13 +1329,12 @@ 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;
                        }
                }