audit: add an option to control logging of passwords with pam_tty_audit
authorRichard Guy Briggs <rgb@redhat.com>
Fri, 3 May 2013 18:03:50 +0000 (14:03 -0400)
committerEric Paris <eparis@redhat.com>
Tue, 30 Apr 2013 19:31:28 +0000 (15:31 -0400)
Most commands are entered one line at a time and processed as complete lines
in non-canonical mode.  Commands that interactively require a password, enter
canonical mode to do this while shutting off echo.  This pair of features
(icanon and !echo) can be used to avoid logging passwords by audit while still
logging the rest of the command.

Adding a member (log_passwd) to the struct audit_tty_status passed in by
pam_tty_audit allows control of canonical mode without echo per task.

Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
Signed-off-by: Eric Paris <eparis@redhat.com>
drivers/tty/tty_audit.c
include/linux/sched.h
include/uapi/linux/audit.h
kernel/audit.c

index 755d418019c8850b2a3688d875fc042a9ceaad59..5f3868202183f8fd76870447cfc73f4039455b76 100644 (file)
@@ -138,6 +138,7 @@ void tty_audit_fork(struct signal_struct *sig)
 
        spin_lock_irqsave(&current->sighand->siglock, flags);
        sig->audit_tty = current->signal->audit_tty;
+       sig->audit_tty_log_passwd = current->signal->audit_tty_log_passwd;
        spin_unlock_irqrestore(&current->sighand->siglock, flags);
 }
 
@@ -275,10 +276,18 @@ void tty_audit_add_data(struct tty_struct *tty, unsigned char *data,
 {
        struct tty_audit_buf *buf;
        int major, minor;
+       int audit_log_tty_passwd;
+       unsigned long flags;
 
        if (unlikely(size == 0))
                return;
 
+       spin_lock_irqsave(&current->sighand->siglock, flags);
+       audit_log_tty_passwd = current->signal->audit_tty_log_passwd;
+       spin_unlock_irqrestore(&current->sighand->siglock, flags);
+       if (!audit_log_tty_passwd && icanon && !L_ECHO(tty))
+               return;
+
        if (tty->driver->type == TTY_DRIVER_TYPE_PTY
            && tty->driver->subtype == PTY_TYPE_MASTER)
                return;
index d2112477ff5e0ed9a942c9698cbf8549e6087a9c..c4689fe92864fc9fa5fbe55004bdb939eee41263 100644 (file)
@@ -641,6 +641,7 @@ struct signal_struct {
 #endif
 #ifdef CONFIG_AUDIT
        unsigned audit_tty;
+       unsigned audit_tty_log_passwd;
        struct tty_audit_buf *tty_audit_buf;
 #endif
 #ifdef CONFIG_CGROUPS
index 9f096f1c0907b7056bcbe396783fdb2237724a65..c058c24b97ac053a8ed7b05c5ee90df54811f7c2 100644 (file)
@@ -369,7 +369,8 @@ struct audit_status {
 };
 
 struct audit_tty_status {
-       __u32           enabled; /* 1 = enabled, 0 = disabled */
+       __u32           enabled;        /* 1 = enabled, 0 = disabled */
+       __u32           log_passwd;     /* 1 = enabled, 0 = disabled */
 };
 
 /* audit_rule_data supports filter rules with both integer and string
index 241aa8593fa875efcd0ec3bd6caaad8b1d9eb5fb..998a0d4155cfdf49384689644facc0f3e1f6930b 100644 (file)
@@ -49,6 +49,7 @@
 #include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/kthread.h>
+#include <linux/kernel.h>
 
 #include <linux/audit.h>
 
@@ -808,6 +809,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 
                spin_lock_irqsave(&tsk->sighand->siglock, flags);
                s.enabled = tsk->signal->audit_tty != 0;
+               s.log_passwd = tsk->signal->audit_tty_log_passwd;
                spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
 
                audit_send_reply(NETLINK_CB(skb).portid, seq,
@@ -815,18 +817,20 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                break;
        }
        case AUDIT_TTY_SET: {
-               struct audit_tty_status *s;
+               struct audit_tty_status s;
                struct task_struct *tsk = current;
                unsigned long flags;
 
-               if (nlh->nlmsg_len < sizeof(struct audit_tty_status))
-                       return -EINVAL;
-               s = data;
-               if (s->enabled != 0 && s->enabled != 1)
+               memset(&s, 0, sizeof(s));
+               /* guard against past and future API changes */
+               memcpy(&s, data, min(sizeof(s), (size_t)nlh->nlmsg_len));
+               if ((s.enabled != 0 && s.enabled != 1) ||
+                   (s.log_passwd != 0 && s.log_passwd != 1))
                        return -EINVAL;
 
                spin_lock_irqsave(&tsk->sighand->siglock, flags);
-               tsk->signal->audit_tty = s->enabled != 0;
+               tsk->signal->audit_tty = s.enabled;
+               tsk->signal->audit_tty_log_passwd = s.log_passwd;
                spin_unlock_irqrestore(&tsk->sighand->siglock, flags);
                break;
        }