]> Git Repo - J-linux.git/commitdiff
Merge tag 'audit-pr-20200601' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoor...
authorLinus Torvalds <[email protected]>
Wed, 3 Jun 2020 00:13:37 +0000 (17:13 -0700)
committerLinus Torvalds <[email protected]>
Wed, 3 Jun 2020 00:13:37 +0000 (17:13 -0700)
Pull audit updates from Paul Moore:
 "Summary of the significant patches:

   - Record information about binds/unbinds to the audit multicast
     socket. This helps identify which processes have/had access to the
     information in the audit stream.

   - Cleanup and add some additional information to the netfilter
     configuration events collected by audit.

   - Fix some of the audit error handling code so we don't leak network
     namespace references"

* tag 'audit-pr-20200601' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/audit:
  audit: add subj creds to NETFILTER_CFG record to
  audit: Replace zero-length array with flexible-array
  audit: make symbol 'audit_nfcfgs' static
  netfilter: add audit table unregister actions
  audit: tidy and extend netfilter_cfg x_tables
  audit: log audit netlink multicast bind and unbind
  audit: fix a net reference leak in audit_list_rules_send()
  audit: fix a net reference leak in audit_send_reply()

1  2 
kernel/audit.c
net/bridge/netfilter/ebtables.c

diff --combined kernel/audit.c
index 87f31bf1f0a0c80304a6ff82cc4207aee1194ca7,e33460e01b3b7f7f9026d9afafaf1774c842c88d..8c201f414226246f7f6c173faa721423aabff51f
@@@ -880,7 -880,7 +880,7 @@@ main_queue
        return 0;
  }
  
- int audit_send_list(void *_dest)
+ int audit_send_list_thread(void *_dest)
  {
        struct audit_netlink_list *dest = _dest;
        struct sk_buff *skb;
@@@ -924,19 -924,30 +924,30 @@@ out_kfree_skb
        return NULL;
  }
  
+ static void audit_free_reply(struct audit_reply *reply)
+ {
+       if (!reply)
+               return;
+       if (reply->skb)
+               kfree_skb(reply->skb);
+       if (reply->net)
+               put_net(reply->net);
+       kfree(reply);
+ }
  static int audit_send_reply_thread(void *arg)
  {
        struct audit_reply *reply = (struct audit_reply *)arg;
-       struct sock *sk = audit_get_sk(reply->net);
  
        audit_ctl_lock();
        audit_ctl_unlock();
  
        /* Ignore failure. It'll only happen if the sender goes away,
           because our timeout is set to infinite. */
-       netlink_unicast(sk, reply->skb, reply->portid, 0);
-       put_net(reply->net);
-       kfree(reply);
+       netlink_unicast(audit_get_sk(reply->net), reply->skb, reply->portid, 0);
+       reply->skb = NULL;
+       audit_free_reply(reply);
        return 0;
  }
  
   * @payload: payload data
   * @size: payload size
   *
-  * Allocates an skb, builds the netlink message, and sends it to the port id.
-  * No failure notifications.
+  * Allocates a skb, builds the netlink message, and sends it to the port id.
   */
  static void audit_send_reply(struct sk_buff *request_skb, int seq, int type, int done,
                             int multi, const void *payload, int size)
  {
-       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),
-                                           GFP_KERNEL);
+       struct audit_reply *reply;
  
+       reply = kzalloc(sizeof(*reply), GFP_KERNEL);
        if (!reply)
                return;
  
-       skb = audit_make_reply(seq, type, done, multi, payload, size);
-       if (!skb)
-               goto out;
-       reply->net = get_net(net);
+       reply->skb = audit_make_reply(seq, type, done, multi, payload, size);
+       if (!reply->skb)
+               goto err;
+       reply->net = get_net(sock_net(NETLINK_CB(request_skb).sk));
        reply->portid = NETLINK_CB(request_skb).portid;
-       reply->skb = skb;
  
        tsk = kthread_run(audit_send_reply_thread, reply, "audit_send_reply");
-       if (!IS_ERR(tsk))
-               return;
-       kfree_skb(skb);
- out:
-       kfree(reply);
+       if (IS_ERR(tsk))
+               goto err;
+       return;
+ err:
+       audit_free_reply(reply);
  }
  
  /*
@@@ -1326,9 -1334,6 +1334,9 @@@ static int audit_receive_msg(struct sk_
        case AUDIT_FIRST_USER_MSG2 ... AUDIT_LAST_USER_MSG2:
                if (!audit_enabled && msg_type != AUDIT_USER_AVC)
                        return 0;
 +              /* exit early if there isn't at least one character to print */
 +              if (data_len < 2)
 +                      return -EINVAL;
  
                err = audit_filter(msg_type, AUDIT_FILTER_USER);
                if (err == 1) { /* match or error */
@@@ -1525,20 -1530,60 +1533,60 @@@ static void audit_receive(struct sk_buf
        audit_ctl_unlock();
  }
  
+ /* Log information about who is connecting to the audit multicast socket */
+ static void audit_log_multicast(int group, const char *op, int err)
+ {
+       const struct cred *cred;
+       struct tty_struct *tty;
+       char comm[sizeof(current->comm)];
+       struct audit_buffer *ab;
+       if (!audit_enabled)
+               return;
+       ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_EVENT_LISTENER);
+       if (!ab)
+               return;
+       cred = current_cred();
+       tty = audit_get_tty();
+       audit_log_format(ab, "pid=%u uid=%u auid=%u tty=%s ses=%u",
+                        task_pid_nr(current),
+                        from_kuid(&init_user_ns, cred->uid),
+                        from_kuid(&init_user_ns, audit_get_loginuid(current)),
+                        tty ? tty_name(tty) : "(none)",
+                        audit_get_sessionid(current));
+       audit_put_tty(tty);
+       audit_log_task_context(ab); /* subj= */
+       audit_log_format(ab, " comm=");
+       audit_log_untrustedstring(ab, get_task_comm(comm, current));
+       audit_log_d_path_exe(ab, current->mm); /* exe= */
+       audit_log_format(ab, " nl-mcgrp=%d op=%s res=%d", group, op, !err);
+       audit_log_end(ab);
+ }
  /* Run custom bind function on netlink socket group connect or bind requests. */
- static int audit_bind(struct net *net, int group)
+ static int audit_multicast_bind(struct net *net, int group)
  {
+       int err = 0;
        if (!capable(CAP_AUDIT_READ))
-               return -EPERM;
+               err = -EPERM;
+       audit_log_multicast(group, "connect", err);
+       return err;
+ }
  
-       return 0;
+ static void audit_multicast_unbind(struct net *net, int group)
+ {
+       audit_log_multicast(group, "disconnect", 0);
  }
  
  static int __net_init audit_net_init(struct net *net)
  {
        struct netlink_kernel_cfg cfg = {
                .input  = audit_receive,
-               .bind   = audit_bind,
+               .bind   = audit_multicast_bind,
+               .unbind = audit_multicast_unbind,
                .flags  = NL_CFG_F_NONROOT_RECV,
                .groups = AUDIT_NLGRP_MAX,
        };
index 7e869284e0523e04d6828388710fdb49424dbb74,4778db5601b0d082a2d932e0cd6548964cf69a81..c83ffe9121639ce4c608afcd4c05089e759b7d7d
@@@ -1046,14 -1046,8 +1046,8 @@@ static int do_replace_finish(struct ne
        vfree(table);
        vfree(counterstmp);
  
- #ifdef CONFIG_AUDIT
-       if (audit_enabled) {
-               audit_log(audit_context(), GFP_KERNEL,
-                         AUDIT_NETFILTER_CFG,
-                         "table=%s family=%u entries=%u",
-                         repl->name, AF_BRIDGE, repl->nentries);
-       }
- #endif
+       audit_log_nfcfg(repl->name, AF_BRIDGE, repl->nentries,
+                       AUDIT_XT_OP_REPLACE);
        return ret;
  
  free_unlock:
@@@ -1095,14 -1089,16 +1089,14 @@@ static int do_replace(struct net *net, 
        tmp.name[sizeof(tmp.name) - 1] = 0;
  
        countersize = COUNTER_OFFSET(tmp.nentries) * nr_cpu_ids;
 -      newinfo = __vmalloc(sizeof(*newinfo) + countersize, GFP_KERNEL_ACCOUNT,
 -                          PAGE_KERNEL);
 +      newinfo = __vmalloc(sizeof(*newinfo) + countersize, GFP_KERNEL_ACCOUNT);
        if (!newinfo)
                return -ENOMEM;
  
        if (countersize)
                memset(newinfo->counters, 0, countersize);
  
 -      newinfo->entries = __vmalloc(tmp.entries_size, GFP_KERNEL_ACCOUNT,
 -                                   PAGE_KERNEL);
 +      newinfo->entries = __vmalloc(tmp.entries_size, GFP_KERNEL_ACCOUNT);
        if (!newinfo->entries) {
                ret = -ENOMEM;
                goto free_newinfo;
@@@ -1128,6 -1124,8 +1122,8 @@@ static void __ebt_unregister_table(stru
        mutex_lock(&ebt_mutex);
        list_del(&table->list);
        mutex_unlock(&ebt_mutex);
+       audit_log_nfcfg(table->name, AF_BRIDGE, table->private->nentries,
+                       AUDIT_XT_OP_UNREGISTER);
        EBT_ENTRY_ITERATE(table->private->entries, table->private->entries_size,
                          ebt_cleanup_entry, net, NULL);
        if (table->private->nentries)
@@@ -1221,6 -1219,8 +1217,8 @@@ int ebt_register_table(struct net *net
                *res = NULL;
        }
  
+       audit_log_nfcfg(repl->name, AF_BRIDGE, repl->nentries,
+                       AUDIT_XT_OP_REGISTER);
        return ret;
  free_unlock:
        mutex_unlock(&ebt_mutex);
This page took 0.083174 seconds and 4 git commands to generate.