Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c0404993 authored by Steve Grubb's avatar Steve Grubb Committed by David Woodhouse
Browse files

AUDIT: Add message types to audit records



This patch adds more messages types to the audit subsystem so that audit 
analysis is quicker, intuitive, and more useful.

Signed-off-by: default avatarSteve Grubb <sgrubb@redhat.com>
---
I forgot one type in the big patch. I need to add one for user space 
originating SE Linux avc messages. This is used by dbus and nscd.

-Steve
---
Updated to 2.6.12-rc4-mm1.
-dwmw2

Signed-off-by: default avatarDavid Woodhouse <dwmw2@infradead.org>
parent 9ea74f06
Loading
Loading
Loading
Loading
+50 −16
Original line number Diff line number Diff line
@@ -27,15 +27,53 @@
#include <linux/sched.h>
#include <linux/elf.h>

/* Request and reply types */
/* The netlink messages for the audit system is divided into blocks:
 * 1000 - 1099 are for commanding the audit system
 * 1100 - 1199 user space trusted application messages
 * 1200 - 1299 messages internal to the audit daemon
 * 1300 - 1399 audit event messages
 * 1400 - 1499 SE Linux use
 * 1500 - 1999 future use
 * 2000 is for otherwise unclassified kernel audit messages
 *
 * Messages from 1000-1199 are bi-directional. 1200-1299 are exclusively user
 * space. Anything over that is kernel --> user space communication.
 */
#define AUDIT_GET		1000	/* Get status */
#define AUDIT_SET		1001	/* Set status (enable/disable/auditd) */
#define AUDIT_LIST		1002	/* List filtering rules */
#define AUDIT_ADD		1003	/* Add filtering rule */
#define AUDIT_DEL		1004	/* Delete filtering rule */
#define AUDIT_USER		1005	/* Send a message from user-space */
#define AUDIT_LIST		1002	/* List syscall filtering rules */
#define AUDIT_ADD		1003	/* Add syscall filtering rule */
#define AUDIT_DEL		1004	/* Delete syscall filtering rule */
#define AUDIT_USER		1005	/* Message from userspace -- deprecated */
#define AUDIT_LOGIN		1006	/* Define the login id and information */
#define AUDIT_SIGNAL_INFO	1010	/* Get information about sender of signal*/
#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 file/dir watches */
#define AUDIT_SIGNAL_INFO	1010	/* Get info about sender of signal to auditd */

#define AUDIT_USER_AUTH		1100	/* User space authentication */
#define AUDIT_USER_ACCT		1101	/* User space acct change */
#define AUDIT_USER_MGMT		1102	/* User space acct management */
#define AUDIT_CRED_ACQ		1103	/* User space credential acquired */
#define AUDIT_CRED_DISP		1104	/* User space credential disposed */
#define AUDIT_USER_START	1105	/* User space session start */ 
#define AUDIT_USER_END		1106	/* User space session end */
#define AUDIT_USER_AVC		1107	/* User space avc message */
 
#define AUDIT_DAEMON_START      1200    /* Daemon startup record */
#define AUDIT_DAEMON_END        1201    /* Daemon normal stop record */
#define AUDIT_DAEMON_ABORT      1202    /* Daemon error stop record */
#define AUDIT_DAEMON_CONFIG     1203    /* Daemon config change */

#define AUDIT_SYSCALL		1300	/* Syscall event */
#define AUDIT_FS_WATCH		1301	/* Filesystem watch event */
#define AUDIT_PATH		1302	/* Filname path information */
#define AUDIT_IPC		1303	/* IPC record */
#define AUDIT_SOCKET		1304	/* Socket record */
#define AUDIT_CONFIG_CHANGE	1305	/* Audit system configuration change */

#define AUDIT_AVC		1400	/* SE Linux avc denial or grant */
#define AUDIT_SELINUX_ERR	1401	/* Internal SE Linux Errors */

#define AUDIT_KERNEL		2000	/* Asynchronous audit record. NOT A REQUEST. */

@@ -216,14 +254,11 @@ extern void audit_signal_info(int sig, struct task_struct *t);
#ifdef CONFIG_AUDIT
/* These are defined in audit.c */
				/* Public API */
#define audit_log(ctx, fmt, args...) \
	audit_log_type(ctx, AUDIT_KERNEL, 0, fmt, ##args)
extern void		    audit_log_type(struct audit_context *ctx, int type,
				      int pid, const char *fmt, ...)
			    __attribute__((format(printf,4,5)));
extern void		    audit_log(struct audit_context *ctx, int type,
				      const char *fmt, ...)
			    __attribute__((format(printf,3,4)));

extern struct audit_buffer *audit_log_start(struct audit_context *ctx, int type,
					    int pid);
extern struct audit_buffer *audit_log_start(struct audit_context *ctx,int type);
extern void		    audit_log_format(struct audit_buffer *ab,
					     const char *fmt, ...)
			    __attribute__((format(printf,2,3)));
@@ -243,9 +278,8 @@ extern void audit_send_reply(int pid, int seq, int type,
					     void *payload, int size);
extern void		    audit_log_lost(const char *message);
#else
#define audit_log(c,f,...) do { ; } while (0)
#define audit_log_type(c,t,p,f,...) do { ; } while (0)
#define audit_log_start(c,t,p) ({ NULL; })
#define audit_log(c,t,f,...) do { ; } while (0)
#define audit_log_start(c,t) ({ NULL; })
#define audit_log_vformat(b,f,a) do { ; } while (0)
#define audit_log_format(b,f,...) do { ; } while (0)
#define audit_log_end(b) do { ; } while (0)
+55 −23
Original line number Diff line number Diff line
@@ -140,6 +140,12 @@ struct audit_buffer {
	struct audit_context *ctx;	/* NULL or associated context */
};

static void audit_set_pid(struct audit_buffer *ab, pid_t pid)
{
	struct nlmsghdr *nlh = (struct nlmsghdr *)ab->skb->data;
	nlh->nlmsg_pid = pid;
}

struct audit_entry {
	struct list_head  list;
	struct audit_rule rule;
@@ -233,7 +239,8 @@ static int audit_set_rate_limit(int limit, uid_t loginuid)
{
	int old		 = audit_rate_limit;
	audit_rate_limit = limit;
	audit_log(NULL, "audit_rate_limit=%d old=%d by auid %u",
	audit_log(NULL, AUDIT_CONFIG_CHANGE, 
			"audit_rate_limit=%d old=%d by auid %u",
			audit_rate_limit, old, loginuid);
	return old;
}
@@ -242,7 +249,8 @@ static int audit_set_backlog_limit(int limit, uid_t loginuid)
{
	int old		 = audit_backlog_limit;
	audit_backlog_limit = limit;
	audit_log(NULL, "audit_backlog_limit=%d old=%d by auid %u",
	audit_log(NULL, AUDIT_CONFIG_CHANGE,
			"audit_backlog_limit=%d old=%d by auid %u",
			audit_backlog_limit, old, loginuid);
	return old;
}
@@ -253,7 +261,8 @@ static int audit_set_enabled(int state, uid_t loginuid)
	if (state != 0 && state != 1)
		return -EINVAL;
	audit_enabled = state;
	audit_log(NULL, "audit_enabled=%d old=%d by auid %u",
	audit_log(NULL, AUDIT_CONFIG_CHANGE,
			"audit_enabled=%d old=%d by auid %u",
			audit_enabled, old, loginuid);
	return old;
}
@@ -266,7 +275,8 @@ static int audit_set_failure(int state, uid_t loginuid)
	    && state != AUDIT_FAIL_PANIC)
		return -EINVAL;
	audit_failure = state;
	audit_log(NULL, "audit_failure=%d old=%d by auid %u",
	audit_log(NULL, AUDIT_CONFIG_CHANGE,
			"audit_failure=%d old=%d by auid %u",
			audit_failure, old, loginuid);
	return old;
}
@@ -316,6 +326,14 @@ static int audit_netlink_ok(kernel_cap_t eff_cap, u16 msg_type)
			err = -EPERM;
		break;
	case AUDIT_USER:
	case AUDIT_USER_AUTH:
	case AUDIT_USER_ACCT:
	case AUDIT_USER_MGMT:
	case AUDIT_CRED_ACQ:
	case AUDIT_CRED_DISP:
	case AUDIT_USER_START:
	case AUDIT_USER_END:
	case AUDIT_USER_AVC:
		if (!cap_raised(eff_cap, CAP_AUDIT_WRITE))
			err = -EPERM;
		break;
@@ -332,6 +350,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
	void			*data;
	struct audit_status	*status_get, status_set;
	int			err;
	struct audit_buffer	*ab;
	u16			msg_type = nlh->nlmsg_type;
	uid_t			loginuid; /* loginuid of sender */
	struct audit_sig_info   sig_data;
@@ -373,7 +392,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
		if (status_get->mask & AUDIT_STATUS_PID) {
			int old   = audit_pid;
			audit_pid = status_get->pid;
			audit_log(NULL, "audit_pid=%d old=%d by auid %u",
			audit_log(NULL, AUDIT_CONFIG_CHANGE,
				"audit_pid=%d old=%d by auid %u",
				  audit_pid, old, loginuid);
		}
		if (status_get->mask & AUDIT_STATUS_RATE_LIMIT)
@@ -383,13 +403,26 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
							loginuid);
		break;
	case AUDIT_USER:
		audit_log_type(NULL, AUDIT_USER, pid,
	case AUDIT_USER_AUTH:
	case AUDIT_USER_ACCT:
	case AUDIT_USER_MGMT:
	case AUDIT_CRED_ACQ:
	case AUDIT_CRED_DISP:
	case AUDIT_USER_START:
	case AUDIT_USER_END:
	case AUDIT_USER_AVC:
		ab = audit_log_start(NULL, msg_type);
		if (!ab)
			break;	/* audit_panic has been called */
		audit_log_format(ab,
				 "user pid=%d uid=%d length=%d loginuid=%u"
				 " msg='%.1024s'",
				 pid, uid,
				 (int)(nlh->nlmsg_len
				       - ((char *)data - (char *)nlh)),
				 loginuid, (char *)data);
		audit_set_pid(ab, pid);
		audit_log_end(ab);
		break;
	case AUDIT_ADD:
	case AUDIT_DEL:
@@ -504,7 +537,7 @@ static int __init audit_init(void)

	audit_initialized = 1;
	audit_enabled = audit_default;
	audit_log(NULL, "initialized");
	audit_log(NULL, AUDIT_KERNEL, "initialized");
	return 0;
}
__initcall(audit_init);
@@ -541,10 +574,12 @@ static void audit_buffer_free(struct audit_buffer *ab)
	spin_unlock_irqrestore(&audit_freelist_lock, flags);
}

static struct audit_buffer * audit_buffer_alloc(int gfp_mask)
static struct audit_buffer * audit_buffer_alloc(struct audit_context *ctx,
						int gfp_mask, int type)
{
	unsigned long flags;
	struct audit_buffer *ab = NULL;
	struct nlmsghdr *nlh;

	spin_lock_irqsave(&audit_freelist_lock, flags);
	if (!list_empty(&audit_freelist)) {
@@ -566,6 +601,12 @@ static struct audit_buffer * audit_buffer_alloc(int gfp_mask)
	if (!ab->skb)
		goto err;

	ab->ctx   = ctx;
	nlh = (struct nlmsghdr *)skb_put(ab->skb, NLMSG_SPACE(0));
	nlh->nlmsg_type = type;
	nlh->nlmsg_flags = 0;
	nlh->nlmsg_pid = 0;
	nlh->nlmsg_seq = 0;
	return ab;
err:
	audit_buffer_free(ab);
@@ -578,12 +619,11 @@ static struct audit_buffer * audit_buffer_alloc(int gfp_mask)
 * syscall, then the syscall is marked as auditable and an audit record
 * will be written at syscall exit.  If there is no associated task, tsk
 * should be NULL. */
struct audit_buffer *audit_log_start(struct audit_context *ctx, int type, int pid)
struct audit_buffer *audit_log_start(struct audit_context *ctx, int type)
{
	struct audit_buffer	*ab	= NULL;
	struct timespec		t;
	unsigned int		serial;
	struct nlmsghdr *nlh;

	if (!audit_initialized)
		return NULL;
@@ -600,19 +640,12 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, int type, int pi
		return NULL;
	}

	ab = audit_buffer_alloc(GFP_ATOMIC);
	ab = audit_buffer_alloc(ctx, GFP_ATOMIC, type);
	if (!ab) {
		audit_log_lost("out of memory in audit_log_start");
		return NULL;
	}

	ab->ctx   = ctx;
	nlh = (struct nlmsghdr *)skb_put(ab->skb, NLMSG_SPACE(0));
	nlh->nlmsg_type = type;
	nlh->nlmsg_flags = 0;
	nlh->nlmsg_pid = pid;
	nlh->nlmsg_seq = 0;

	if (!audit_get_stamp(ab->ctx, &t, &serial)) {
		t = CURRENT_TIME;
		serial = 0;
@@ -809,13 +842,12 @@ void audit_log_end(struct audit_buffer *ab)
/* Log an audit record.  This is a convenience function that calls
 * audit_log_start, audit_log_vformat, and audit_log_end.  It may be
 * called in any context. */
void audit_log_type(struct audit_context *ctx, int type, int pid,
		    const char *fmt, ...)
void audit_log(struct audit_context *ctx, int type, const char *fmt, ...)
{
	struct audit_buffer *ab;
	va_list args;

	ab = audit_log_start(ctx, type, pid);
	ab = audit_log_start(ctx, type);
	if (ab) {
		va_start(args, fmt);
		audit_log_vformat(ab, fmt, args);
+25 −17
Original line number Diff line number Diff line
@@ -286,7 +286,8 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
			err = audit_add_rule(entry, &audit_entlist);
		if (!err && (flags & AUDIT_AT_EXIT))
			err = audit_add_rule(entry, &audit_extlist);
		audit_log(NULL, "auid %u added an audit rule\n", loginuid);
		audit_log(NULL, AUDIT_CONFIG_CHANGE, 
				"auid %u added an audit rule\n", loginuid);
		break;
	case AUDIT_DEL:
		flags =((struct audit_rule *)data)->flags;
@@ -296,7 +297,8 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data,
			err = audit_del_rule(data, &audit_entlist);
		if (!err && (flags & AUDIT_AT_EXIT))
			err = audit_del_rule(data, &audit_extlist);
		audit_log(NULL, "auid %u removed an audit rule\n", loginuid);
		audit_log(NULL, AUDIT_CONFIG_CHANGE,
				"auid %u removed an audit rule\n", loginuid);
		break;
	default:
		return -EINVAL;
@@ -648,7 +650,7 @@ static void audit_log_exit(struct audit_context *context)
	int i;
	struct audit_buffer *ab;

	ab = audit_log_start(context, AUDIT_KERNEL, 0);
	ab = audit_log_start(context, AUDIT_SYSCALL);
	if (!ab)
		return;		/* audit_panic has been called */
	audit_log_format(ab, "syscall=%d", context->major);
@@ -680,28 +682,28 @@ static void audit_log_exit(struct audit_context *context)
	while (context->aux) {
		struct audit_aux_data *aux;

		ab = audit_log_start(context, AUDIT_KERNEL, 0);
		aux = context->aux;

		ab = audit_log_start(context, aux->type);
		if (!ab)
			continue; /* audit_panic has been called */

		aux = context->aux;
		context->aux = aux->next;

		audit_log_format(ab, "auxitem=%d", aux->type);
		switch (aux->type) {
		case AUDIT_AUX_IPCPERM: {
		case AUDIT_IPC: {
			struct audit_aux_data_ipcctl *axi = (void *)aux;
			audit_log_format(ab, 
					 " qbytes=%lx uid=%d gid=%d mode=%x",
					 " qbytes=%lx iuid=%d igid=%d mode=%x",
					 axi->qbytes, axi->uid, axi->gid, axi->mode);
			}
		}
		audit_log_end(ab);

		context->aux = aux->next;
		kfree(aux);
	}

	for (i = 0; i < context->name_count; i++) {
		ab = audit_log_start(context, AUDIT_KERNEL, 0);
		ab = audit_log_start(context, AUDIT_PATH);
		if (!ab)
			continue; /* audit_panic has been called */
		audit_log_format(ab, "item=%d", i);
@@ -711,7 +713,7 @@ static void audit_log_exit(struct audit_context *context)
		}
		if (context->names[i].ino != (unsigned long)-1)
			audit_log_format(ab, " inode=%lu dev=%02x:%02x mode=%#o"
					     " uid=%d gid=%d rdev=%02x:%02x",
					     " ouid=%d ogid=%d rdev=%02x:%02x",
					 context->names[i].ino,
					 MAJOR(context->names[i].dev),
					 MINOR(context->names[i].dev),
@@ -1008,10 +1010,16 @@ int audit_get_stamp(struct audit_context *ctx,
int audit_set_loginuid(struct task_struct *task, uid_t loginuid)
{
	if (task->audit_context) {
		audit_log_type(NULL, AUDIT_LOGIN, 0,
			  "login pid=%d uid=%u old loginuid=%u new loginuid=%u",
			  task->pid, task->uid, task->audit_context->loginuid,
			  loginuid);
		struct audit_buffer *ab;

		ab = audit_log_start(NULL, AUDIT_LOGIN);
		if (ab) {
			audit_log_format(ab, "login pid=%d uid=%u "
				"old loginuid=%u new loginuid=%u",
				task->pid, task->uid, 
				task->audit_context->loginuid, loginuid);
			audit_log_end(ab);
		}
		task->audit_context->loginuid = loginuid;
	}
	return 0;
@@ -1039,7 +1047,7 @@ int audit_ipc_perms(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode)
	ax->gid = gid;
	ax->mode = mode;

	ax->d.type = AUDIT_AUX_IPCPERM;
	ax->d.type = AUDIT_IPC;
	ax->d.next = context->aux;
	context->aux = (void *)ax;
	return 0;
+2 −2
Original line number Diff line number Diff line
@@ -242,7 +242,7 @@ void __init avc_init(void)
	avc_node_cachep = kmem_cache_create("avc_node", sizeof(struct avc_node),
					     0, SLAB_PANIC, NULL, NULL);

	audit_log(current->audit_context, "AVC INITIALIZED\n");
	audit_log(current->audit_context, AUDIT_KERNEL, "AVC INITIALIZED\n");
}

int avc_get_hash_stats(char *page)
@@ -549,7 +549,7 @@ void avc_audit(u32 ssid, u32 tsid,
			return;
	}

	ab = audit_log_start(current->audit_context, AUDIT_KERNEL, 0);
	ab = audit_log_start(current->audit_context, AUDIT_AVC);
	if (!ab)
		return;		/* audit_panic has been called */
	audit_log_format(ab, "avc:  %s ", denied ? "denied" : "granted");
+1 −1
Original line number Diff line number Diff line
@@ -3419,7 +3419,7 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb)
	err = selinux_nlmsg_lookup(isec->sclass, nlh->nlmsg_type, &perm);
	if (err) {
		if (err == -EINVAL) {
			audit_log(current->audit_context,
			audit_log(current->audit_context, AUDIT_SELINUX_ERR,
				  "SELinux:  unrecognized netlink message"
				  " type=%hu for sclass=%hu\n",
				  nlh->nlmsg_type, isec->sclass);
Loading