Commit 9d99b164 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull audit updates from Paul Moore:
 "Summary of the significant patches:

   - Record information about binds/unbinds to the audit multicast
     socket. This helps identify which processes have/had access to the
     information in the audit stream.

   - Cleanup and add some additional information to the netfilter
     configuration events collected by audit.

   - Fix some of the audit error handling code so we don't leak network
     namespace references"

* tag 'audit-pr-20200601' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/audit:
  audit: add subj creds to NETFILTER_CFG record to
  audit: Replace zero-length array with flexible-array
  audit: make symbol 'audit_nfcfgs' static
  netfilter: add audit table unregister actions
  audit: tidy and extend netfilter_cfg x_tables
  audit: log audit netlink multicast bind and unbind
  audit: fix a net reference leak in audit_list_rules_send()
  audit: fix a net reference leak in audit_send_reply()
parents 91681e84 9d44a121
Loading
Loading
Loading
Loading
+23 −1
Original line number Diff line number Diff line
@@ -19,7 +19,7 @@
struct audit_sig_info {
	uid_t		uid;
	pid_t		pid;
	char		ctx[0];
	char		ctx[];
};

struct audit_buffer;
@@ -94,6 +94,12 @@ struct audit_ntp_data {
struct audit_ntp_data {};
#endif

enum audit_nfcfgop {
	AUDIT_XT_OP_REGISTER,
	AUDIT_XT_OP_REPLACE,
	AUDIT_XT_OP_UNREGISTER,
};

extern int is_audit_feature_set(int which);

extern int __init audit_register_class(int class, unsigned *list);
@@ -379,6 +385,8 @@ extern void __audit_log_kern_module(char *name);
extern void __audit_fanotify(unsigned int response);
extern void __audit_tk_injoffset(struct timespec64 offset);
extern void __audit_ntp_log(const struct audit_ntp_data *ad);
extern void __audit_log_nfcfg(const char *name, u8 af, unsigned int nentries,
			      enum audit_nfcfgop op);

static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp)
{
@@ -514,6 +522,14 @@ static inline void audit_ntp_log(const struct audit_ntp_data *ad)
		__audit_ntp_log(ad);
}

static inline void audit_log_nfcfg(const char *name, u8 af,
				   unsigned int nentries,
				   enum audit_nfcfgop op)
{
	if (audit_enabled)
		__audit_log_nfcfg(name, af, nentries, op);
}

extern int audit_n_rules;
extern int audit_signals;
#else /* CONFIG_AUDITSYSCALL */
@@ -646,6 +662,12 @@ static inline void audit_ntp_log(const struct audit_ntp_data *ad)

static inline void audit_ptrace(struct task_struct *t)
{ }

static inline void audit_log_nfcfg(const char *name, u8 af,
				   unsigned int nentries,
				   enum audit_nfcfgop op)
{ }

#define audit_n_rules 0
#define audit_signals 0
#endif /* CONFIG_AUDITSYSCALL */
+1 −0
Original line number Diff line number Diff line
@@ -117,6 +117,7 @@
#define AUDIT_TIME_INJOFFSET	1332	/* Timekeeping offset injected */
#define AUDIT_TIME_ADJNTPVAL	1333	/* NTP value adjustment */
#define AUDIT_BPF		1334	/* BPF subsystem */
#define AUDIT_EVENT_LISTENER	1335	/* Task joined multicast read socket */

#define AUDIT_AVC		1400	/* SE Linux avc denial or grant */
#define AUDIT_SELINUX_ERR	1401	/* Internal SE Linux Errors */
+74 −26
Original line number Diff line number Diff line
@@ -880,7 +880,7 @@ static int kauditd_thread(void *dummy)
	return 0;
}

int audit_send_list(void *_dest)
int audit_send_list_thread(void *_dest)
{
	struct audit_netlink_list *dest = _dest;
	struct sk_buff *skb;
@@ -924,19 +924,30 @@ struct sk_buff *audit_make_reply(int seq, int type, int done,
	return NULL;
}

static void audit_free_reply(struct audit_reply *reply)
{
	if (!reply)
		return;

	if (reply->skb)
		kfree_skb(reply->skb);
	if (reply->net)
		put_net(reply->net);
	kfree(reply);
}

static int audit_send_reply_thread(void *arg)
{
	struct audit_reply *reply = (struct audit_reply *)arg;
	struct sock *sk = audit_get_sk(reply->net);

	audit_ctl_lock();
	audit_ctl_unlock();

	/* Ignore failure. It'll only happen if the sender goes away,
	   because our timeout is set to infinite. */
	netlink_unicast(sk, reply->skb, reply->portid, 0);
	put_net(reply->net);
	kfree(reply);
	netlink_unicast(audit_get_sk(reply->net), reply->skb, reply->portid, 0);
	reply->skb = NULL;
	audit_free_reply(reply);
	return 0;
}

@@ -950,35 +961,32 @@ static int audit_send_reply_thread(void *arg)
 * @payload: payload data
 * @size: payload size
 *
 * Allocates an skb, builds the netlink message, and sends it to the port id.
 * No failure notifications.
 * Allocates a skb, builds the netlink message, and sends it to the port id.
 */
static void audit_send_reply(struct sk_buff *request_skb, int seq, int type, int done,
			     int multi, const void *payload, int size)
{
	struct net *net = sock_net(NETLINK_CB(request_skb).sk);
	struct sk_buff *skb;
	struct task_struct *tsk;
	struct audit_reply *reply = kmalloc(sizeof(struct audit_reply),
					    GFP_KERNEL);
	struct audit_reply *reply;

	reply = kzalloc(sizeof(*reply), GFP_KERNEL);
	if (!reply)
		return;

	skb = audit_make_reply(seq, type, done, multi, payload, size);
	if (!skb)
		goto out;

	reply->net = get_net(net);
	reply->skb = audit_make_reply(seq, type, done, multi, payload, size);
	if (!reply->skb)
		goto err;
	reply->net = get_net(sock_net(NETLINK_CB(request_skb).sk));
	reply->portid = NETLINK_CB(request_skb).portid;
	reply->skb = skb;

	tsk = kthread_run(audit_send_reply_thread, reply, "audit_send_reply");
	if (!IS_ERR(tsk))
	if (IS_ERR(tsk))
		goto err;

	return;
	kfree_skb(skb);
out:
	kfree(reply);

err:
	audit_free_reply(reply);
}

/*
@@ -1525,20 +1533,60 @@ static void audit_receive(struct sk_buff *skb)
	audit_ctl_unlock();
}

/* Log information about who is connecting to the audit multicast socket */
static void audit_log_multicast(int group, const char *op, int err)
{
	const struct cred *cred;
	struct tty_struct *tty;
	char comm[sizeof(current->comm)];
	struct audit_buffer *ab;

	if (!audit_enabled)
		return;

	ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_EVENT_LISTENER);
	if (!ab)
		return;

	cred = current_cred();
	tty = audit_get_tty();
	audit_log_format(ab, "pid=%u uid=%u auid=%u tty=%s ses=%u",
			 task_pid_nr(current),
			 from_kuid(&init_user_ns, cred->uid),
			 from_kuid(&init_user_ns, audit_get_loginuid(current)),
			 tty ? tty_name(tty) : "(none)",
			 audit_get_sessionid(current));
	audit_put_tty(tty);
	audit_log_task_context(ab); /* subj= */
	audit_log_format(ab, " comm=");
	audit_log_untrustedstring(ab, get_task_comm(comm, current));
	audit_log_d_path_exe(ab, current->mm); /* exe= */
	audit_log_format(ab, " nl-mcgrp=%d op=%s res=%d", group, op, !err);
	audit_log_end(ab);
}

/* Run custom bind function on netlink socket group connect or bind requests. */
static int audit_bind(struct net *net, int group)
static int audit_multicast_bind(struct net *net, int group)
{
	int err = 0;

	if (!capable(CAP_AUDIT_READ))
		return -EPERM;
		err = -EPERM;
	audit_log_multicast(group, "connect", err);
	return err;
}

	return 0;
static void audit_multicast_unbind(struct net *net, int group)
{
	audit_log_multicast(group, "disconnect", 0);
}

static int __net_init audit_net_init(struct net *net)
{
	struct netlink_kernel_cfg cfg = {
		.input	= audit_receive,
		.bind	= audit_bind,
		.bind	= audit_multicast_bind,
		.unbind	= audit_multicast_unbind,
		.flags	= NL_CFG_F_NONROOT_RECV,
		.groups	= AUDIT_NLGRP_MAX,
	};
+1 −1
Original line number Diff line number Diff line
@@ -229,7 +229,7 @@ struct audit_netlink_list {
	struct sk_buff_head q;
};

int audit_send_list(void *_dest);
int audit_send_list_thread(void *_dest);

extern int selinux_audit_rule_update(void);

+7 −9
Original line number Diff line number Diff line
@@ -1161,11 +1161,8 @@ int audit_rule_change(int type, int seq, void *data, size_t datasz)
 */
int audit_list_rules_send(struct sk_buff *request_skb, int seq)
{
	u32 portid = NETLINK_CB(request_skb).portid;
	struct net *net = sock_net(NETLINK_CB(request_skb).sk);
	struct task_struct *tsk;
	struct audit_netlink_list *dest;
	int err = 0;

	/* We can't just spew out the rules here because we might fill
	 * the available socket buffer space and deadlock waiting for
@@ -1173,25 +1170,26 @@ int audit_list_rules_send(struct sk_buff *request_skb, int seq)
	 * happen if we're actually running in the context of auditctl
	 * trying to _send_ the stuff */

	dest = kmalloc(sizeof(struct audit_netlink_list), GFP_KERNEL);
	dest = kmalloc(sizeof(*dest), GFP_KERNEL);
	if (!dest)
		return -ENOMEM;
	dest->net = get_net(net);
	dest->portid = portid;
	dest->net = get_net(sock_net(NETLINK_CB(request_skb).sk));
	dest->portid = NETLINK_CB(request_skb).portid;
	skb_queue_head_init(&dest->q);

	mutex_lock(&audit_filter_mutex);
	audit_list_rules(seq, &dest->q);
	mutex_unlock(&audit_filter_mutex);

	tsk = kthread_run(audit_send_list, dest, "audit_send_list");
	tsk = kthread_run(audit_send_list_thread, dest, "audit_send_list");
	if (IS_ERR(tsk)) {
		skb_queue_purge(&dest->q);
		put_net(dest->net);
		kfree(dest);
		err = PTR_ERR(tsk);
		return PTR_ERR(tsk);
	}

	return err;
	return 0;
}

int audit_comparator(u32 left, u32 op, u32 right)
Loading