]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge branch 'stable-4.7' of git://git.infradead.org/users/pcmoore/audit
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 19 May 2016 01:46:55 +0000 (18:46 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 19 May 2016 01:46:55 +0000 (18:46 -0700)
Pull audit updates from Paul Moore:
 "Four small audit patches for 4.7.

  Two are simple cleanups around the audit thread management code, one
  adds a tty field to AUDIT_LOGIN events, and the final patch makes
  tty_name() usable regardless of CONFIG_TTY.

  Nothing controversial, and it all passes our regression test"

* 'stable-4.7' of git://git.infradead.org/users/pcmoore/audit:
  tty: provide tty_name() even without CONFIG_TTY
  audit: add tty field to LOGIN event
  audit: we don't need to __set_current_state(TASK_RUNNING)
  audit: cleanup prune_tree_thread

1  2 
include/linux/audit.h
include/linux/tty.h
kernel/audit.c
kernel/auditsc.c

diff --combined include/linux/audit.h
index e38e3fc13ea8764a66d4c84a6dea1bee3f4e630b,32cdafb312d88a7984eeba69a06db183275ac591..961a417d641e5221264e75b4d987fc3015607d41
@@@ -26,6 -26,7 +26,7 @@@
  #include <linux/sched.h>
  #include <linux/ptrace.h>
  #include <uapi/linux/audit.h>
+ #include <linux/tty.h>
  
  #define AUDIT_INO_UNSET ((unsigned long)-1)
  #define AUDIT_DEV_UNSET ((dev_t)-1)
@@@ -109,10 -110,6 +110,10 @@@ extern int audit_classify_compat_syscal
  /* maximized args number that audit_socketcall can process */
  #define AUDITSC_ARGS          6
  
 +/* bit values for ->signal->audit_tty */
 +#define AUDIT_TTY_ENABLE      BIT(0)
 +#define AUDIT_TTY_LOG_PASSWD  BIT(1)
 +
  struct filename;
  
  extern void audit_log_session_info(struct audit_buffer *ab);
@@@ -347,6 -344,23 +348,23 @@@ static inline unsigned int audit_get_se
        return tsk->sessionid;
  }
  
+ static inline struct tty_struct *audit_get_tty(struct task_struct *tsk)
+ {
+       struct tty_struct *tty = NULL;
+       unsigned long flags;
+       spin_lock_irqsave(&tsk->sighand->siglock, flags);
+       if (tsk->signal)
+               tty = tty_kref_get(tsk->signal->tty);
+       spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
+       return tty;
+ }
+ static inline void audit_put_tty(struct tty_struct *tty)
+ {
+       tty_kref_put(tty);
+ }
  extern void __audit_ipc_obj(struct kern_ipc_perm *ipcp);
  extern void __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, umode_t mode);
  extern void __audit_bprm(struct linux_binprm *bprm);
@@@ -504,6 -518,12 +522,12 @@@ static inline unsigned int audit_get_se
  {
        return -1;
  }
+ static inline struct tty_struct *audit_get_tty(struct task_struct *tsk)
+ {
+       return NULL;
+ }
+ static inline void audit_put_tty(struct tty_struct *tty)
+ { }
  static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp)
  { }
  static inline void audit_ipc_set_perm(unsigned long qbytes, uid_t uid,
diff --combined include/linux/tty.h
index 3b09f235db6668b932792f32890d0bbee942e8cb,a93cce297832032ffcef76f4b1cee0a8319c86e4..17b247c94440abe0a00c2187b3cc17066a8b9f5e
@@@ -302,7 -302,6 +302,7 @@@ struct tty_struct 
        struct work_struct hangup_work;
        void *disc_data;
        void *driver_data;
 +      spinlock_t files_lock;          /* protects tty_files list */
        struct list_head tty_files;
  
  #define N_TTY_BUF_SIZE 4096
@@@ -337,6 -336,7 +337,6 @@@ struct tty_file_private 
  #define TTY_IO_ERROR          1       /* Cause an I/O error (may be no ldisc too) */
  #define TTY_OTHER_CLOSED      2       /* Other side (if any) has closed */
  #define TTY_EXCLUSIVE                 3       /* Exclusive open mode */
 -#define TTY_DEBUG             4       /* Debugging */
  #define TTY_DO_WRITE_WAKEUP   5       /* Call write_wakeup after queuing new */
  #define TTY_OTHER_DONE                6       /* Closed pty has completed input processing */
  #define TTY_LDISC_OPEN                11      /* Line discipline is open */
@@@ -371,6 -371,7 +371,7 @@@ extern void proc_clear_tty(struct task_
  extern struct tty_struct *get_current_tty(void);
  /* tty_io.c */
  extern int __init tty_init(void);
+ extern const char *tty_name(const struct tty_struct *tty);
  #else
  static inline void console_init(void)
  { }
@@@ -391,6 -392,8 +392,8 @@@ static inline struct tty_struct *get_cu
  /* tty_io.c */
  static inline int __init tty_init(void)
  { return 0; }
+ static inline const char *tty_name(const struct tty_struct *tty)
+ { return "(none)"; }
  #endif
  
  extern struct ktermios tty_std_termios;
@@@ -415,7 -418,6 +418,6 @@@ static inline struct tty_struct *tty_kr
        return tty;
  }
  
- extern const char *tty_name(const struct tty_struct *tty);
  extern const char *tty_driver_name(const struct tty_struct *tty);
  extern void tty_wait_until_sent(struct tty_struct *tty, long timeout);
  extern int __tty_check_change(struct tty_struct *tty, int sig);
@@@ -433,6 -435,8 +435,6 @@@ extern struct device *tty_register_devi
                                void *drvdata,
                                const struct attribute_group **attr_grp);
  extern void tty_unregister_device(struct tty_driver *driver, unsigned index);
 -extern int tty_read_raw_data(struct tty_struct *tty, unsigned char *bufp,
 -                           int buflen);
  extern void tty_write_message(struct tty_struct *tty, char *msg);
  extern int tty_send_xchar(struct tty_struct *tty, char ch);
  extern int tty_put_char(struct tty_struct *tty, unsigned char c);
@@@ -444,7 -448,12 +446,7 @@@ extern void tty_unthrottle(struct tty_s
  extern int tty_throttle_safe(struct tty_struct *tty);
  extern int tty_unthrottle_safe(struct tty_struct *tty);
  extern int tty_do_resize(struct tty_struct *tty, struct winsize *ws);
 -extern void tty_driver_remove_tty(struct tty_driver *driver,
 -                                struct tty_struct *tty);
 -extern void tty_free_termios(struct tty_struct *tty);
  extern int is_current_pgrp_orphaned(void);
 -extern int is_ignored(int sig);
 -extern int tty_signal(int sig, struct tty_struct *tty);
  extern void tty_hangup(struct tty_struct *tty);
  extern void tty_vhangup(struct tty_struct *tty);
  extern int tty_hung_up_p(struct file *filp);
@@@ -486,8 -495,7 +488,8 @@@ extern int tty_set_termios(struct tty_s
  extern struct tty_ldisc *tty_ldisc_ref(struct tty_struct *);
  extern void tty_ldisc_deref(struct tty_ldisc *);
  extern struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *);
 -extern void tty_ldisc_hangup(struct tty_struct *tty);
 +extern void tty_ldisc_hangup(struct tty_struct *tty, bool reset);
 +extern int tty_ldisc_reinit(struct tty_struct *tty, int disc);
  extern const struct file_operations tty_ldiscs_proc_fops;
  
  extern void tty_wakeup(struct tty_struct *tty);
@@@ -502,13 -510,16 +504,13 @@@ extern struct tty_struct *alloc_tty_str
  extern int tty_alloc_file(struct file *file);
  extern void tty_add_file(struct tty_struct *tty, struct file *file);
  extern void tty_free_file(struct file *file);
 -extern void free_tty_struct(struct tty_struct *tty);
 -extern void deinitialize_tty_struct(struct tty_struct *tty);
  extern struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx);
  extern int tty_release(struct inode *inode, struct file *filp);
 -extern int tty_init_termios(struct tty_struct *tty);
 +extern void tty_init_termios(struct tty_struct *tty);
  extern int tty_standard_install(struct tty_driver *driver,
                struct tty_struct *tty);
  
  extern struct mutex tty_mutex;
 -extern spinlock_t tty_files_lock;
  
  #define tty_is_writelocked(tty)  (mutex_is_locked(&tty->atomic_write_lock))
  
@@@ -566,29 -577,43 +568,29 @@@ static inline int tty_port_users(struc
  
  extern int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc);
  extern int tty_unregister_ldisc(int disc);
 -extern int tty_set_ldisc(struct tty_struct *tty, int ldisc);
 +extern int tty_set_ldisc(struct tty_struct *tty, int disc);
  extern int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty);
  extern void tty_ldisc_release(struct tty_struct *tty);
  extern void tty_ldisc_init(struct tty_struct *tty);
  extern void tty_ldisc_deinit(struct tty_struct *tty);
 -extern void tty_ldisc_begin(void);
 -
 -static inline int tty_ldisc_receive_buf(struct tty_ldisc *ld, unsigned char *p,
 -                                      char *f, int count)
 -{
 -      if (ld->ops->receive_buf2)
 -              count = ld->ops->receive_buf2(ld->tty, p, f, count);
 -      else {
 -              count = min_t(int, count, ld->tty->receive_room);
 -              if (count)
 -                      ld->ops->receive_buf(ld->tty, p, f, count);
 -      }
 -      return count;
 -}
 -
 +extern int tty_ldisc_receive_buf(struct tty_ldisc *ld, unsigned char *p,
 +                               char *f, int count);
  
  /* n_tty.c */
 -extern struct tty_ldisc_ops tty_ldisc_N_TTY;
  extern void n_tty_inherit_ops(struct tty_ldisc_ops *ops);
 +extern void __init n_tty_init(void);
  
  /* tty_audit.c */
  #ifdef CONFIG_AUDIT
  extern void tty_audit_add_data(struct tty_struct *tty, const void *data,
 -                             size_t size, unsigned icanon);
 +                             size_t size);
  extern void tty_audit_exit(void);
  extern void tty_audit_fork(struct signal_struct *sig);
  extern void tty_audit_tiocsti(struct tty_struct *tty, char ch);
 -extern void tty_audit_push(struct tty_struct *tty);
 -extern int tty_audit_push_current(void);
 +extern int tty_audit_push(void);
  #else
  static inline void tty_audit_add_data(struct tty_struct *tty, const void *data,
 -                                    size_t size, unsigned icanon)
 +                                    size_t size)
  {
  }
  static inline void tty_audit_tiocsti(struct tty_struct *tty, char ch)
@@@ -600,7 -625,10 +602,7 @@@ static inline void tty_audit_exit(void
  static inline void tty_audit_fork(struct signal_struct *sig)
  {
  }
 -static inline void tty_audit_push(struct tty_struct *tty)
 -{
 -}
 -static inline int tty_audit_push_current(void)
 +static inline int tty_audit_push(void)
  {
        return 0;
  }
@@@ -622,11 -650,11 +624,11 @@@ extern long vt_compat_ioctl(struct tty_
  
  /* tty_mutex.c */
  /* functions for preparation of BKL removal */
 -extern void __lockfunc tty_lock(struct tty_struct *tty);
 +extern void tty_lock(struct tty_struct *tty);
  extern int  tty_lock_interruptible(struct tty_struct *tty);
 -extern void __lockfunc tty_unlock(struct tty_struct *tty);
 -extern void __lockfunc tty_lock_slave(struct tty_struct *tty);
 -extern void __lockfunc tty_unlock_slave(struct tty_struct *tty);
 +extern void tty_unlock(struct tty_struct *tty);
 +extern void tty_lock_slave(struct tty_struct *tty);
 +extern void tty_unlock_slave(struct tty_struct *tty);
  extern void tty_set_lock_subclass(struct tty_struct *tty);
  
  #ifdef CONFIG_PROC_FS
diff --combined kernel/audit.c
index 678c3f000191be66aed944e764209ef5c2924b98,384374a1d232edcec9a2afc5a85693ade95196aa..22bb4f24f071df56dbddcb3f84fbf3ad2e8c63bc
@@@ -64,7 -64,6 +64,6 @@@
  #include <linux/security.h>
  #endif
  #include <linux/freezer.h>
- #include <linux/tty.h>
  #include <linux/pid_namespace.h>
  #include <net/netns/generic.h>
  
@@@ -430,7 -429,6 +429,6 @@@ restart
                                        attempts, audit_pid);
                                set_current_state(TASK_INTERRUPTIBLE);
                                schedule();
-                               __set_current_state(TASK_RUNNING);
                                goto restart;
                        }
                }
@@@ -809,16 -807,6 +807,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"
@@@ -1341,15 -1322,14 +1339,14 @@@ static inline void audit_get_stamp(stru
  static long wait_for_auditd(long 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)
+           skb_queue_len(&audit_skb_queue) > audit_backlog_limit) {
+               add_wait_queue_exclusive(&audit_backlog_wait, &wait);
+               set_current_state(TASK_UNINTERRUPTIBLE);
                sleep_time = schedule_timeout(sleep_time);
-       __set_current_state(TASK_RUNNING);
-       remove_wait_queue(&audit_backlog_wait, &wait);
+               remove_wait_queue(&audit_backlog_wait, &wait);
+       }
  
        return sleep_time;
  }
@@@ -1890,21 -1870,14 +1887,14 @@@ void audit_log_task_info(struct audit_b
  {
        const struct cred *cred;
        char comm[sizeof(tsk->comm)];
-       char *tty;
+       struct tty_struct *tty;
  
        if (!ab)
                return;
  
        /* tsk == current */
        cred = current_cred();
-       spin_lock_irq(&tsk->sighand->siglock);
-       if (tsk->signal && tsk->signal->tty && tsk->signal->tty->name)
-               tty = tsk->signal->tty->name;
-       else
-               tty = "(none)";
-       spin_unlock_irq(&tsk->sighand->siglock);
+       tty = audit_get_tty(tsk);
        audit_log_format(ab,
                         " ppid=%d pid=%d auid=%u uid=%u gid=%u"
                         " euid=%u suid=%u fsuid=%u"
                         from_kgid(&init_user_ns, cred->egid),
                         from_kgid(&init_user_ns, cred->sgid),
                         from_kgid(&init_user_ns, cred->fsgid),
-                        tty, audit_get_sessionid(tsk));
+                        tty ? tty_name(tty) : "(none)",
+                        audit_get_sessionid(tsk));
+       audit_put_tty(tty);
        audit_log_format(ab, " comm=");
        audit_log_untrustedstring(ab, get_task_comm(comm, tsk));
        audit_log_d_path_exe(ab, tsk->mm);
        audit_log_task_context(ab);
  }
diff --combined kernel/auditsc.c
index 7d0e3cf8abe1d687325bc8096368eaba38d9bd0d,71e14d836e69f84d4e53e52a8e9d7280914f930a..62ab53d7619cfb249154276e40a38d1e69a906f6
@@@ -1980,6 -1980,7 +1980,7 @@@ static void audit_log_set_loginuid(kuid
  {
        struct audit_buffer *ab;
        uid_t uid, oldloginuid, loginuid;
+       struct tty_struct *tty;
  
        if (!audit_enabled)
                return;
        uid = from_kuid(&init_user_ns, task_uid(current));
        oldloginuid = from_kuid(&init_user_ns, koldloginuid);
        loginuid = from_kuid(&init_user_ns, kloginuid),
+       tty = audit_get_tty(current);
  
        ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN);
        if (!ab)
                return;
        audit_log_format(ab, "pid=%d uid=%u", task_pid_nr(current), uid);
        audit_log_task_context(ab);
-       audit_log_format(ab, " old-auid=%u auid=%u old-ses=%u ses=%u res=%d",
-                        oldloginuid, loginuid, oldsessionid, sessionid, !rc);
+       audit_log_format(ab, " old-auid=%u auid=%u tty=%s old-ses=%u ses=%u res=%d",
+                        oldloginuid, loginuid, tty ? tty_name(tty) : "(none)",
+                        oldsessionid, sessionid, !rc);
+       audit_put_tty(tty);
        audit_log_end(ab);
  }
  
@@@ -2412,8 -2416,8 +2416,8 @@@ void __audit_seccomp(unsigned long sysc
                return;
        audit_log_task(ab);
        audit_log_format(ab, " sig=%ld arch=%x syscall=%ld compat=%d ip=0x%lx code=0x%x",
 -                       signr, syscall_get_arch(), syscall, is_compat_task(),
 -                       KSTK_EIP(current), code);
 +                       signr, syscall_get_arch(), syscall,
 +                       in_compat_syscall(), KSTK_EIP(current), code);
        audit_log_end(ab);
  }