return 0;
}
+static int verify_encap_tmpl(struct rtattr **xfrma)
+{
+ struct rtattr *rt = xfrma[XFRMA_ENCAP - 1];
+ struct xfrm_encap_tmpl *encap;
+
+ if (!rt)
+ return 0;
+
+ if ((rt->rta_len - sizeof(*rt)) < sizeof(*encap))
+ return -EINVAL;
+
+ return 0;
+}
+
static int verify_newsa_info(struct xfrm_usersa_info *p,
struct rtattr **xfrma)
{
goto out;
if ((err = verify_one_alg(xfrma, XFRMA_ALG_COMP)))
goto out;
+ if ((err = verify_encap_tmpl(xfrma)))
+ goto out;
err = -EINVAL;
switch (p->mode) {
return 0;
}
+static int attach_encap_tmpl(struct xfrm_encap_tmpl **encapp, struct rtattr *u_arg)
+{
+ struct rtattr *rta = u_arg;
+ struct xfrm_encap_tmpl *p, *uencap;
+
+ if (!rta)
+ return 0;
+
+ uencap = RTA_DATA(rta);
+ p = kmalloc(sizeof(*p), GFP_KERNEL);
+ if (!p)
+ return -ENOMEM;
+
+ memcpy(p, uencap, sizeof(*p));
+ *encapp = p;
+ return 0;
+}
+
static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p)
{
memcpy(&x->id, &p->id, sizeof(x->id));
goto error;
if ((err = attach_one_algo(&x->calg, xfrma[XFRMA_ALG_COMP-1])))
goto error;
+ if ((err = attach_encap_tmpl(&x->encap, xfrma[XFRMA_ENCAP-1])))
+ goto error;
err = -ENOENT;
x->type = xfrm_get_type(x->id.proto, x->props.family);
if (x->calg)
RTA_PUT(skb, XFRMA_ALG_COMP, sizeof(*(x->calg)), x->calg);
+ if (x->encap)
+ RTA_PUT(skb, XFRMA_ENCAP, sizeof(*x->encap), x->encap);
+
nlh->nlmsg_len = skb->tail - b;
out:
sp->this_idx++;