[XFRM]: Audit function arguments misordered
[pandora-kernel.git] / net / xfrm / xfrm_policy.c
index 7012891..26b846e 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/netfilter.h>
 #include <linux/module.h>
 #include <linux/cache.h>
-#include <linux/audit.h>
 #include <net/xfrm.h>
 #include <net/ip.h>
 
@@ -50,8 +49,6 @@ static DEFINE_SPINLOCK(xfrm_policy_gc_lock);
 
 static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family);
 static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo);
-static struct xfrm_policy_afinfo *xfrm_policy_lock_afinfo(unsigned int family);
-static void xfrm_policy_unlock_afinfo(struct xfrm_policy_afinfo *afinfo);
 
 static inline int
 __xfrm4_selector_match(struct xfrm_selector *sel, struct flowi *fl)
@@ -87,72 +84,6 @@ int xfrm_selector_match(struct xfrm_selector *sel, struct flowi *fl,
        return 0;
 }
 
-int xfrm_register_type(struct xfrm_type *type, unsigned short family)
-{
-       struct xfrm_policy_afinfo *afinfo = xfrm_policy_lock_afinfo(family);
-       struct xfrm_type **typemap;
-       int err = 0;
-
-       if (unlikely(afinfo == NULL))
-               return -EAFNOSUPPORT;
-       typemap = afinfo->type_map;
-
-       if (likely(typemap[type->proto] == NULL))
-               typemap[type->proto] = type;
-       else
-               err = -EEXIST;
-       xfrm_policy_unlock_afinfo(afinfo);
-       return err;
-}
-EXPORT_SYMBOL(xfrm_register_type);
-
-int xfrm_unregister_type(struct xfrm_type *type, unsigned short family)
-{
-       struct xfrm_policy_afinfo *afinfo = xfrm_policy_lock_afinfo(family);
-       struct xfrm_type **typemap;
-       int err = 0;
-
-       if (unlikely(afinfo == NULL))
-               return -EAFNOSUPPORT;
-       typemap = afinfo->type_map;
-
-       if (unlikely(typemap[type->proto] != type))
-               err = -ENOENT;
-       else
-               typemap[type->proto] = NULL;
-       xfrm_policy_unlock_afinfo(afinfo);
-       return err;
-}
-EXPORT_SYMBOL(xfrm_unregister_type);
-
-struct xfrm_type *xfrm_get_type(u8 proto, unsigned short family)
-{
-       struct xfrm_policy_afinfo *afinfo;
-       struct xfrm_type **typemap;
-       struct xfrm_type *type;
-       int modload_attempted = 0;
-
-retry:
-       afinfo = xfrm_policy_get_afinfo(family);
-       if (unlikely(afinfo == NULL))
-               return NULL;
-       typemap = afinfo->type_map;
-
-       type = typemap[proto];
-       if (unlikely(type && !try_module_get(type->owner)))
-               type = NULL;
-       if (!type && !modload_attempted) {
-               xfrm_policy_put_afinfo(afinfo);
-               request_module("xfrm-type-%d-%d",
-                              (int) family, (int) proto);
-               modload_attempted = 1;
-               goto retry;
-       }
-
-       xfrm_policy_put_afinfo(afinfo);
-       return type;
-}
-
 int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl,
                    unsigned short family)
 {
@@ -171,94 +102,6 @@ int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl,
 }
 EXPORT_SYMBOL(xfrm_dst_lookup);
 
-void xfrm_put_type(struct xfrm_type *type)
-{
-       module_put(type->owner);
-}
-
-int xfrm_register_mode(struct xfrm_mode *mode, int family)
-{
-       struct xfrm_policy_afinfo *afinfo;
-       struct xfrm_mode **modemap;
-       int err;
-
-       if (unlikely(mode->encap >= XFRM_MODE_MAX))
-               return -EINVAL;
-
-       afinfo = xfrm_policy_lock_afinfo(family);
-       if (unlikely(afinfo == NULL))
-               return -EAFNOSUPPORT;
-
-       err = -EEXIST;
-       modemap = afinfo->mode_map;
-       if (likely(modemap[mode->encap] == NULL)) {
-               modemap[mode->encap] = mode;
-               err = 0;
-       }
-
-       xfrm_policy_unlock_afinfo(afinfo);
-       return err;
-}
-EXPORT_SYMBOL(xfrm_register_mode);
-
-int xfrm_unregister_mode(struct xfrm_mode *mode, int family)
-{
-       struct xfrm_policy_afinfo *afinfo;
-       struct xfrm_mode **modemap;
-       int err;
-
-       if (unlikely(mode->encap >= XFRM_MODE_MAX))
-               return -EINVAL;
-
-       afinfo = xfrm_policy_lock_afinfo(family);
-       if (unlikely(afinfo == NULL))
-               return -EAFNOSUPPORT;
-
-       err = -ENOENT;
-       modemap = afinfo->mode_map;
-       if (likely(modemap[mode->encap] == mode)) {
-               modemap[mode->encap] = NULL;
-               err = 0;
-       }
-
-       xfrm_policy_unlock_afinfo(afinfo);
-       return err;
-}
-EXPORT_SYMBOL(xfrm_unregister_mode);
-
-struct xfrm_mode *xfrm_get_mode(unsigned int encap, int family)
-{
-       struct xfrm_policy_afinfo *afinfo;
-       struct xfrm_mode *mode;
-       int modload_attempted = 0;
-
-       if (unlikely(encap >= XFRM_MODE_MAX))
-               return NULL;
-
-retry:
-       afinfo = xfrm_policy_get_afinfo(family);
-       if (unlikely(afinfo == NULL))
-               return NULL;
-
-       mode = afinfo->mode_map[encap];
-       if (unlikely(mode && !try_module_get(mode->owner)))
-               mode = NULL;
-       if (!mode && !modload_attempted) {
-               xfrm_policy_put_afinfo(afinfo);
-               request_module("xfrm-mode-%d-%d", family, encap);
-               modload_attempted = 1;
-               goto retry;
-       }
-
-       xfrm_policy_put_afinfo(afinfo);
-       return mode;
-}
-
-void xfrm_put_mode(struct xfrm_mode *mode)
-{
-       module_put(mode->owner);
-}
-
 static inline unsigned long make_jiffies(long secs)
 {
        if (secs >= (MAX_SCHEDULE_TIMEOUT-1)/HZ)
@@ -850,10 +693,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;
                        }
                }
@@ -865,10 +707,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;
                                }
                        }
@@ -909,8 +750,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++;
@@ -930,11 +771,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++;
 
@@ -1477,10 +1316,11 @@ 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);
+               err = PTR_ERR(policy);
                if (IS_ERR(policy))
-                       return PTR_ERR(policy);
+                       goto dropdst;
        }
 
        if (!policy) {
@@ -1491,8 +1331,9 @@ restart:
 
                policy = flow_cache_lookup(fl, dst_orig->ops->family,
                                           dir, xfrm_policy_lookup);
+               err = PTR_ERR(policy);
                if (IS_ERR(policy))
-                       return PTR_ERR(policy);
+                       goto dropdst;
        }
 
        if (!policy)
@@ -1505,6 +1346,7 @@ restart:
        xfrm_nr += pols[0]->xfrm_nr;
 
        switch (policy->action) {
+       default:
        case XFRM_POLICY_BLOCK:
                /* Prohibit the flow */
                err = -EPERM;
@@ -1661,8 +1503,9 @@ restart:
        return 0;
 
 error:
-       dst_release(dst_orig);
        xfrm_pols_put(pols, npols);
+dropdst:
+       dst_release(dst_orig);
        *dst_p = NULL;
        return err;
 }
@@ -1687,17 +1530,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 +1793,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);
        }
 }
@@ -2105,7 +1944,8 @@ int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *first,
                if (xdst->genid != dst->xfrm->genid)
                        return 0;
 
-               if (strict && fl && dst->xfrm->props.mode != XFRM_MODE_TUNNEL &&
+               if (strict && fl &&
+                   !(dst->xfrm->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) &&
                    !xfrm_state_addr_flow_check(dst->xfrm, fl, family))
                        return 0;
 
@@ -2150,123 +1990,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);
-               security_release_secctx(secctx, secctx_len);
-       } 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;
@@ -2339,25 +2062,13 @@ static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo)
        read_unlock(&xfrm_policy_afinfo_lock);
 }
 
-static struct xfrm_policy_afinfo *xfrm_policy_lock_afinfo(unsigned int family)
+static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void *ptr)
 {
-       struct xfrm_policy_afinfo *afinfo;
-       if (unlikely(family >= NPROTO))
-               return NULL;
-       write_lock_bh(&xfrm_policy_afinfo_lock);
-       afinfo = xfrm_policy_afinfo[family];
-       if (unlikely(!afinfo))
-               write_unlock_bh(&xfrm_policy_afinfo_lock);
-       return afinfo;
-}
+       struct net_device *dev = ptr;
 
-static void xfrm_policy_unlock_afinfo(struct xfrm_policy_afinfo *afinfo)
-{
-       write_unlock_bh(&xfrm_policy_afinfo_lock);
-}
+       if (dev->nd_net != &init_net)
+               return NOTIFY_DONE;
 
-static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void *ptr)
-{
        switch (event) {
        case NETDEV_DOWN:
                xfrm_flush_bundles();
@@ -2412,6 +2123,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(auid, sid);
+       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(auid, sid);
+       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)
@@ -2519,7 +2296,8 @@ static int xfrm_policy_migrate(struct xfrm_policy *pol,
                        if (!migrate_tmpl_match(mp, &pol->xfrm_vec[i]))
                                continue;
                        n++;
-                       if (pol->xfrm_vec[i].mode != XFRM_MODE_TUNNEL)
+                       if (pol->xfrm_vec[i].mode != XFRM_MODE_TUNNEL &&
+                           pol->xfrm_vec[i].mode != XFRM_MODE_BEET)
                                continue;
                        /* update endpoints */
                        memcpy(&pol->xfrm_vec[i].id.daddr, &mp->new_daddr,