[PATCH] Race-free auditd shutdown credentials

Chris Wright chrisw at osdl.org
Tue Apr 26 21:53:36 UTC 2005


* Steve Grubb (sgrubb at redhat.com) wrote:
> 
> The attached patch addresses the problem with getting the shutdown information 
> in a race-free way. It creates a new message type AUDIT_TERM_INFO, which is 
> used by the audit daemon to query who issued the shutdown. It requires the 
> placement of a hook function that gathers the information.

Heh, I was going to suggest something like this.  However, I was
thinking it'd be an skb queued up, ready to go once asked for.

> diff -urB linux-2.6.9.orig/include/linux/audit.h linux-2.6.9/include/linux/audit.h
> --- linux-2.6.9.orig/include/linux/audit.h	2005-04-26 15:41:58.000000000 -0400
> +++ linux-2.6.9/include/linux/audit.h	2005-04-26 16:09:46.000000000 -0400
> @@ -38,6 +38,7 @@
>  #define AUDIT_WATCH_INS		1007 /* Insert file/dir watch entry */
>  #define AUDIT_WATCH_REM		1008 /* Remove file/dir watch entry */
>  #define AUDIT_WATCH_LIST	1009 /* List all watches */
> +#define AUDIT_TERM_INFO		1010 /* Get termination information */
>  #define AUDIT_KERNEL		2000 /* Asynchronous audit record. NOT A REQUEST. */
>  
>  /* Rule flags */
> @@ -201,6 +202,11 @@
>  
>  };
>  
> +struct audit_term_info {
> +	uid_t		uid;
> +	pid_t		pid;
> +};
> +
>  struct audit_buffer;
>  struct audit_context;
>  struct inode;
> @@ -297,6 +303,7 @@
>  					     int done, int multi,
>  					     void *payload, int size);
>  extern void		    audit_log_lost(const char *message);
> +extern void		    audit_kill_info(int sig, struct task_struct *t);
>  #else
>  #define audit_log(t,f,...) do { ; } while (0)
>  #define audit_log_start(t) ({ NULL; })
> @@ -312,6 +319,7 @@
>  #define audit_set_backlog_limit(l) do { ; } while (0)
>  #define audit_set_enabled(s) do { ; } while (0)
>  #define audit_set_failure(s) do { ; } while (0)
> +#define audit_kill_info(s,t) do { ; } while (0)
>  #endif
>  #endif
>  #endif
> diff -urB linux-2.6.9.orig/kernel/audit.c linux-2.6.9/kernel/audit.c
> --- linux-2.6.9.orig/kernel/audit.c	2005-04-26 15:42:00.000000000 -0400
> +++ linux-2.6.9/kernel/audit.c	2005-04-26 16:09:46.000000000 -0400
> @@ -68,7 +68,7 @@
>  
>  /* If audit records are to be written to the netlink socket, audit_pid
>   * contains the (non-zero) pid. */
> -static int	audit_pid;
> +int		audit_pid;
>  
>  /* If audit_limit is non-zero, limit the rate of sending audit records
>   * to that number per second.  This prevents DoS attacks, but results in
> @@ -79,6 +79,10 @@
>  static int	audit_backlog_limit = 64;
>  static atomic_t	audit_backlog	    = ATOMIC_INIT(0);
>  
> +/* The identity of the user shutting down the audit system. */
> +uid_t		audit_kill_uid;
> +pid_t		audit_kill_pid;

This is not race free.

> +
>  /* Records can be lost in several ways:
>     0) [suppressed in audit_alloc]
>     1) out of memory in audit_log_start [kmalloc of struct audit_buffer]
> @@ -320,6 +324,7 @@
>  	case AUDIT_DEL:
>  	case AUDIT_WATCH_INS:
>  	case AUDIT_WATCH_REM:
> +	case AUDIT_TERM_INFO:
>  		if (!cap_raised(eff_cap, CAP_AUDIT_CONTROL))
>  			err = -EPERM;
>  		break;
> @@ -343,6 +348,7 @@
>  	struct audit_buffer	*ab;
>  	u16			msg_type = nlh->nlmsg_type;
>  	uid_t			loginuid; /* loginuid of sender */
> +	struct audit_term_info  term_data;
>  
>  	err = audit_netlink_ok(NETLINK_CB(skb).eff_cap, msg_type);
>  	if (err)
> @@ -429,6 +435,12 @@
>  					  NETLINK_CB(skb).pid,
>  					  uid, seq, data);
>  		break;
> +	case AUDIT_TERM_INFO:
> +		term_data.uid = audit_kill_uid;
> +		term_data.pid = audit_kill_pid;
> +		audit_send_reply(NETLINK_CB(skb).pid, seq, AUDIT_TERM_INFO, 
> +				0, 0, &term_data, sizeof(term_data));
> +		break;
>  	default:
>  		err = -EINVAL;
>  		break;
> @@ -572,6 +584,8 @@
>  		audit_panic("cannot initialize netlink socket");
>  
>  	audit_initialized = 1;
> +	audit_kill_uid = -1;
> +	audit_kill_pid = -1;
>  	audit_enabled = audit_default;
>  	audit_filesystem_init();
>  	audit_log(NULL, "initialized");
> diff -urB linux-2.6.9.orig/kernel/auditsc.c linux-2.6.9/kernel/auditsc.c
> --- linux-2.6.9.orig/kernel/auditsc.c	2005-04-26 15:42:00.000000000 -0400
> +++ linux-2.6.9/kernel/auditsc.c	2005-04-26 16:09:46.000000000 -0400
> @@ -1134,3 +1134,22 @@
>  audit_notify_watch_exit:
>  	return ret;
>  }
> +
> +void audit_kill_info(int sig, struct task_struct *t)
> +{
> +	extern pid_t audit_kill_pid;
> +	extern uid_t audit_kill_uid;
> +	extern int audit_pid;
> +
> +	if (unlikely(audit_pid && t->pid == audit_pid)) {
> +		if (sig == SIGTERM || sig == SIGKILL) {
> +			struct audit_context *ctx = current->audit_context;
> +			audit_kill_pid = current->pid;
> +			if (ctx)
> +				audit_kill_uid = ctx->loginuid;
> +			else
> +				audit_kill_uid = current->uid;
> +		}

Two threads can race and give inconsistent results here.

> +	}
> +}
> +
> diff -urB linux-2.6.9.orig/kernel/signal.c linux-2.6.9/kernel/signal.c
> --- linux-2.6.9.orig/kernel/signal.c	2005-04-26 15:42:00.000000000 -0400
> +++ linux-2.6.9/kernel/signal.c	2005-04-26 16:43:19.000000000 -0400
> @@ -21,6 +21,7 @@
>  #include <linux/binfmts.h>
>  #include <linux/security.h>
>  #include <linux/ptrace.h>
> +#include <linux/audit.h>
>  #include <asm/param.h>
>  #include <asm/uaccess.h>
>  #include <asm/unistd.h>
> @@ -623,6 +624,10 @@
>  	int error = -EINVAL;
>  	if (sig < 0 || sig > _NSIG)
>  		return error;
> +
> +	/* Let audit system examine the signal */
> +	audit_kill_info(sig, t);

This is not secure, and the data isn't queued, so anybody can reset
these values.

> +
>  	error = -EPERM;
>  	if ((!info || ((unsigned long)info != 1 &&
>  			(unsigned long)info != 2 && SI_FROMUSER(info)))
> diff -urB linux-2.6.9.orig/security/selinux/nlmsgtab.c linux-2.6.9/security/selinux/nlmsgtab.c
> --- linux-2.6.9.orig/security/selinux/nlmsgtab.c	2005-04-26 15:42:02.000000000 -0400
> +++ linux-2.6.9/security/selinux/nlmsgtab.c	2005-04-26 16:09:46.000000000 -0400
> @@ -97,6 +97,7 @@
>  	{ AUDIT_WATCH_INS,	NETLINK_AUDIT_SOCKET__NLMSG_WRITE },
>  	{ AUDIT_WATCH_REM,	NETLINK_AUDIT_SOCKET__NLMSG_WRITE },
>  	{ AUDIT_WATCH_LIST,	NETLINK_AUDIT_SOCKET__NLMSG_READPRIV },
> +	{ AUDIT_TERM_INFO,	NETLINK_AUDIT_SOCKET__NLMSG_READ  },
>  };
>  
>  




More information about the Linux-audit mailing list