Merge with master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
authorDavid Woodhouse <dwmw2@shinybook.infradead.org>
Thu, 5 May 2005 12:59:37 +0000 (13:59 +0100)
committerDavid Woodhouse <dwmw2@shinybook.infradead.org>
Thu, 5 May 2005 12:59:37 +0000 (13:59 +0100)
1  2 
kernel/audit.c
net/netlink/af_netlink.c

diff --combined kernel/audit.c
index 00455a9cf027917f3253cf3c654194c635743e1d,ac26d4d960d3366d0473ede3533ab89446b75dc3..9c4f1af0c794674404810d7caff0131218cbc950
@@@ -1,4 -1,4 +1,4 @@@
 -/* audit.c -- Auditing support -*- linux-c -*-
 +/* audit.c -- Auditing support
   * Gateway between the kernel (e.g., selinux) and the user-space audit daemon.
   * System-call specific features have moved to auditsc.c
   *
@@@ -38,7 -38,7 +38,7 @@@
   *      6) Support low-overhead kernel-based filtering to minimize the
   *         information that must be passed to user-space.
   *
 - * Example user-space utilities: http://people.redhat.com/faith/audit/
 + * Example user-space utilities: http://people.redhat.com/sgrubb/audit/
   */
  
  #include <linux/init.h>
@@@ -142,6 -142,7 +142,6 @@@ struct audit_buffer 
        int                  total;
        int                  type;
        int                  pid;
 -      int                  count; /* Times requeued */
  };
  
  void audit_set_type(struct audit_buffer *ab, int type)
@@@ -238,36 -239,36 +238,36 @@@ void audit_log_lost(const char *message
  
  }
  
 -static int audit_set_rate_limit(int limit)
 +static int audit_set_rate_limit(int limit, uid_t loginuid)
  {
        int old          = audit_rate_limit;
        audit_rate_limit = limit;
 -      audit_log(current->audit_context, "audit_rate_limit=%d old=%d",
 -                audit_rate_limit, old);
 +      audit_log(NULL, "audit_rate_limit=%d old=%d by auid %u",
 +                      audit_rate_limit, old, loginuid);
        return old;
  }
  
 -static int audit_set_backlog_limit(int limit)
 +static int audit_set_backlog_limit(int limit, uid_t loginuid)
  {
        int old          = audit_backlog_limit;
        audit_backlog_limit = limit;
 -      audit_log(current->audit_context, "audit_backlog_limit=%d old=%d",
 -                audit_backlog_limit, old);
 +      audit_log(NULL, "audit_backlog_limit=%d old=%d by auid %u",
 +                      audit_backlog_limit, old, loginuid);
        return old;
  }
  
 -static int audit_set_enabled(int state)
 +static int audit_set_enabled(int state, uid_t loginuid)
  {
        int old          = audit_enabled;
        if (state != 0 && state != 1)
                return -EINVAL;
        audit_enabled = state;
 -      audit_log(current->audit_context, "audit_enabled=%d old=%d",
 -                audit_enabled, old);
 +      audit_log(NULL, "audit_enabled=%d old=%d by auid %u",
 +                audit_enabled, old, loginuid);
        return old;
  }
  
 -static int audit_set_failure(int state)
 +static int audit_set_failure(int state, uid_t loginuid)
  {
        int old          = audit_failure;
        if (state != AUDIT_FAIL_SILENT
            && state != AUDIT_FAIL_PANIC)
                return -EINVAL;
        audit_failure = state;
 -      audit_log(current->audit_context, "audit_failure=%d old=%d",
 -                audit_failure, old);
 +      audit_log(NULL, "audit_failure=%d old=%d by auid %u",
 +                audit_failure, old, loginuid);
        return old;
  }
  
@@@ -343,7 -344,6 +343,7 @@@ static int audit_receive_msg(struct sk_
        int                     err;
        struct audit_buffer     *ab;
        u16                     msg_type = nlh->nlmsg_type;
 +      uid_t                   loginuid; /* loginuid of sender */
  
        err = audit_netlink_ok(NETLINK_CB(skb).eff_cap, msg_type);
        if (err)
  
        pid  = NETLINK_CREDS(skb)->pid;
        uid  = NETLINK_CREDS(skb)->uid;
 +      loginuid = NETLINK_CB(skb).loginuid;
        seq  = nlh->nlmsg_seq;
        data = NLMSG_DATA(nlh);
  
                        return -EINVAL;
                status_get   = (struct audit_status *)data;
                if (status_get->mask & AUDIT_STATUS_ENABLED) {
 -                      err = audit_set_enabled(status_get->enabled);
 +                      err = audit_set_enabled(status_get->enabled, loginuid);
                        if (err < 0) return err;
                }
                if (status_get->mask & AUDIT_STATUS_FAILURE) {
 -                      err = audit_set_failure(status_get->failure);
 +                      err = audit_set_failure(status_get->failure, loginuid);
                        if (err < 0) return err;
                }
                if (status_get->mask & AUDIT_STATUS_PID) {
                        int old   = audit_pid;
                        audit_pid = status_get->pid;
 -                      audit_log(current->audit_context,
 -                                "audit_pid=%d old=%d", audit_pid, old);
 +                      audit_log(NULL, "audit_pid=%d old=%d by auid %u",
 +                                audit_pid, old, loginuid);
                }
                if (status_get->mask & AUDIT_STATUS_RATE_LIMIT)
 -                      audit_set_rate_limit(status_get->rate_limit);
 +                      audit_set_rate_limit(status_get->rate_limit, loginuid);
                if (status_get->mask & AUDIT_STATUS_BACKLOG_LIMIT)
 -                      audit_set_backlog_limit(status_get->backlog_limit);
 +                      audit_set_backlog_limit(status_get->backlog_limit,
 +                                                      loginuid);
                break;
        case AUDIT_USER:
                ab = audit_log_start(NULL);
                if (!ab)
                        break;  /* audit_panic has been called */
                audit_log_format(ab,
 -                               "user pid=%d uid=%d length=%d msg='%.1024s'",
 +                               "user pid=%d uid=%d length=%d loginuid=%u"
 +                               " msg='%.1024s'",
                                 pid, uid,
                                 (int)(nlh->nlmsg_len
                                       - ((char *)data - (char *)nlh)),
 -                               (char *)data);
 +                               loginuid, (char *)data);
                ab->type = AUDIT_USER;
                ab->pid  = pid;
                audit_log_end(ab);
        case AUDIT_LIST:
  #ifdef CONFIG_AUDITSYSCALL
                err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid,
 -                                         uid, seq, data);
 +                                         uid, seq, data, loginuid);
  #else
                err = -EOPNOTSUPP;
  #endif
  /* Get message from skb (based on rtnetlink_rcv_skb).  Each message is
   * processed by audit_receive_msg.  Malformed skbs with wrong length are
   * discarded silently.  */
- static int audit_receive_skb(struct sk_buff *skb)
+ static void audit_receive_skb(struct sk_buff *skb)
  {
        int             err;
        struct nlmsghdr *nlh;
        while (skb->len >= NLMSG_SPACE(0)) {
                nlh = (struct nlmsghdr *)skb->data;
                if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len)
-                       return 0;
+                       return;
                rlen = NLMSG_ALIGN(nlh->nlmsg_len);
                if (rlen > skb->len)
                        rlen = skb->len;
                        netlink_ack(skb, nlh, 0);
                skb_pull(skb, rlen);
        }
-       return 0;
  }
  
  /* Receive messages from netlink socket. */
  static void audit_receive(struct sock *sk, int length)
  {
        struct sk_buff  *skb;
+       unsigned int qlen;
  
-       if (down_trylock(&audit_netlink_sem))
-               return;
+       down(&audit_netlink_sem);
  
-                               /* FIXME: this must not cause starvation */
-       while ((skb = skb_dequeue(&sk->sk_receive_queue))) {
-               if (audit_receive_skb(skb) && skb->len)
-                       skb_queue_head(&sk->sk_receive_queue, skb);
-               else
-                       kfree_skb(skb);
+       for (qlen = skb_queue_len(&sk->sk_receive_queue); qlen; qlen--) {
+               skb = skb_dequeue(&sk->sk_receive_queue);
+               audit_receive_skb(skb);
+               kfree_skb(skb);
        }
        up(&audit_netlink_sem);
  }
@@@ -486,7 -480,7 +483,7 @@@ static void audit_log_move(struct audit
        if (ab->len == 0)
                return;
  
 -      skb = skb_peek(&ab->sklist);
 +      skb = skb_peek_tail(&ab->sklist);
        if (!skb || skb_tailroom(skb) <= ab->len + extra) {
                skb = alloc_skb(2 * ab->len + extra, GFP_ATOMIC);
                if (!skb) {
@@@ -525,9 -519,9 +522,9 @@@ static inline int audit_log_drain(struc
                        retval = netlink_unicast(audit_sock, skb, audit_pid,
                                                 MSG_DONTWAIT);
                }
 -              if (retval == -EAGAIN && ab->count < 5) {
 -                      ++ab->count;
 -                      skb_queue_tail(&ab->sklist, skb);
 +              if (retval == -EAGAIN &&
 +                  (atomic_read(&audit_backlog)) < audit_backlog_limit) {
 +                      skb_queue_head(&ab->sklist, skb);
                        audit_log_end_irq(ab);
                        return 1;
                }
                if (!audit_pid) { /* No daemon */
                        int offset = ab->nlh ? NLMSG_SPACE(0) : 0;
                        int len    = skb->len - offset;
 -                      printk(KERN_ERR "%*.*s\n",
 -                             len, len, skb->data + offset);
 +                      skb->data[offset + len] = '\0';
 +                      printk(KERN_ERR "%s\n", skb->data + offset);
                }
                kfree_skb(skb);
                ab->nlh = NULL;
@@@ -623,7 -617,7 +620,7 @@@ struct audit_buffer *audit_log_start(st
        struct audit_buffer     *ab     = NULL;
        unsigned long           flags;
        struct timespec         t;
 -      int                     serial  = 0;
 +      unsigned int            serial;
  
        if (!audit_initialized)
                return NULL;
        ab->total = 0;
        ab->type  = AUDIT_KERNEL;
        ab->pid   = 0;
 -      ab->count = 0;
  
  #ifdef CONFIG_AUDITSYSCALL
        if (ab->ctx)
                audit_get_stamp(ab->ctx, &t, &serial);
        else
  #endif
 +      {
                t = CURRENT_TIME;
 -
 +              serial = 0;
 +      }
        audit_log_format(ab, "audit(%lu.%03lu:%u): ",
                         t.tv_sec, t.tv_nsec/1000000, serial);
        return ab;
@@@ -724,29 -717,6 +721,29 @@@ void audit_log_format(struct audit_buff
        va_end(args);
  }
  
 +void audit_log_hex(struct audit_buffer *ab, const unsigned char *buf, size_t len)
 +{
 +      int i;
 +
 +      for (i=0; i<len; i++)
 +              audit_log_format(ab, "%02x", buf[i]);
 +}
 +
 +void audit_log_untrustedstring(struct audit_buffer *ab, const char *string)
 +{
 +      const unsigned char *p = string;
 +
 +      while (*p) {
 +              if (*p == '"' || *p == ' ' || *p < 0x20 || *p > 0x7f) {
 +                      audit_log_hex(ab, string, strlen(string));
 +                      return;
 +              }
 +              p++;
 +      }
 +      audit_log_format(ab, "\"%s\"", string);
 +}
 +
 +
  /* This is a helper-function to print the d_path without using a static
   * buffer or allocating another buffer in addition to the one in
   * audit_buffer. */
diff --combined net/netlink/af_netlink.c
index 379ed06e60a37d852390d2bbdc67422fce369c6c,4ee392066148e771925f601c5159f6d0960776af..733bf52cef3e72c663a9f4bc7f90cecab421c706
@@@ -49,8 -49,6 +49,8 @@@
  #include <linux/bitops.h>
  #include <linux/mm.h>
  #include <linux/types.h>
 +#include <linux/audit.h>
 +
  #include <net/sock.h>
  #include <net/scm.h>
  
@@@ -375,7 -373,6 +375,6 @@@ static int netlink_release(struct socke
                nlk->cb->done(nlk->cb);
                netlink_destroy_callback(nlk->cb);
                nlk->cb = NULL;
-               __sock_put(sk);
        }
        spin_unlock(&nlk->cb_lock);
  
@@@ -907,7 -904,6 +906,7 @@@ static int netlink_sendmsg(struct kioc
        NETLINK_CB(skb).groups  = nlk->groups;
        NETLINK_CB(skb).dst_pid = dst_pid;
        NETLINK_CB(skb).dst_groups = dst_groups;
 +      NETLINK_CB(skb).loginuid = audit_get_loginuid(current->audit_context);
        memcpy(NETLINK_CREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
  
        /* What can I do? Netlink is asynchronous, so that
@@@ -1102,7 -1098,6 +1101,6 @@@ static int netlink_dump(struct sock *sk
        spin_unlock(&nlk->cb_lock);
  
        netlink_destroy_callback(cb);
-       __sock_put(sk);
        return 0;
  }
  
@@@ -1141,7 -1136,6 +1139,6 @@@ int netlink_dump_start(struct sock *ssk
                return -EBUSY;
        }
        nlk->cb = cb;
-       sock_hold(sk);
        spin_unlock(&nlk->cb_lock);
  
        netlink_dump(sk);