Merge branch 'stable-4.13' of git://git.infradead.org/users/pcmoore/audit
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 5 Jul 2017 18:24:05 +0000 (11:24 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 5 Jul 2017 18:24:05 +0000 (11:24 -0700)
Pull audit updates from Paul Moore:
 "Things are relatively quiet on the audit front for v4.13, just five
  patches for a total diffstat of 102 lines.

  There are two patches from Richard to consistently record the POSIX
  capabilities and add the ambient capability information as well.

  I also chipped in two patches to fix a race condition with the auditd
  tracking code and ensure we don't skip sending any records to the
  audit multicast group.

  Finally a single style fix that I accepted because I must have been in
  a good mood that day.

  Everything passes our test suite, and should be relatively harmless,
  please merge for v4.13"

* 'stable-4.13' of git://git.infradead.org/users/pcmoore/audit:
  audit: make sure we never skip the multicast broadcast
  audit: fix a race condition with the auditd tracking code
  audit: style fix
  audit: add ambient capabilities to CAPSET and BPRM_FCAPS records
  audit: unswing cap_* fields in PATH records

1  2 
kernel/audit.c
kernel/auditsc.c

diff --combined kernel/audit.c
index 4b7d49868ce1e39d11603f6160d04e7e5d4457e2,7cad70214b81a1639b0af97b131cbe3db0d46cbf..833267bbd80bc62b367699eb9cdc646c20fb264c
@@@ -575,12 -575,16 +575,16 @@@ static void kauditd_retry_skb(struct sk
  
  /**
   * auditd_reset - Disconnect the auditd connection
+  * @ac: auditd connection state
   *
   * Description:
   * Break the auditd/kauditd connection and move all the queued records into the
-  * hold queue in case auditd reconnects.
+  * hold queue in case auditd reconnects.  It is important to note that the @ac
+  * pointer should never be dereferenced inside this function as it may be NULL
+  * or invalid, you can only compare the memory address!  If @ac is NULL then
+  * the connection will always be reset.
   */
- static void auditd_reset(void)
+ static void auditd_reset(const struct auditd_connection *ac)
  {
        unsigned long flags;
        struct sk_buff *skb;
        spin_lock_irqsave(&auditd_conn_lock, flags);
        ac_old = rcu_dereference_protected(auditd_conn,
                                           lockdep_is_held(&auditd_conn_lock));
+       if (ac && ac != ac_old) {
+               /* someone already registered a new auditd connection */
+               spin_unlock_irqrestore(&auditd_conn_lock, flags);
+               return;
+       }
        rcu_assign_pointer(auditd_conn, NULL);
        spin_unlock_irqrestore(&auditd_conn_lock, flags);
  
        if (ac_old)
                call_rcu(&ac_old->rcu, auditd_conn_free);
  
-       /* flush all of the main and retry queues to the hold queue */
+       /* flush the retry queue to the hold queue, but don't touch the main
+        * queue since we need to process that normally for multicast */
        while ((skb = skb_dequeue(&audit_retry_queue)))
                kauditd_hold_skb(skb);
-       while ((skb = skb_dequeue(&audit_queue)))
-               kauditd_hold_skb(skb);
  }
  
  /**
@@@ -649,8 -657,8 +657,8 @@@ static int auditd_send_unicast_skb(stru
        return rc;
  
  err:
-       if (rc == -ECONNREFUSED)
-               auditd_reset();
+       if (ac && rc == -ECONNREFUSED)
+               auditd_reset(ac);
        return rc;
  }
  
@@@ -795,9 -803,9 +803,9 @@@ static int kauditd_thread(void *dummy
                rc = kauditd_send_queue(sk, portid,
                                        &audit_hold_queue, UNICAST_RETRIES,
                                        NULL, kauditd_rehold_skb);
-               if (rc < 0) {
+               if (ac && rc < 0) {
                        sk = NULL;
-                       auditd_reset();
+                       auditd_reset(ac);
                        goto main_queue;
                }
  
                rc = kauditd_send_queue(sk, portid,
                                        &audit_retry_queue, UNICAST_RETRIES,
                                        NULL, kauditd_hold_skb);
-               if (rc < 0) {
+               if (ac && rc < 0) {
                        sk = NULL;
-                       auditd_reset();
+                       auditd_reset(ac);
                        goto main_queue;
                }
  
@@@ -815,12 -823,13 +823,13 @@@ main_queue
                /* process the main queue - do the multicast send and attempt
                 * unicast, dump failed record sends to the retry queue; if
                 * sk == NULL due to previous failures we will just do the
-                * multicast send and move the record to the retry queue */
+                * multicast send and move the record to the hold queue */
                rc = kauditd_send_queue(sk, portid, &audit_queue, 1,
                                        kauditd_send_multicast_skb,
-                                       kauditd_retry_skb);
-               if (sk == NULL || rc < 0)
-                       auditd_reset();
+                                       (sk ?
+                                        kauditd_retry_skb : kauditd_hold_skb));
+               if (ac && rc < 0)
+                       auditd_reset(ac);
                sk = NULL;
  
                /* drop our netns reference, no auditd sends past this line */
@@@ -1230,7 -1239,7 +1239,7 @@@ static int audit_receive_msg(struct sk_
                                                                auditd_pid, 1);
  
                                /* unregister the auditd connection */
-                               auditd_reset();
+                               auditd_reset(NULL);
                        }
                }
                if (s.mask & AUDIT_STATUS_RATE_LIMIT) {
@@@ -1458,7 -1467,7 +1467,7 @@@ static void audit_receive(struct sk_buf
                err = audit_receive_msg(skb, nlh);
                /* if err or if this message says it wants a response */
                if (err || (nlh->nlmsg_flags & NLM_F_ACK))
 -                      netlink_ack(skb, nlh, err);
 +                      netlink_ack(skb, nlh, err, NULL);
  
                nlh = nlmsg_next(nlh, &len);
        }
@@@ -1999,22 -2008,10 +2008,10 @@@ void audit_log_cap(struct audit_buffer 
  
  static void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name)
  {
-       kernel_cap_t *perm = &name->fcap.permitted;
-       kernel_cap_t *inh = &name->fcap.inheritable;
-       int log = 0;
-       if (!cap_isclear(*perm)) {
-               audit_log_cap(ab, "cap_fp", perm);
-               log = 1;
-       }
-       if (!cap_isclear(*inh)) {
-               audit_log_cap(ab, "cap_fi", inh);
-               log = 1;
-       }
-       if (log)
-               audit_log_format(ab, " cap_fe=%d cap_fver=%x",
-                                name->fcap.fE, name->fcap_ver);
+       audit_log_cap(ab, "cap_fp", &name->fcap.permitted);
+       audit_log_cap(ab, "cap_fi", &name->fcap.inheritable);
+       audit_log_format(ab, " cap_fe=%d cap_fver=%x",
+                        name->fcap.fE, name->fcap_ver);
  }
  
  static inline int audit_copy_fcaps(struct audit_names *name,
diff --combined kernel/auditsc.c
index bb724baa7ac9443b9b0f56b8d046b5ab3de17a65,5fa68d10032f4e243b24b5258ce30eb29164d664..3260ba2312a95e4e500513d5277426e0582b868f
@@@ -73,7 -73,6 +73,7 @@@
  #include <linux/ctype.h>
  #include <linux/string.h>
  #include <linux/uaccess.h>
 +#include <linux/fsnotify_backend.h>
  #include <uapi/linux/limits.h>
  
  #include "audit.h"
@@@ -1261,6 -1260,7 +1261,7 @@@ static void show_special(struct audit_c
                audit_log_cap(ab, "cap_pi", &context->capset.cap.inheritable);
                audit_log_cap(ab, "cap_pp", &context->capset.cap.permitted);
                audit_log_cap(ab, "cap_pe", &context->capset.cap.effective);
+               audit_log_cap(ab, "cap_pa", &context->capset.cap.ambient);
                break;
        case AUDIT_MMAP:
                audit_log_format(ab, "fd=%d flags=0x%x", context->mmap.fd,
@@@ -1382,9 -1382,11 +1383,11 @@@ static void audit_log_exit(struct audit
                        audit_log_cap(ab, "old_pp", &axs->old_pcap.permitted);
                        audit_log_cap(ab, "old_pi", &axs->old_pcap.inheritable);
                        audit_log_cap(ab, "old_pe", &axs->old_pcap.effective);
-                       audit_log_cap(ab, "new_pp", &axs->new_pcap.permitted);
-                       audit_log_cap(ab, "new_pi", &axs->new_pcap.inheritable);
-                       audit_log_cap(ab, "new_pe", &axs->new_pcap.effective);
+                       audit_log_cap(ab, "old_pa", &axs->old_pcap.ambient);
+                       audit_log_cap(ab, "pp", &axs->new_pcap.permitted);
+                       audit_log_cap(ab, "pi", &axs->new_pcap.inheritable);
+                       audit_log_cap(ab, "pe", &axs->new_pcap.effective);
+                       audit_log_cap(ab, "pa", &axs->new_pcap.ambient);
                        break; }
  
                }
@@@ -1597,7 -1599,7 +1600,7 @@@ static inline void handle_one(const str
        struct audit_tree_refs *p;
        struct audit_chunk *chunk;
        int count;
 -      if (likely(hlist_empty(&inode->i_fsnotify_marks)))
 +      if (likely(!inode->i_fsnotify_marks))
                return;
        context = current->audit_context;
        p = context->trees;
@@@ -1640,7 -1642,7 +1643,7 @@@ retry
        seq = read_seqbegin(&rename_lock);
        for(;;) {
                struct inode *inode = d_backing_inode(d);
 -              if (inode && unlikely(!hlist_empty(&inode->i_fsnotify_marks))) {
 +              if (inode && unlikely(inode->i_fsnotify_marks)) {
                        struct audit_chunk *chunk;
                        chunk = audit_tree_lookup(inode);
                        if (chunk) {
@@@ -2342,10 -2344,12 +2345,12 @@@ int __audit_log_bprm_fcaps(struct linux
        ax->old_pcap.permitted   = old->cap_permitted;
        ax->old_pcap.inheritable = old->cap_inheritable;
        ax->old_pcap.effective   = old->cap_effective;
+       ax->old_pcap.ambient     = old->cap_ambient;
  
        ax->new_pcap.permitted   = new->cap_permitted;
        ax->new_pcap.inheritable = new->cap_inheritable;
        ax->new_pcap.effective   = new->cap_effective;
+       ax->new_pcap.ambient     = new->cap_ambient;
        return 0;
  }
  
@@@ -2364,6 -2368,7 +2369,7 @@@ void __audit_log_capset(const struct cr
        context->capset.cap.effective   = new->cap_effective;
        context->capset.cap.inheritable = new->cap_effective;
        context->capset.cap.permitted   = new->cap_permitted;
+       context->capset.cap.ambient     = new->cap_ambient;
        context->type = AUDIT_CAPSET;
  }