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

Commit cb4aaf46 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'audit.b37' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/audit-current:
  [PATCH] AUDIT_FD_PAIR
  [PATCH] audit config lockdown
  [PATCH] minor update to rule add/delete messages (ver 2)
parents 874ff01b db349509
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@
#include <linux/uio.h>
#include <linux/highmem.h>
#include <linux/pagemap.h>
#include <linux/audit.h>

#include <asm/uaccess.h>
#include <asm/ioctls.h>
@@ -985,6 +986,10 @@ int do_pipe(int *fd)
		goto err_fdr;
	fdw = error;

	error = audit_fd_pair(fdr, fdw);
	if (error < 0)
		goto err_fdw;

	fd_install(fdr, fr);
	fd_install(fdw, fw);
	fd[0] = fdr;
@@ -992,6 +997,8 @@ int do_pipe(int *fd)

	return 0;

 err_fdw:
	put_unused_fd(fdw);
 err_fdr:
	put_unused_fd(fdr);
 err_read_pipe:
+9 −0
Original line number Diff line number Diff line
@@ -89,6 +89,7 @@
#define AUDIT_MQ_NOTIFY		1314	/* POSIX MQ notify record type */
#define AUDIT_MQ_GETSETATTR	1315	/* POSIX MQ get/set attribute record type */
#define AUDIT_KERNEL_OTHER	1316	/* For use by 3rd party modules */
#define AUDIT_FD_PAIR		1317    /* audit record for pipe/socketpair */

#define AUDIT_AVC		1400	/* SE Linux avc denial or grant */
#define AUDIT_SELINUX_ERR	1401	/* Internal SE Linux Errors */
@@ -387,6 +388,7 @@ extern int __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode
extern int audit_bprm(struct linux_binprm *bprm);
extern int audit_socketcall(int nargs, unsigned long *args);
extern int audit_sockaddr(int len, void *addr);
extern int __audit_fd_pair(int fd1, int fd2);
extern int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt);
extern int audit_set_macxattr(const char *name);
extern int __audit_mq_open(int oflag, mode_t mode, struct mq_attr __user *u_attr);
@@ -401,6 +403,12 @@ static inline int audit_ipc_obj(struct kern_ipc_perm *ipcp)
		return __audit_ipc_obj(ipcp);
	return 0;
}
static inline int audit_fd_pair(int fd1, int fd2)
{
	if (unlikely(!audit_dummy_context()))
		return __audit_fd_pair(fd1, fd2);
	return 0;
}
static inline int audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode)
{
	if (unlikely(!audit_dummy_context()))
@@ -459,6 +467,7 @@ extern int audit_n_rules;
#define audit_ipc_set_perm(q,u,g,m) ({ 0; })
#define audit_bprm(p) ({ 0; })
#define audit_socketcall(n,a) ({ 0; })
#define audit_fd_pair(n,a) ({ 0; })
#define audit_sockaddr(len, addr) ({ 0; })
#define audit_avc_path(dentry, mnt) ({ 0; })
#define audit_set_macxattr(n) do { ; } while (0)
+157 −59
Original line number Diff line number Diff line
@@ -2,7 +2,7 @@
 * Gateway between the kernel (e.g., selinux) and the user-space audit daemon.
 * System-call specific features have moved to auditsc.c
 *
 * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina.
 * Copyright 2003-2007 Red Hat Inc., Durham, North Carolina.
 * All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or modify
@@ -65,7 +65,9 @@
 * (Initialization happens after skb_init is called.) */
static int	audit_initialized;

/* No syscall auditing will take place unless audit_enabled != 0. */
/* 0 - no auditing
 * 1 - auditing enabled
 * 2 - auditing enabled and configuration is locked/unchangeable. */
int		audit_enabled;

/* Default state when kernel boots without any parameters. */
@@ -239,102 +241,150 @@ void audit_log_lost(const char *message)

static int audit_set_rate_limit(int limit, uid_t loginuid, u32 sid)
{
	int old	= audit_rate_limit;
	int res, rc = 0, old = audit_rate_limit;

	/* check if we are locked */
	if (audit_enabled == 2)
		res = 0;
	else
		res = 1;

	if (sid) {
		char *ctx = NULL;
		u32 len;
		int rc;
		if ((rc = selinux_sid_to_string(sid, &ctx, &len)))
			return rc;
		else
		if ((rc = selinux_sid_to_string(sid, &ctx, &len)) == 0) {
			audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
				"audit_rate_limit=%d old=%d by auid=%u subj=%s",
				limit, old, loginuid, ctx);
				"audit_rate_limit=%d old=%d by auid=%u"
				" subj=%s res=%d",
				limit, old, loginuid, ctx, res);
			kfree(ctx);
		} else
			res = 0; /* Something weird, deny request */
	}
	audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
			"audit_rate_limit=%d old=%d by auid=%u",
			limit, old, loginuid);
		"audit_rate_limit=%d old=%d by auid=%u res=%d",
		limit, old, loginuid, res);

	/* If we are allowed, make the change */
	if (res == 1)
		audit_rate_limit = limit;
	return 0;
	/* Not allowed, update reason */
	else if (rc == 0)
		rc = -EPERM;
	return rc;
}

static int audit_set_backlog_limit(int limit, uid_t loginuid, u32 sid)
{
	int old	= audit_backlog_limit;
	int res, rc = 0, old = audit_backlog_limit;

	/* check if we are locked */
	if (audit_enabled == 2)
		res = 0;
	else
		res = 1;

	if (sid) {
		char *ctx = NULL;
		u32 len;
		int rc;
		if ((rc = selinux_sid_to_string(sid, &ctx, &len)))
			return rc;
		else
		if ((rc = selinux_sid_to_string(sid, &ctx, &len)) == 0) {
			audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
			    "audit_backlog_limit=%d old=%d by auid=%u subj=%s",
				limit, old, loginuid, ctx);
				"audit_backlog_limit=%d old=%d by auid=%u"
				" subj=%s res=%d",
				limit, old, loginuid, ctx, res);
			kfree(ctx);
		} else
			res = 0; /* Something weird, deny request */
	}
	audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
			"audit_backlog_limit=%d old=%d by auid=%u",
			limit, old, loginuid);
		"audit_backlog_limit=%d old=%d by auid=%u res=%d",
		limit, old, loginuid, res);

	/* If we are allowed, make the change */
	if (res == 1)
		audit_backlog_limit = limit;
	return 0;
	/* Not allowed, update reason */
	else if (rc == 0)
		rc = -EPERM;
	return rc;
}

static int audit_set_enabled(int state, uid_t loginuid, u32 sid)
{
	int old = audit_enabled;
	int res, rc = 0, old = audit_enabled;

	if (state != 0 && state != 1)
	if (state < 0 || state > 2)
		return -EINVAL;

	/* check if we are locked */
	if (audit_enabled == 2)
		res = 0;
	else
		res = 1;

	if (sid) {
		char *ctx = NULL;
		u32 len;
		int rc;
		if ((rc = selinux_sid_to_string(sid, &ctx, &len)))
			return rc;
		else
		if ((rc = selinux_sid_to_string(sid, &ctx, &len)) == 0) {
			audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
				"audit_enabled=%d old=%d by auid=%u subj=%s",
				state, old, loginuid, ctx);
				"audit_enabled=%d old=%d by auid=%u"
				" subj=%s res=%d",
				state, old, loginuid, ctx, res);
			kfree(ctx);
		} else
			res = 0; /* Something weird, deny request */
	}
	audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
			"audit_enabled=%d old=%d by auid=%u",
			state, old, loginuid);
		"audit_enabled=%d old=%d by auid=%u res=%d",
		state, old, loginuid, res);

	/* If we are allowed, make the change */
	if (res == 1)
		audit_enabled = state;
	return 0;
	/* Not allowed, update reason */
	else if (rc == 0)
		rc = -EPERM;
	return rc;
}

static int audit_set_failure(int state, uid_t loginuid, u32 sid)
{
	int old = audit_failure;
	int res, rc = 0, old = audit_failure;

	if (state != AUDIT_FAIL_SILENT
	    && state != AUDIT_FAIL_PRINTK
	    && state != AUDIT_FAIL_PANIC)
		return -EINVAL;

	/* check if we are locked */
	if (audit_enabled == 2)
		res = 0;
	else
		res = 1;

	if (sid) {
		char *ctx = NULL;
		u32 len;
		int rc;
		if ((rc = selinux_sid_to_string(sid, &ctx, &len)))
			return rc;
		else
		if ((rc = selinux_sid_to_string(sid, &ctx, &len)) == 0) {
			audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
				"audit_failure=%d old=%d by auid=%u subj=%s",
				state, old, loginuid, ctx);
				"audit_failure=%d old=%d by auid=%u"
				" subj=%s res=%d",
				state, old, loginuid, ctx, res);
			kfree(ctx);
		} else
			res = 0; /* Something weird, deny request */
	}
	audit_log(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE,
			"audit_failure=%d old=%d by auid=%u",
			state, old, loginuid);
		"audit_failure=%d old=%d by auid=%u res=%d",
		state, old, loginuid, res);

	/* If we are allowed, make the change */
	if (res == 1)
		audit_failure = state;
	return 0;
	/* Not allowed, update reason */
	else if (rc == 0)
		rc = -EPERM;
	return rc;
}

static int kauditd_thread(void *dummy)
@@ -599,6 +649,30 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
	case AUDIT_DEL:
		if (nlmsg_len(nlh) < sizeof(struct audit_rule))
			return -EINVAL;
		if (audit_enabled == 2) {
			ab = audit_log_start(NULL, GFP_KERNEL,
					AUDIT_CONFIG_CHANGE);
			if (ab) {
				audit_log_format(ab,
						 "pid=%d uid=%u auid=%u",
						 pid, uid, loginuid);
				if (sid) {
					if (selinux_sid_to_string(
							sid, &ctx, &len)) {
						audit_log_format(ab,
							" ssid=%u", sid);
						/* Maybe call audit_panic? */
					} else
						audit_log_format(ab,
							" subj=%s", ctx);
					kfree(ctx);
				}
				audit_log_format(ab, " audit_enabled=%d res=0",
					audit_enabled);
				audit_log_end(ab);
			}
			return -EPERM;
		}
		/* fallthrough */
	case AUDIT_LIST:
		err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid,
@@ -609,6 +683,30 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
	case AUDIT_DEL_RULE:
		if (nlmsg_len(nlh) < sizeof(struct audit_rule_data))
			return -EINVAL;
		if (audit_enabled == 2) {
			ab = audit_log_start(NULL, GFP_KERNEL,
					AUDIT_CONFIG_CHANGE);
			if (ab) {
				audit_log_format(ab,
						 "pid=%d uid=%u auid=%u",
						 pid, uid, loginuid);
				if (sid) {
					if (selinux_sid_to_string(
							sid, &ctx, &len)) {
						audit_log_format(ab,
							" ssid=%u", sid);
						/* Maybe call audit_panic? */
					} else
						audit_log_format(ab,
							" subj=%s", ctx);
					kfree(ctx);
				}
				audit_log_format(ab, " audit_enabled=%d res=0",
					audit_enabled);
				audit_log_end(ab);
			}
			return -EPERM;
		}
		/* fallthrough */
	case AUDIT_LIST_RULES:
		err = audit_receive_filter(nlh->nlmsg_type, NETLINK_CB(skb).pid,
+5 −4
Original line number Diff line number Diff line
@@ -937,9 +937,10 @@ static void audit_update_watch(struct audit_parent *parent,
		}

		ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
		audit_log_format(ab, "audit updated rules specifying path=");
		audit_log_format(ab, "op=updated rules specifying path=");
		audit_log_untrustedstring(ab, owatch->path);
		audit_log_format(ab, " with dev=%u ino=%lu\n", dev, ino);
		audit_log_format(ab, " list=%d res=1", r->listnr);
		audit_log_end(ab);

		audit_remove_watch(owatch);
@@ -969,14 +970,14 @@ static void audit_remove_parent_watches(struct audit_parent *parent)
			e = container_of(r, struct audit_entry, rule);

			ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
			audit_log_format(ab, "audit implicitly removed rule path=");
			audit_log_format(ab, "op=remove rule path=");
			audit_log_untrustedstring(ab, w->path);
			if (r->filterkey) {
				audit_log_format(ab, " key=");
				audit_log_untrustedstring(ab, r->filterkey);
			} else
				audit_log_format(ab, " key=(null)");
			audit_log_format(ab, " list=%d", r->listnr);
			audit_log_format(ab, " list=%d res=1", r->listnr);
			audit_log_end(ab);

			list_del(&r->rlist);
@@ -1410,7 +1411,7 @@ static void audit_log_rule_change(uid_t loginuid, u32 sid, char *action,
			audit_log_format(ab, " subj=%s", ctx);
		kfree(ctx);
	}
	audit_log_format(ab, " %s rule key=", action);
	audit_log_format(ab, " op=%s rule key=", action);
	if (rule->filterkey)
		audit_log_untrustedstring(ab, rule->filterkey);
	else
+40 −0
Original line number Diff line number Diff line
@@ -170,6 +170,11 @@ struct audit_aux_data_sockaddr {
	char			a[0];
};

struct audit_aux_data_fd_pair {
	struct	audit_aux_data d;
	int	fd[2];
};

struct audit_aux_data_path {
	struct audit_aux_data	d;
	struct dentry		*dentry;
@@ -961,6 +966,11 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
			audit_log_d_path(ab, "path=", axi->dentry, axi->mnt);
			break; }

		case AUDIT_FD_PAIR: {
			struct audit_aux_data_fd_pair *axs = (void *)aux;
			audit_log_format(ab, "fd0=%d fd1=%d", axs->fd[0], axs->fd[1]);
			break; }

		}
		audit_log_end(ab);
	}
@@ -1814,6 +1824,36 @@ int audit_socketcall(int nargs, unsigned long *args)
	return 0;
}

/**
 * __audit_fd_pair - record audit data for pipe and socketpair
 * @fd1: the first file descriptor
 * @fd2: the second file descriptor
 *
 * Returns 0 for success or NULL context or < 0 on error.
 */
int __audit_fd_pair(int fd1, int fd2)
{
	struct audit_context *context = current->audit_context;
	struct audit_aux_data_fd_pair *ax;

	if (likely(!context)) {
		return 0;
	}

	ax = kmalloc(sizeof(*ax), GFP_KERNEL);
	if (!ax) {
		return -ENOMEM;
	}

	ax->fd[0] = fd1;
	ax->fd[1] = fd2;

	ax->d.type = AUDIT_FD_PAIR;
	ax->d.next = context->aux;
	context->aux = (void *)ax;
	return 0;
}

/**
 * audit_sockaddr - record audit data for sys_bind, sys_connect, sys_sendto
 * @len: data length in user space
Loading