]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/xfrm/xfrm_user.c
Pull bugfix into test branch
[linux-2.6-omap-h63xx.git] / net / xfrm / xfrm_user.c
index 6f97665983d274f60509109450d441c2b602b953..e5372b11fc8f105bd4ecf6071c0418f71855760c 100644 (file)
@@ -31,6 +31,7 @@
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
 #include <linux/in6.h>
 #endif
+#include <linux/audit.h>
 
 static int verify_one_alg(struct rtattr **xfrma, enum xfrm_attr_type_t type)
 {
@@ -454,6 +455,9 @@ static int xfrm_add_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
        else
                err = xfrm_state_update(x);
 
+       xfrm_audit_log(NETLINK_CB(skb).loginuid, NETLINK_CB(skb).sid,
+                      AUDIT_MAC_IPSEC_ADDSA, err ? 0 : 1, NULL, x);
+
        if (err < 0) {
                x->km.state = XFRM_STATE_DEAD;
                __xfrm_state_put(x);
@@ -523,6 +527,10 @@ static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma)
        }
 
        err = xfrm_state_delete(x);
+
+       xfrm_audit_log(NETLINK_CB(skb).loginuid, NETLINK_CB(skb).sid,
+                      AUDIT_MAC_IPSEC_DELSA, err ? 0 : 1, NULL, x);
+
        if (err < 0)
                goto out;
 
@@ -858,7 +866,6 @@ static void copy_templates(struct xfrm_policy *xp, struct xfrm_user_tmpl *ut,
        int i;
 
        xp->xfrm_nr = nr;
-       xp->family = ut->family;
        for (i = 0; i < nr; i++, ut++) {
                struct xfrm_tmpl *t = &xp->xfrm_vec[i];
 
@@ -876,19 +883,53 @@ static void copy_templates(struct xfrm_policy *xp, struct xfrm_user_tmpl *ut,
        }
 }
 
+static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family)
+{
+       int i;
+
+       if (nr > XFRM_MAX_DEPTH)
+               return -EINVAL;
+
+       for (i = 0; i < nr; i++) {
+               /* We never validated the ut->family value, so many
+                * applications simply leave it at zero.  The check was
+                * never made and ut->family was ignored because all
+                * templates could be assumed to have the same family as
+                * the policy itself.  Now that we will have ipv4-in-ipv6
+                * and ipv6-in-ipv4 tunnels, this is no longer true.
+                */
+               if (!ut[i].family)
+                       ut[i].family = family;
+
+               switch (ut[i].family) {
+               case AF_INET:
+                       break;
+#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
+               case AF_INET6:
+                       break;
+#endif
+               default:
+                       return -EINVAL;
+               };
+       }
+
+       return 0;
+}
+
 static int copy_from_user_tmpl(struct xfrm_policy *pol, struct rtattr **xfrma)
 {
        struct rtattr *rt = xfrma[XFRMA_TMPL-1];
-       struct xfrm_user_tmpl *utmpl;
-       int nr;
 
        if (!rt) {
                pol->xfrm_nr = 0;
        } else {
-               nr = (rt->rta_len - sizeof(*rt)) / sizeof(*utmpl);
+               struct xfrm_user_tmpl *utmpl = RTA_DATA(rt);
+               int nr = (rt->rta_len - sizeof(*rt)) / sizeof(*utmpl);
+               int err;
 
-               if (nr > XFRM_MAX_DEPTH)
-                       return -EINVAL;
+               err = validate_tmpl(nr, utmpl, pol->family);
+               if (err)
+                       return err;
 
                copy_templates(pol, RTA_DATA(rt), nr);
        }
@@ -997,6 +1038,9 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr
         * a type XFRM_MSG_UPDPOLICY - JHS */
        excl = nlh->nlmsg_type == XFRM_MSG_NEWPOLICY;
        err = xfrm_policy_insert(p->dir, xp, excl);
+       xfrm_audit_log(NETLINK_CB(skb).loginuid, NETLINK_CB(skb).sid,
+                      AUDIT_MAC_IPSEC_DELSPD, err ? 0 : 1, xp, NULL);
+
        if (err) {
                security_xfrm_policy_free(xp);
                kfree(xp);
@@ -1224,6 +1268,10 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfr
                xp = xfrm_policy_bysel_ctx(type, p->dir, &p->sel, tmp.security, delete);
                security_xfrm_policy_free(&tmp);
        }
+       if (delete)
+               xfrm_audit_log(NETLINK_CB(skb).loginuid, NETLINK_CB(skb).sid,
+                              AUDIT_MAC_IPSEC_DELSPD, (xp) ? 1 : 0, xp, NULL);
+
        if (xp == NULL)
                return -ENOENT;
 
@@ -1258,8 +1306,11 @@ static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh, void **xfrma
 {
        struct km_event c;
        struct xfrm_usersa_flush *p = NLMSG_DATA(nlh);
+       struct xfrm_audit audit_info;
 
-       xfrm_state_flush(p->proto);
+       audit_info.loginuid = NETLINK_CB(skb).loginuid;
+       audit_info.secid = NETLINK_CB(skb).sid;
+       xfrm_state_flush(p->proto, &audit_info);
        c.data.proto = p->proto;
        c.event = nlh->nlmsg_type;
        c.seq = nlh->nlmsg_seq;
@@ -1409,12 +1460,15 @@ static int xfrm_flush_policy(struct sk_buff *skb, struct nlmsghdr *nlh, void **x
        struct km_event c;
        u8 type = XFRM_POLICY_TYPE_MAIN;
        int err;
+       struct xfrm_audit audit_info;
 
        err = copy_from_user_policy_type(&type, (struct rtattr **)xfrma);
        if (err)
                return err;
 
-       xfrm_policy_flush(type);
+       audit_info.loginuid = NETLINK_CB(skb).loginuid;
+       audit_info.secid = NETLINK_CB(skb).sid;
+       xfrm_policy_flush(type, &audit_info);
        c.data.type = type;
        c.event = nlh->nlmsg_type;
        c.seq = nlh->nlmsg_seq;
@@ -1469,6 +1523,9 @@ static int xfrm_add_pol_expire(struct sk_buff *skb, struct nlmsghdr *nlh, void *
        err = 0;
        if (up->hard) {
                xfrm_policy_delete(xp, p->dir);
+               xfrm_audit_log(NETLINK_CB(skb).loginuid, NETLINK_CB(skb).sid,
+                               AUDIT_MAC_IPSEC_DELSPD, 1, xp, NULL);
+
        } else {
                // reset the timers here?
                printk("Dont know what to do with soft policy expire\n");
@@ -1500,8 +1557,11 @@ static int xfrm_add_sa_expire(struct sk_buff *skb, struct nlmsghdr *nlh, void **
                goto out;
        km_state_expired(x, ue->hard, current->pid);
 
-       if (ue->hard)
+       if (ue->hard) {
                __xfrm_state_delete(x);
+               xfrm_audit_log(NETLINK_CB(skb).loginuid, NETLINK_CB(skb).sid,
+                              AUDIT_MAC_IPSEC_DELSA, 1, NULL, x);
+       }
 out:
        spin_unlock_bh(&x->lock);
        xfrm_state_put(x);
@@ -1530,7 +1590,8 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh, void **xf
        }
 
        /*   build an XP */
-       xp = xfrm_policy_construct(&ua->policy, (struct rtattr **) xfrma, &err);        if (!xp) {
+       xp = xfrm_policy_construct(&ua->policy, (struct rtattr **) xfrma, &err);
+       if (!xp) {
                kfree(x);
                return err;
        }
@@ -1979,7 +2040,7 @@ static struct xfrm_policy *xfrm_compile_policy(struct sock *sk, int opt,
                return NULL;
 
        nr = ((len - sizeof(*p)) / sizeof(*ut));
-       if (nr > XFRM_MAX_DEPTH)
+       if (validate_tmpl(nr, ut, p->sel.family))
                return NULL;
 
        if (p->dir > XFRM_POLICY_OUT)