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

Commit 6ad11bdd authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull audit updates from Paul Moore:
 "We didn't have anything to send for v4.16, but we're back with a
  little more than usual for v4.17.

  Eleven patches in total, most fall into the small fix category, but
  there are three non-trivial changes worth calling out:

   - the audit entry filter is being removed after deprecating it for
     quite a while (years of no one really using it because it turns out
     to be not very practical)

   - created our own version of "__mutex_owner()" because the locking
     folks were upset we were using theirs

   - improved our handling of kernel command line parameters to make
     them more forgiving

   - we fixed auditing of symlink operations

  Everything passes the audit-testsuite and as of a few minutes ago it
  merges well with your tree"

* tag 'audit-pr-20180403' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/audit:
  audit: add refused symlink to audit_names
  audit: remove path param from link denied function
  audit: link denied should not directly generate PATH record
  audit: make ANOM_LINK obey audit_enabled and audit_dummy_context
  audit: do not panic on invalid boot parameter
  audit: track the owner of the command mutex ourselves
  audit: return on memory error to avoid null pointer dereference
  audit: bail before bug check if audit disabled
  audit: deprecate the AUDIT_FILTER_ENTRY filter
  audit: session ID should not set arch quick field pointer
  audit: update bugtracker and source URIs
parents 69824bcc ea841baf
Loading
Loading
Loading
Loading
+7 −7
Original line number Diff line number Diff line
@@ -389,15 +389,15 @@
			Use software keyboard repeat

	audit=		[KNL] Enable the audit sub-system
			Format: { "0" | "1" } (0 = disabled, 1 = enabled)
			0 - kernel audit is disabled and can not be enabled
			    until the next reboot
			Format: { "0" | "1" | "off" | "on" }
			0 | off - kernel audit is disabled and can not be
			    enabled until the next reboot
			unset - kernel audit is initialized but disabled and
			    will be fully enabled by the userspace auditd.
			1 - kernel audit is initialized and partially enabled,
			    storing at most audit_backlog_limit messages in
			    RAM until it is fully enabled by the userspace
			    auditd.
			1 | on - kernel audit is initialized and partially
			    enabled, storing at most audit_backlog_limit
			    messages in RAM until it is fully enabled by the
			    userspace auditd.
			Default: unset

	audit_backlog_limit= [KNL] Set the audit queue size limit.
+0 −1
Original line number Diff line number Diff line
@@ -2504,7 +2504,6 @@ M: Paul Moore <paul@paul-moore.com>
M:	Eric Paris <eparis@redhat.com>
L:	linux-audit@redhat.com (moderated for non-subscribers)
W:	https://github.com/linux-audit
W:	https://people.redhat.com/sgrubb/audit
T:	git git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/audit.git
S:	Supported
F:	include/linux/audit.h
+3 −2
Original line number Diff line number Diff line
@@ -929,7 +929,8 @@ static inline int may_follow_link(struct nameidata *nd)
	if (nd->flags & LOOKUP_RCU)
		return -ECHILD;

	audit_log_link_denied("follow_link", &nd->stack[0].link);
	audit_inode(nd->name, nd->stack[0].link.dentry, 0);
	audit_log_link_denied("follow_link");
	return -EACCES;
}

@@ -995,7 +996,7 @@ static int may_linkat(struct path *link)
	if (safe_hardlink_source(inode) || inode_owner_or_capable(inode))
		return 0;

	audit_log_link_denied("linkat", link);
	audit_log_link_denied("linkat");
	return -EPERM;
}

+2 −4
Original line number Diff line number Diff line
@@ -146,8 +146,7 @@ extern void audit_log_d_path(struct audit_buffer *ab,
					     const struct path *path);
extern void		    audit_log_key(struct audit_buffer *ab,
					  char *key);
extern void		    audit_log_link_denied(const char *operation,
						  const struct path *link);
extern void		    audit_log_link_denied(const char *operation);
extern void		    audit_log_lost(const char *message);

extern int audit_log_task_context(struct audit_buffer *ab);
@@ -194,8 +193,7 @@ static inline void audit_log_d_path(struct audit_buffer *ab,
{ }
static inline void audit_log_key(struct audit_buffer *ab, char *key)
{ }
static inline void audit_log_link_denied(const char *string,
					 const struct path *link)
static inline void audit_log_link_denied(const char *string)
{ }
static inline int audit_log_task_context(struct audit_buffer *ab)
{
+76 −32
Original line number Diff line number Diff line
@@ -38,7 +38,8 @@
 *	  6) Support low-overhead kernel-based filtering to minimize the
 *	     information that must be passed to user-space.
 *
 * Example user-space utilities: http://people.redhat.com/sgrubb/audit/
 * Audit userspace, documentation, tests, and bug/issue trackers:
 * 	https://github.com/linux-audit
 */

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -180,9 +181,21 @@ static char *audit_feature_names[2] = {
	"loginuid_immutable",
};


/* Serialize requests from userspace. */
DEFINE_MUTEX(audit_cmd_mutex);
/**
 * struct audit_ctl_mutex - serialize requests from userspace
 * @lock: the mutex used for locking
 * @owner: the task which owns the lock
 *
 * Description:
 * This is the lock struct used to ensure we only process userspace requests
 * in an orderly fashion.  We can't simply use a mutex/lock here because we
 * need to track lock ownership so we don't end up blocking the lock owner in
 * audit_log_start() or similar.
 */
static struct audit_ctl_mutex {
	struct mutex lock;
	void *owner;
} audit_cmd_mutex;

/* AUDIT_BUFSIZ is the size of the temporary buffer used for formatting
 * audit records.  Since printk uses a 1024 byte buffer, this buffer
@@ -226,6 +239,36 @@ int auditd_test_task(struct task_struct *task)
	return rc;
}

/**
 * audit_ctl_lock - Take the audit control lock
 */
void audit_ctl_lock(void)
{
	mutex_lock(&audit_cmd_mutex.lock);
	audit_cmd_mutex.owner = current;
}

/**
 * audit_ctl_unlock - Drop the audit control lock
 */
void audit_ctl_unlock(void)
{
	audit_cmd_mutex.owner = NULL;
	mutex_unlock(&audit_cmd_mutex.lock);
}

/**
 * audit_ctl_owner_current - Test to see if the current task owns the lock
 *
 * Description:
 * Return true if the current task owns the audit control lock, false if it
 * doesn't own the lock.
 */
static bool audit_ctl_owner_current(void)
{
	return (current == audit_cmd_mutex.owner);
}

/**
 * auditd_pid_vnr - Return the auditd PID relative to the namespace
 *
@@ -860,8 +903,8 @@ int audit_send_list(void *_dest)
	struct sock *sk = audit_get_sk(dest->net);

	/* wait for parent to finish and send an ACK */
	mutex_lock(&audit_cmd_mutex);
	mutex_unlock(&audit_cmd_mutex);
	audit_ctl_lock();
	audit_ctl_unlock();

	while ((skb = __skb_dequeue(&dest->q)) != NULL)
		netlink_unicast(sk, skb, dest->portid, 0);
@@ -902,8 +945,8 @@ static int audit_send_reply_thread(void *arg)
	struct audit_reply *reply = (struct audit_reply *)arg;
	struct sock *sk = audit_get_sk(reply->net);

	mutex_lock(&audit_cmd_mutex);
	mutex_unlock(&audit_cmd_mutex);
	audit_ctl_lock();
	audit_ctl_unlock();

	/* Ignore failure. It'll only happen if the sender goes away,
	   because our timeout is set to infinite. */
@@ -1058,6 +1101,8 @@ static void audit_log_feature_change(int which, u32 old_feature, u32 new_feature
		return;

	ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_FEATURE_CHANGE);
	if (!ab)
		return;
	audit_log_task_info(ab, current);
	audit_log_format(ab, " feature=%s old=%u new=%u old_lock=%u new_lock=%u res=%d",
			 audit_feature_names[which], !!old_feature, !!new_feature,
@@ -1466,7 +1511,7 @@ static void audit_receive(struct sk_buff *skb)
	nlh = nlmsg_hdr(skb);
	len = skb->len;

	mutex_lock(&audit_cmd_mutex);
	audit_ctl_lock();
	while (nlmsg_ok(nlh, len)) {
		err = audit_receive_msg(skb, nlh);
		/* if err or if this message says it wants a response */
@@ -1475,7 +1520,7 @@ static void audit_receive(struct sk_buff *skb)

		nlh = nlmsg_next(nlh, &len);
	}
	mutex_unlock(&audit_cmd_mutex);
	audit_ctl_unlock();
}

/* Run custom bind function on netlink socket group connect or bind requests. */
@@ -1547,6 +1592,9 @@ static int __init audit_init(void)
	for (i = 0; i < AUDIT_INODE_BUCKETS; i++)
		INIT_LIST_HEAD(&audit_inode_hash[i]);

	mutex_init(&audit_cmd_mutex.lock);
	audit_cmd_mutex.owner = NULL;

	pr_info("initializing netlink subsys (%s)\n",
		audit_default ? "enabled" : "disabled");
	register_pernet_subsys(&audit_net_ops);
@@ -1567,19 +1615,26 @@ static int __init audit_init(void)
}
postcore_initcall(audit_init);

/* Process kernel command-line parameter at boot time.  audit=0 or audit=1. */
/*
 * Process kernel command-line parameter at boot time.
 * audit={0|off} or audit={1|on}.
 */
static int __init audit_enable(char *str)
{
	long val;

	if (kstrtol(str, 0, &val))
		panic("audit: invalid 'audit' parameter value (%s)\n", str);
	audit_default = (val ? AUDIT_ON : AUDIT_OFF);
	if (!strcasecmp(str, "off") || !strcmp(str, "0"))
		audit_default = AUDIT_OFF;
	else if (!strcasecmp(str, "on") || !strcmp(str, "1"))
		audit_default = AUDIT_ON;
	else {
		pr_err("audit: invalid 'audit' parameter value (%s)\n", str);
		audit_default = AUDIT_ON;
	}

	if (audit_default == AUDIT_OFF)
		audit_initialized = AUDIT_DISABLED;
	if (audit_set_enabled(audit_default))
		panic("audit: error setting audit state (%d)\n", audit_default);
		pr_err("audit: error setting audit state (%d)\n",
		       audit_default);

	pr_info("%s\n", audit_default ?
		"enabled (after initialization)" : "disabled (until reboot)");
@@ -1710,8 +1765,7 @@ struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t gfp_mask,
	 *    using a PID anchored in the caller's namespace
	 * 2. generator holding the audit_cmd_mutex - we don't want to block
	 *    while holding the mutex */
	if (!(auditd_test_task(current) ||
	      (current == __mutex_owner(&audit_cmd_mutex)))) {
	if (!(auditd_test_task(current) || audit_ctl_owner_current())) {
		long stime = audit_backlog_wait_time;

		while (audit_backlog_limit &&
@@ -2254,33 +2308,23 @@ EXPORT_SYMBOL(audit_log_task_info);
/**
 * audit_log_link_denied - report a link restriction denial
 * @operation: specific link operation
 * @link: the path that triggered the restriction
 */
void audit_log_link_denied(const char *operation, const struct path *link)
void audit_log_link_denied(const char *operation)
{
	struct audit_buffer *ab;
	struct audit_names *name;

	name = kzalloc(sizeof(*name), GFP_NOFS);
	if (!name)
	if (!audit_enabled || audit_dummy_context())
		return;

	/* Generate AUDIT_ANOM_LINK with subject, operation, outcome. */
	ab = audit_log_start(current->audit_context, GFP_KERNEL,
			     AUDIT_ANOM_LINK);
	if (!ab)
		goto out;
		return;
	audit_log_format(ab, "op=%s", operation);
	audit_log_task_info(ab, current);
	audit_log_format(ab, " res=0");
	audit_log_end(ab);

	/* Generate AUDIT_PATH record with object. */
	name->type = AUDIT_TYPE_NORMAL;
	audit_copy_inode(name, link->dentry, d_backing_inode(link->dentry));
	audit_log_name(current->audit_context, name, link, 0, NULL);
out:
	kfree(name);
}

/**
Loading