summaryrefslogtreecommitdiffstats
path: root/net/xfrm/xfrm_policy.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/xfrm/xfrm_policy.c')
-rw-r--r--net/xfrm/xfrm_policy.c236
1 files changed, 91 insertions, 145 deletions
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 157bfbd250b..af27c193697 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -25,8 +25,6 @@
#include <linux/cache.h>
#include <net/xfrm.h>
#include <net/ip.h>
-#include <linux/audit.h>
-#include <linux/cache.h>
#include "xfrm_hash.h"
@@ -851,13 +849,12 @@ xfrm_policy_flush_secctx_check(u8 type, struct xfrm_audit *audit_info)
continue;
err = security_xfrm_policy_delete(pol);
if (err) {
- xfrm_audit_log(audit_info->loginuid,
- audit_info->secid,
- AUDIT_MAC_IPSEC_DELSPD, 0,
- pol, NULL);
+ xfrm_audit_policy_delete(pol, 0,
+ audit_info->loginuid,
+ audit_info->secid);
return err;
}
- }
+ }
for (i = xfrm_policy_bydst[dir].hmask; i >= 0; i--) {
hlist_for_each_entry(pol, entry,
xfrm_policy_bydst[dir].table + i,
@@ -866,10 +863,9 @@ xfrm_policy_flush_secctx_check(u8 type, struct xfrm_audit *audit_info)
continue;
err = security_xfrm_policy_delete(pol);
if (err) {
- xfrm_audit_log(audit_info->loginuid,
- audit_info->secid,
- AUDIT_MAC_IPSEC_DELSPD,
- 0, pol, NULL);
+ xfrm_audit_policy_delete(pol, 0,
+ audit_info->loginuid,
+ audit_info->secid);
return err;
}
}
@@ -910,8 +906,8 @@ int xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info)
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_audit_policy_delete(pol, 1, audit_info->loginuid,
+ audit_info->secid);
xfrm_policy_kill(pol);
killed++;
@@ -931,11 +927,9 @@ int xfrm_policy_flush(u8 type, struct xfrm_audit *audit_info)
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_audit_policy_delete(pol, 1,
+ audit_info->loginuid,
+ audit_info->secid);
xfrm_policy_kill(pol);
killed++;
@@ -1299,7 +1293,8 @@ xfrm_tmpl_resolve_one(struct xfrm_policy *policy, struct flowi *fl,
xfrm_address_t *local = saddr;
struct xfrm_tmpl *tmpl = &policy->xfrm_vec[i];
- if (tmpl->mode == XFRM_MODE_TUNNEL) {
+ if (tmpl->mode == XFRM_MODE_TUNNEL ||
+ tmpl->mode == XFRM_MODE_BEET) {
remote = &tmpl->id.daddr;
local = &tmpl->saddr;
family = tmpl->encap_family;
@@ -1477,7 +1472,7 @@ restart:
pol_dead = 0;
xfrm_nr = 0;
- if (sk && sk->sk_policy[1]) {
+ if (sk && sk->sk_policy[XFRM_POLICY_OUT]) {
policy = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl);
if (IS_ERR(policy))
return PTR_ERR(policy);
@@ -1687,17 +1682,13 @@ static inline int
xfrm_secpath_reject(int idx, struct sk_buff *skb, struct flowi *fl)
{
struct xfrm_state *x;
- int err;
if (!skb->sp || idx < 0 || idx >= skb->sp->len)
return 0;
x = skb->sp->xvec[idx];
if (!x->type->reject)
return 0;
- xfrm_state_hold(x);
- err = x->type->reject(x, skb, fl);
- xfrm_state_put(x);
- return err;
+ return x->type->reject(x, skb, fl);
}
/* When skb is transformed back to its "native" form, we have to
@@ -1954,8 +1945,8 @@ static int stale_bundle(struct dst_entry *dst)
void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev)
{
while ((dst = dst->child) && dst->xfrm && dst->dev == dev) {
- dst->dev = &loopback_dev;
- dev_hold(&loopback_dev);
+ dst->dev = init_net.loopback_dev;
+ dev_hold(dst->dev);
dev_put(dev);
}
}
@@ -2141,7 +2132,7 @@ int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *first,
if (last == first)
break;
- last = last->u.next;
+ last = (struct xfrm_dst *)last->u.dst.next;
last->child_mtu_cached = mtu;
}
@@ -2150,122 +2141,6 @@ int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *first,
EXPORT_SYMBOL(xfrm_bundle_ok);
-#ifdef CONFIG_AUDITSYSCALL
-/* 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;
-
- BUG_ON((type == AUDIT_MAC_IPSEC_ADDSA ||
- type == AUDIT_MAC_IPSEC_DELSA) && !x);
- BUG_ON((type == AUDIT_MAC_IPSEC_ADDSPD ||
- type == AUDIT_MAC_IPSEC_DELSPD) && !xp);
-
- 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);
-#endif /* CONFIG_AUDITSYSCALL */
-
int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
{
int err = 0;
@@ -2357,6 +2232,11 @@ static void xfrm_policy_unlock_afinfo(struct xfrm_policy_afinfo *afinfo)
static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void *ptr)
{
+ struct net_device *dev = ptr;
+
+ if (dev->nd_net != &init_net)
+ return NOTIFY_DONE;
+
switch (event) {
case NETDEV_DOWN:
xfrm_flush_bundles();
@@ -2378,7 +2258,7 @@ static void __init xfrm_policy_init(void)
xfrm_dst_cache = kmem_cache_create("xfrm_dst_cache",
sizeof(struct xfrm_dst),
0, SLAB_HWCACHE_ALIGN|SLAB_PANIC,
- NULL, NULL);
+ NULL);
hmask = 8 - 1;
sz = (hmask+1) * sizeof(struct hlist_head);
@@ -2411,6 +2291,72 @@ void __init xfrm_init(void)
xfrm_input_init();
}
+#ifdef CONFIG_AUDITSYSCALL
+static inline void xfrm_audit_common_policyinfo(struct xfrm_policy *xp,
+ struct audit_buffer *audit_buf)
+{
+ if (xp->security)
+ audit_log_format(audit_buf, " sec_alg=%u sec_doi=%u sec_obj=%s",
+ xp->security->ctx_alg, xp->security->ctx_doi,
+ xp->security->ctx_str);
+
+ switch(xp->selector.family) {
+ case AF_INET:
+ audit_log_format(audit_buf, " src=%u.%u.%u.%u dst=%u.%u.%u.%u",
+ NIPQUAD(xp->selector.saddr.a4),
+ NIPQUAD(xp->selector.daddr.a4));
+ break;
+ case AF_INET6:
+ {
+ struct in6_addr saddr6, daddr6;
+
+ memcpy(&saddr6, xp->selector.saddr.a6,
+ sizeof(struct in6_addr));
+ memcpy(&daddr6, xp->selector.daddr.a6,
+ sizeof(struct in6_addr));
+ audit_log_format(audit_buf,
+ " src=" NIP6_FMT " dst=" NIP6_FMT,
+ NIP6(saddr6), NIP6(daddr6));
+ }
+ break;
+ }
+}
+
+void
+xfrm_audit_policy_add(struct xfrm_policy *xp, int result, u32 auid, u32 sid)
+{
+ struct audit_buffer *audit_buf;
+ extern int audit_enabled;
+
+ if (audit_enabled == 0)
+ return;
+ audit_buf = xfrm_audit_start(sid, auid);
+ if (audit_buf == NULL)
+ return;
+ audit_log_format(audit_buf, " op=SPD-add res=%u", result);
+ xfrm_audit_common_policyinfo(xp, audit_buf);
+ audit_log_end(audit_buf);
+}
+EXPORT_SYMBOL_GPL(xfrm_audit_policy_add);
+
+void
+xfrm_audit_policy_delete(struct xfrm_policy *xp, int result, u32 auid, u32 sid)
+{
+ struct audit_buffer *audit_buf;
+ extern int audit_enabled;
+
+ if (audit_enabled == 0)
+ return;
+ audit_buf = xfrm_audit_start(sid, auid);
+ if (audit_buf == NULL)
+ return;
+ audit_log_format(audit_buf, " op=SPD-delete res=%u", result);
+ xfrm_audit_common_policyinfo(xp, audit_buf);
+ audit_log_end(audit_buf);
+}
+EXPORT_SYMBOL_GPL(xfrm_audit_policy_delete);
+#endif
+
#ifdef CONFIG_XFRM_MIGRATE
static int xfrm_migrate_selector_match(struct xfrm_selector *sel_cmp,
struct xfrm_selector *sel_tgt)