]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - net/xfrm/xfrm_state.c
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec...
[karo-tx-linux.git] / net / xfrm / xfrm_state.c
index 2e291bc5f1fc1003ca62e40f67da8a6a46875c02..4a28f669c915cd5721d45f7de1dd77ac1072874c 100644 (file)
@@ -1309,7 +1309,8 @@ out:
 EXPORT_SYMBOL(xfrm_state_add);
 
 #ifdef CONFIG_XFRM_MIGRATE
-static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig)
+static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig,
+                                          struct xfrm_encap_tmpl *encap)
 {
        struct net *net = xs_net(orig);
        struct xfrm_state *x = xfrm_state_alloc(net);
@@ -1351,8 +1352,14 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig)
        }
        x->props.calgo = orig->props.calgo;
 
-       if (orig->encap) {
-               x->encap = kmemdup(orig->encap, sizeof(*x->encap), GFP_KERNEL);
+       if (encap || orig->encap) {
+               if (encap)
+                       x->encap = kmemdup(encap, sizeof(*x->encap),
+                                       GFP_KERNEL);
+               else
+                       x->encap = kmemdup(orig->encap, sizeof(*x->encap),
+                                       GFP_KERNEL);
+
                if (!x->encap)
                        goto error;
        }
@@ -1442,11 +1449,12 @@ struct xfrm_state *xfrm_migrate_state_find(struct xfrm_migrate *m, struct net *n
 EXPORT_SYMBOL(xfrm_migrate_state_find);
 
 struct xfrm_state *xfrm_state_migrate(struct xfrm_state *x,
-                                     struct xfrm_migrate *m)
+                                     struct xfrm_migrate *m,
+                                     struct xfrm_encap_tmpl *encap)
 {
        struct xfrm_state *xc;
 
-       xc = xfrm_state_clone(x);
+       xc = xfrm_state_clone(x, encap);
        if (!xc)
                return NULL;
 
@@ -1958,7 +1966,8 @@ EXPORT_SYMBOL(km_policy_expired);
 #ifdef CONFIG_XFRM_MIGRATE
 int km_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
               const struct xfrm_migrate *m, int num_migrate,
-              const struct xfrm_kmaddress *k)
+              const struct xfrm_kmaddress *k,
+              const struct xfrm_encap_tmpl *encap)
 {
        int err = -EINVAL;
        int ret;
@@ -1967,7 +1976,8 @@ int km_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
        rcu_read_lock();
        list_for_each_entry_rcu(km, &xfrm_km_list, list) {
                if (km->migrate) {
-                       ret = km->migrate(sel, dir, type, m, num_migrate, k);
+                       ret = km->migrate(sel, dir, type, m, num_migrate, k,
+                                         encap);
                        if (!ret)
                                err = ret;
                }
@@ -2025,13 +2035,9 @@ int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen
        if (optlen <= 0 || optlen > PAGE_SIZE)
                return -EMSGSIZE;
 
-       data = kmalloc(optlen, GFP_KERNEL);
-       if (!data)
-               return -ENOMEM;
-
-       err = -EFAULT;
-       if (copy_from_user(data, optval, optlen))
-               goto out;
+       data = memdup_user(optval, optlen);
+       if (IS_ERR(data))
+               return PTR_ERR(data);
 
        err = -EINVAL;
        rcu_read_lock();
@@ -2049,7 +2055,6 @@ int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen
                err = 0;
        }
 
-out:
        kfree(data);
        return err;
 }