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

Commit 161a09e7 authored by Joy Latten's avatar Joy Latten Committed by David S. Miller
Browse files

audit: Add auditing to ipsec



An audit message occurs when an ipsec SA
or ipsec policy is created/deleted.

Signed-off-by: default avatarJoy Latten <latten@austin.ibm.com>
Signed-off-by: default avatarJames Morris <jmorris@namei.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 95b99a67
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -101,6 +101,10 @@
#define AUDIT_MAC_CIPSOV4_DEL	1408	/* NetLabel: del CIPSOv4 DOI entry */
#define AUDIT_MAC_MAP_ADD	1409	/* NetLabel: add LSM domain mapping */
#define AUDIT_MAC_MAP_DEL	1410	/* NetLabel: del LSM domain mapping */
#define AUDIT_MAC_IPSEC_ADDSA	1411	/* Add a XFRM state */
#define AUDIT_MAC_IPSEC_DELSA	1412	/* Delete a XFRM state */
#define AUDIT_MAC_IPSEC_ADDSPD	1413	/* Add a XFRM policy */
#define AUDIT_MAC_IPSEC_DELSPD	1414	/* Delete a XFRM policy */

#define AUDIT_FIRST_KERN_ANOM_MSG   1700
#define AUDIT_LAST_KERN_ANOM_MSG    1799
@@ -377,6 +381,7 @@ extern void auditsc_get_stamp(struct audit_context *ctx,
			      struct timespec *t, unsigned int *serial);
extern int  audit_set_loginuid(struct task_struct *task, uid_t loginuid);
extern uid_t audit_get_loginuid(struct audit_context *ctx);
extern void audit_log_task_context(struct audit_buffer *ab);
extern int __audit_ipc_obj(struct kern_ipc_perm *ipcp);
extern int __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode);
extern int audit_bprm(struct linux_binprm *bprm);
@@ -449,6 +454,7 @@ extern int audit_n_rules;
#define audit_inode_update(i) do { ; } while (0)
#define auditsc_get_stamp(c,t,s) do { BUG(); } while (0)
#define audit_get_loginuid(c) ({ -1; })
#define audit_log_task_context(b) do { ; } while (0)
#define audit_ipc_obj(i) ({ 0; })
#define audit_ipc_set_perm(q,u,g,m) ({ 0; })
#define audit_bprm(p) ({ 0; })
+14 −5
Original line number Diff line number Diff line
@@ -392,6 +392,15 @@ extern int xfrm_unregister_km(struct xfrm_mgr *km);

extern unsigned int xfrm_policy_count[XFRM_POLICY_MAX*2];

/* Audit Information */
struct xfrm_audit
{
	uid_t	loginuid;
	u32	secid;
};
void xfrm_audit_log(uid_t auid, u32 secid, int type, int result,
		    struct xfrm_policy *xp, struct xfrm_state *x);

static inline void xfrm_pol_hold(struct xfrm_policy *policy)
{
	if (likely(policy != NULL))
@@ -906,7 +915,7 @@ static inline int xfrm_state_sort(struct xfrm_state **dst, struct xfrm_state **s
#endif
extern struct xfrm_state *xfrm_find_acq_byseq(u32 seq);
extern int xfrm_state_delete(struct xfrm_state *x);
extern void xfrm_state_flush(u8 proto);
extern void xfrm_state_flush(u8 proto, struct xfrm_audit *audit_info);
extern int xfrm_replay_check(struct xfrm_state *x, __be32 seq);
extern void xfrm_replay_advance(struct xfrm_state *x, __be32 seq);
extern void xfrm_replay_notify(struct xfrm_state *x, int event);
@@ -959,13 +968,13 @@ struct xfrm_policy *xfrm_policy_bysel_ctx(u8 type, int dir,
					  struct xfrm_selector *sel,
					  struct xfrm_sec_ctx *ctx, int delete);
struct xfrm_policy *xfrm_policy_byid(u8, int dir, u32 id, int delete);
void xfrm_policy_flush(u8 type);
void xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info);
u32 xfrm_get_acqseq(void);
void xfrm_alloc_spi(struct xfrm_state *x, __be32 minspi, __be32 maxspi);
struct xfrm_state * xfrm_find_acq(u8 mode, u32 reqid, u8 proto,
				  xfrm_address_t *daddr, xfrm_address_t *saddr,
				  int create, unsigned short family);
extern void xfrm_policy_flush(u8 type);
extern void xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info);
extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol);
extern int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *xdst,
			  struct flowi *fl, int family, int strict);
+5 −1
Original line number Diff line number Diff line
@@ -731,7 +731,7 @@ static inline void audit_free_context(struct audit_context *context)
		printk(KERN_ERR "audit: freed %d contexts\n", count);
}

static void audit_log_task_context(struct audit_buffer *ab)
void audit_log_task_context(struct audit_buffer *ab)
{
	char *ctx = NULL;
	ssize_t len = 0;
@@ -760,6 +760,8 @@ static void audit_log_task_context(struct audit_buffer *ab)
	return;
}

EXPORT_SYMBOL(audit_log_task_context);

static void audit_log_task_info(struct audit_buffer *ab, struct task_struct *tsk)
{
	char name[sizeof(tsk->comm)];
@@ -1488,6 +1490,8 @@ uid_t audit_get_loginuid(struct audit_context *ctx)
	return ctx ? ctx->loginuid : -1;
}

EXPORT_SYMBOL(audit_get_loginuid);

/**
 * __audit_mq_open - record audit data for a POSIX MQ open
 * @oflag: open flag
+24 −3
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#include <linux/proc_fs.h>
#include <linux/init.h>
#include <net/xfrm.h>
#include <linux/audit.h>

#include <net/sock.h>

@@ -1420,6 +1421,9 @@ static int pfkey_add(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr,
	else
		err = xfrm_state_update(x);

	xfrm_audit_log(audit_get_loginuid(current->audit_context), 0,
		       AUDIT_MAC_IPSEC_ADDSA, err ? 0 : 1, NULL, x);

	if (err < 0) {
		x->km.state = XFRM_STATE_DEAD;
		__xfrm_state_put(x);
@@ -1462,6 +1466,10 @@ static int pfkey_delete(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
	}

	err = xfrm_state_delete(x);

	xfrm_audit_log(audit_get_loginuid(current->audit_context), 0,
		       AUDIT_MAC_IPSEC_DELSA, err ? 0 : 1, NULL, x);

	if (err < 0)
		goto out;

@@ -1637,12 +1645,15 @@ static int pfkey_flush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hd
{
	unsigned proto;
	struct km_event c;
	struct xfrm_audit audit_info;

	proto = pfkey_satype2proto(hdr->sadb_msg_satype);
	if (proto == 0)
		return -EINVAL;

	xfrm_state_flush(proto);
	audit_info.loginuid = audit_get_loginuid(current->audit_context);
	audit_info.secid = 0;
	xfrm_state_flush(proto, &audit_info);
	c.data.proto = proto;
	c.seq = hdr->sadb_msg_seq;
	c.pid = hdr->sadb_msg_pid;
@@ -2205,6 +2216,9 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, struct sadb_msg *h
	err = xfrm_policy_insert(pol->sadb_x_policy_dir-1, xp,
				 hdr->sadb_msg_type != SADB_X_SPDUPDATE);

	xfrm_audit_log(audit_get_loginuid(current->audit_context), 0,
		       AUDIT_MAC_IPSEC_ADDSPD, err ? 0 : 1, xp, NULL);

	if (err)
		goto out;

@@ -2282,6 +2296,10 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg
	xp = xfrm_policy_bysel_ctx(XFRM_POLICY_TYPE_MAIN, pol->sadb_x_policy_dir-1,
				   &sel, tmp.security, 1);
	security_xfrm_policy_free(&tmp);

	xfrm_audit_log(audit_get_loginuid(current->audit_context), 0,
		       AUDIT_MAC_IPSEC_DELSPD, (xp) ? 1 : 0, xp, NULL);

	if (xp == NULL)
		return -ENOENT;

@@ -2416,8 +2434,11 @@ static int key_notify_policy_flush(struct km_event *c)
static int pfkey_spdflush(struct sock *sk, struct sk_buff *skb, struct sadb_msg *hdr, void **ext_hdrs)
{
	struct km_event c;
	struct xfrm_audit audit_info;

	xfrm_policy_flush(XFRM_POLICY_TYPE_MAIN);
	audit_info.loginuid = audit_get_loginuid(current->audit_context);
	audit_info.secid = 0;
	xfrm_policy_flush(XFRM_POLICY_TYPE_MAIN, &audit_info);
	c.data.type = XFRM_POLICY_TYPE_MAIN;
	c.event = XFRM_MSG_FLUSHPOLICY;
	c.pid = hdr->sadb_msg_pid;
+119 −1
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
#include <linux/cache.h>
#include <net/xfrm.h>
#include <net/ip.h>
#include <linux/audit.h>

#include "xfrm_hash.h"

@@ -804,7 +805,7 @@ struct xfrm_policy *xfrm_policy_byid(u8 type, int dir, u32 id, int delete)
}
EXPORT_SYMBOL(xfrm_policy_byid);

void xfrm_policy_flush(u8 type)
void xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info)
{
	int dir;

@@ -824,6 +825,9 @@ void xfrm_policy_flush(u8 type)
			hlist_del(&pol->byidx);
			write_unlock_bh(&xfrm_policy_lock);

			xfrm_audit_log(audit_info->loginuid, audit_info->secid,
				       AUDIT_MAC_IPSEC_DELSPD, 1, pol, NULL);

			xfrm_policy_kill(pol);
			killed++;

@@ -842,6 +846,11 @@ void xfrm_policy_flush(u8 type)
				hlist_del(&pol->byidx);
				write_unlock_bh(&xfrm_policy_lock);

				xfrm_audit_log(audit_info->loginuid,
					       audit_info->secid,
					       AUDIT_MAC_IPSEC_DELSPD, 1,
					       pol, NULL);

				xfrm_policy_kill(pol);
				killed++;

@@ -1977,6 +1986,115 @@ int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *first,

EXPORT_SYMBOL(xfrm_bundle_ok);

/* Audit addition and deletion of SAs and ipsec policy */

void xfrm_audit_log(uid_t auid, u32 sid, int type, int result,
		    struct xfrm_policy *xp, struct xfrm_state *x)
{

	char *secctx;
	u32 secctx_len;
	struct xfrm_sec_ctx *sctx = NULL;
	struct audit_buffer *audit_buf;
	int family;
	extern int audit_enabled;

	if (audit_enabled == 0)
		return;

	audit_buf = audit_log_start(current->audit_context, GFP_ATOMIC, type);
	if (audit_buf == NULL)
	return;

	switch(type) {
	case AUDIT_MAC_IPSEC_ADDSA:
		audit_log_format(audit_buf, "SAD add: auid=%u", auid);
		break;
	case AUDIT_MAC_IPSEC_DELSA:
		audit_log_format(audit_buf, "SAD delete: auid=%u", auid);
		break;
	case AUDIT_MAC_IPSEC_ADDSPD:
		audit_log_format(audit_buf, "SPD add: auid=%u", auid);
		break;
	case AUDIT_MAC_IPSEC_DELSPD:
		audit_log_format(audit_buf, "SPD delete: auid=%u", auid);
		break;
	default:
		return;
	}

	if (sid != 0 &&
		security_secid_to_secctx(sid, &secctx, &secctx_len) == 0)
		audit_log_format(audit_buf, " subj=%s", secctx);
	else
		audit_log_task_context(audit_buf);

	if (xp) {
		family = xp->selector.family;
		if (xp->security)
			sctx = xp->security;
	} else {
		family = x->props.family;
		if (x->security)
			sctx = x->security;
	}

	if (sctx)
		audit_log_format(audit_buf,
				" sec_alg=%u sec_doi=%u sec_obj=%s",
				sctx->ctx_alg, sctx->ctx_doi, sctx->ctx_str);

	switch(family) {
	case AF_INET:
		{
			struct in_addr saddr, daddr;
			if (xp) {
				saddr.s_addr = xp->selector.saddr.a4;
				daddr.s_addr = xp->selector.daddr.a4;
			} else {
				saddr.s_addr = x->props.saddr.a4;
				daddr.s_addr = x->id.daddr.a4;
			}
			audit_log_format(audit_buf,
					 " src=%u.%u.%u.%u dst=%u.%u.%u.%u",
					 NIPQUAD(saddr), NIPQUAD(daddr));
		}
			break;
	case AF_INET6:
		{
			struct in6_addr saddr6, daddr6;
			if (xp) {
				memcpy(&saddr6, xp->selector.saddr.a6,
					sizeof(struct in6_addr));
				memcpy(&daddr6, xp->selector.daddr.a6,
					sizeof(struct in6_addr));
			} else {
				memcpy(&saddr6, x->props.saddr.a6,
					sizeof(struct in6_addr));
				memcpy(&daddr6, x->id.daddr.a6,
					sizeof(struct in6_addr));
			}
			audit_log_format(audit_buf,
					 " src=" NIP6_FMT "dst=" NIP6_FMT,
					 NIP6(saddr6), NIP6(daddr6));
		}
		break;
	}

	if (x)
		audit_log_format(audit_buf, " spi=%lu(0x%lx) protocol=%s",
				(unsigned long)ntohl(x->id.spi),
				(unsigned long)ntohl(x->id.spi),
				x->id.proto == IPPROTO_AH ? "AH" :
				(x->id.proto == IPPROTO_ESP ?
				"ESP" : "IPCOMP"));

	audit_log_format(audit_buf, " res=%u", result);
	audit_log_end(audit_buf);
}

EXPORT_SYMBOL(xfrm_audit_log);

int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
{
	int err = 0;
Loading