OSDN Git Service

Merge branch 'stable-4.6' of git://git.infradead.org/users/pcmoore/audit
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 20 Mar 2016 00:52:49 +0000 (17:52 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 20 Mar 2016 00:52:49 +0000 (17:52 -0700)
Pull audit updates from Paul Moore:
 "A small set of patches for audit this time; just three in total and
  one is a spelling fix.

  The two patches with actual content are designed to help prevent new
  instances of auditd from displacing an existing, functioning auditd
  and to generate a log of the attempt.  Not to worry, dead/stuck auditd
  instances can still be replaced by a new instance without problem.

  Nothing controversial, and everything passes our regression suite"

* 'stable-4.6' of git://git.infradead.org/users/pcmoore/audit:
  audit: Fix typo in comment
  audit: log failed attempts to change audit_pid configuration
  audit: stop an old auditd being starved out by a new auditd

1  2 
kernel/audit.c
kernel/audit_watch.c

diff --combined kernel/audit.c
@@@ -809,6 -809,16 +809,16 @@@ static int audit_set_feature(struct sk_
        return 0;
  }
  
+ static int audit_replace(pid_t pid)
+ {
+       struct sk_buff *skb = audit_make_reply(0, 0, AUDIT_REPLACE, 0, 0,
+                                              &pid, sizeof(pid));
+       if (!skb)
+               return -ENOMEM;
+       return netlink_unicast(audit_sock, skb, audit_nlk_portid, 0);
+ }
  static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
  {
        u32                     seq;
                }
                if (s.mask & AUDIT_STATUS_PID) {
                        int new_pid = s.pid;
+                       pid_t requesting_pid = task_tgid_vnr(current);
  
-                       if ((!new_pid) && (task_tgid_vnr(current) != audit_pid))
+                       if ((!new_pid) && (requesting_pid != audit_pid)) {
+                               audit_log_config_change("audit_pid", new_pid, audit_pid, 0);
                                return -EACCES;
+                       }
+                       if (audit_pid && new_pid &&
+                           audit_replace(requesting_pid) != -ECONNREFUSED) {
+                               audit_log_config_change("audit_pid", new_pid, audit_pid, 0);
+                               return -EEXIST;
+                       }
                        if (audit_enabled != AUDIT_OFF)
                                audit_log_config_change("audit_pid", new_pid, audit_pid, 1);
                        audit_pid = new_pid;
                if (err == 1) { /* match or error */
                        err = 0;
                        if (msg_type == AUDIT_USER_TTY) {
 -                              err = tty_audit_push_current();
 +                              err = tty_audit_push();
                                if (err)
                                        break;
                        }
                break;
        case AUDIT_TTY_GET: {
                struct audit_tty_status s;
 -              struct task_struct *tsk = current;
 +              unsigned int t;
  
 -              spin_lock(&tsk->sighand->siglock);
 -              s.enabled = tsk->signal->audit_tty;
 -              s.log_passwd = tsk->signal->audit_tty_log_passwd;
 -              spin_unlock(&tsk->sighand->siglock);
 +              t = READ_ONCE(current->signal->audit_tty);
 +              s.enabled = t & AUDIT_TTY_ENABLE;
 +              s.log_passwd = !!(t & AUDIT_TTY_LOG_PASSWD);
  
                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;
 +              unsigned int t;
  
                memset(&s, 0, sizeof(s));
                /* guard against past and future API changes */
                    (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;
 +              if (err)
 +                      t = READ_ONCE(current->signal->audit_tty);
 +              else {
 +                      t = s.enabled | (-s.log_passwd & AUDIT_TTY_LOG_PASSWD);
 +                      t = xchg(&current->signal->audit_tty, t);
                }
 -              spin_unlock(&tsk->sighand->siglock);
 +              old.enabled = t & AUDIT_TTY_ENABLE;
 +              old.log_passwd = !!(t & AUDIT_TTY_LOG_PASSWD);
  
                audit_log_common_recv_msg(&ab, AUDIT_CONFIG_CHANGE);
                audit_log_format(ab, " op=tty_set old-enabled=%d new-enabled=%d"
@@@ -1718,7 -1737,7 +1736,7 @@@ static inline int audit_copy_fcaps(stru
  
  /* Copy inode data into an audit_names. */
  void audit_copy_inode(struct audit_names *name, const struct dentry *dentry,
 -                    const struct inode *inode)
 +                    struct inode *inode)
  {
        name->ino   = inode->i_ino;
        name->dev   = inode->i_sb->s_dev;
diff --combined kernel/audit_watch.c
@@@ -185,7 -185,7 +185,7 @@@ static struct audit_watch *audit_init_w
        return watch;
  }
  
- /* Translate a watch string to kernel respresentation. */
+ /* Translate a watch string to kernel representation. */
  int audit_to_watch(struct audit_krule *krule, char *path, int len, u32 op)
  {
        struct audit_watch *watch;
@@@ -364,7 -364,7 +364,7 @@@ static int audit_get_nd(struct audit_wa
        struct dentry *d = kern_path_locked(watch->path, parent);
        if (IS_ERR(d))
                return PTR_ERR(d);
 -      mutex_unlock(&d_backing_inode(parent->dentry)->i_mutex);
 +      inode_unlock(d_backing_inode(parent->dentry));
        if (d_is_positive(d)) {
                /* update watch filter fields */
                watch->dev = d_backing_inode(d)->i_sb->s_dev;