The tty termios bits cannot change while n_tty_read() is in the
 i/o loop; the termios_rwsem ensures mutual exclusion with termios
 changes in n_tty_set_termios(). Check L_ICANON() directly and
 eliminate icanon parameter.
 
 NB: tty_audit_add_data() => tty_audit_buf_get() => tty_audit_buf_alloc()
 is a single path; ie., tty_audit_buf_get() and tty_audit_buf_alloc()
 have no other callers. 
 Signed-off-by: Peter Hurley <peter(a)hurleysoftware.com>
 ---
  drivers/tty/n_tty.c     |  6 +++---
  drivers/tty/tty_audit.c | 22 +++++++++-------------
  include/linux/tty.h     |  4 ++--
  3 files changed, 14 insertions(+), 18 deletions(-)
 
 diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
 index b09c0c1..a3ad312 100644
 --- a/drivers/tty/n_tty.c
 +++ b/drivers/tty/n_tty.c
 @@ -163,7 +163,7 @@ static int tty_copy_to_user(struct tty_struct *tty, void __user *to,
  	int uncopied;
  
  	if (n > size) {
 -		tty_audit_add_data(tty, from, size, ldata->icanon);
 +		tty_audit_add_data(tty, from, size);
  		uncopied = copy_to_user(to, from, size);
  		if (uncopied)
  			return uncopied;
 @@ -172,7 +172,7 @@ static int tty_copy_to_user(struct tty_struct *tty, void __user *to,
  		from = ldata->read_buf;
  	}
  
 -	tty_audit_add_data(tty, from, n, ldata->icanon);
 +	tty_audit_add_data(tty, from, n);
  	return copy_to_user(to, from, n);
  }
  
 @@ -2008,7 +2008,7 @@ static int copy_from_read_buf(struct tty_struct *tty,
  		retval = copy_to_user(*b, from, n);
  		n -= retval;
  		is_eof = n == 1 && *from == EOF_CHAR(tty);
 -		tty_audit_add_data(tty, from, n, ldata->icanon);
 +		tty_audit_add_data(tty, from, n);
  		smp_store_release(&ldata->read_tail, ldata->read_tail + n);
  		/* Turn single EOF into zero-length read */
  		if (L_EXTPROC(tty) && ldata->icanon && is_eof &&
 diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c
 index ead924e..d2a004a 100644
 --- a/drivers/tty/tty_audit.c
 +++ b/drivers/tty/tty_audit.c
 @@ -22,8 +22,7 @@ struct tty_audit_buf {
  	unsigned char *data;	/* Allocated size N_TTY_BUF_SIZE */
  };
  
 -static struct tty_audit_buf *tty_audit_buf_alloc(int major, int minor,
 -						 unsigned icanon)
 +static struct tty_audit_buf *tty_audit_buf_alloc(struct tty_struct *tty)
  {
  	struct tty_audit_buf *buf;
  
 @@ -35,9 +34,9 @@ static struct tty_audit_buf *tty_audit_buf_alloc(int major, int minor,
  		goto err_buf;
  	atomic_set(&buf->count, 1);
  	mutex_init(&buf->mutex);
 -	buf->major = major;
 -	buf->minor = minor;
 -	buf->icanon = icanon;
 +	buf->major = tty->driver->major;
 +	buf->minor = tty->driver->minor_start + tty->index;
 +	buf->icanon = !!L_ICANON(tty);
  	buf->valid = 0;
  	return buf;
  
 @@ -216,8 +215,7 @@ int tty_audit_push_current(void)
   *	if TTY auditing is disabled or out of memory.  Otherwise, return a new
   *	reference to the buffer.
   */
 -static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty,
 -		unsigned icanon)
 +static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct *tty)
  {
  	struct tty_audit_buf *buf, *buf2;
  	unsigned long flags;
 @@ -234,9 +232,7 @@ static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct
*tty,
  	}
  	spin_unlock_irqrestore(¤t->sighand->siglock, flags);
  
 -	buf2 = tty_audit_buf_alloc(tty->driver->major,
 -				   tty->driver->minor_start + tty->index,
 -				   icanon);
 +	buf2 = tty_audit_buf_alloc(tty);
  	if (buf2 == NULL) {
  		audit_log_lost("out of memory in TTY auditing");
  		return NULL;
 @@ -265,13 +261,13 @@ static struct tty_audit_buf *tty_audit_buf_get(struct tty_struct
*tty,
   *
   *	Audit @data of @size from @tty, if necessary.
   */
 -void tty_audit_add_data(struct tty_struct *tty, const void *data,
 -			size_t size, unsigned icanon)
 +void tty_audit_add_data(struct tty_struct *tty, const void *data, size_t size)
  {
  	struct tty_audit_buf *buf;
  	int major, minor;
  	int audit_log_tty_passwd;
  	unsigned long flags;
 +	unsigned int icanon = !!L_ICANON(tty);
  
  	if (unlikely(size == 0))
  		return;
 @@ -286,7 +282,7 @@ void tty_audit_add_data(struct tty_struct *tty, const void *data,
  	if (!audit_log_tty_passwd && icanon && !L_ECHO(tty))
  		return;
  
 -	buf = tty_audit_buf_get(tty, icanon);
 +	buf = tty_audit_buf_get(tty);
  	if (!buf)
  		return;
  
 diff --git a/include/linux/tty.h b/include/linux/tty.h
 index 70f3a9c1..f8a20a8 100644
 --- a/include/linux/tty.h
 +++ b/include/linux/tty.h
 @@ -603,7 +603,7 @@ extern void n_tty_inherit_ops(struct tty_ldisc_ops *ops);
  /* 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);
 @@ -611,7 +611,7 @@ extern void tty_audit_push(struct tty_struct *tty);
  extern int tty_audit_push_current(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)
 -- 
 2.6.3
 
 --
 Linux-audit mailing list
 Linux-audit(a)redhat.com
 
https://www.redhat.com/mailman/listinfo/linux-audit 
- RGB
--
Richard Guy Briggs <rbriggs(a)redhat.com>
Senior Software Engineer, Kernel Security, AMER ENG Base Operating Systems, Red Hat
Remote, Ottawa, Canada
Voice: +1.647.777.2635, Internal: (81) 32635, Alt: +1.613.693.0684x3545