|
@@ -123,9 +123,21 @@ static inline int verify_replay(struct xfrm_usersa_info *p,
|
|
|
struct nlattr **attrs)
|
|
|
{
|
|
|
struct nlattr *rt = attrs[XFRMA_REPLAY_ESN_VAL];
|
|
|
+ struct xfrm_replay_state_esn *rs;
|
|
|
|
|
|
- if ((p->flags & XFRM_STATE_ESN) && !rt)
|
|
|
- return -EINVAL;
|
|
|
+ if (p->flags & XFRM_STATE_ESN) {
|
|
|
+ if (!rt)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ rs = nla_data(rt);
|
|
|
+
|
|
|
+ if (rs->bmp_len > XFRMA_REPLAY_ESN_MAX / sizeof(rs->bmp[0]) / 8)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ if (nla_len(rt) < xfrm_replay_state_esn_len(rs) &&
|
|
|
+ nla_len(rt) != sizeof(*rs))
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
|
|
|
if (!rt)
|
|
|
return 0;
|
|
@@ -370,14 +382,15 @@ static inline int xfrm_replay_verify_len(struct xfrm_replay_state_esn *replay_es
|
|
|
struct nlattr *rp)
|
|
|
{
|
|
|
struct xfrm_replay_state_esn *up;
|
|
|
+ int ulen;
|
|
|
|
|
|
if (!replay_esn || !rp)
|
|
|
return 0;
|
|
|
|
|
|
up = nla_data(rp);
|
|
|
+ ulen = xfrm_replay_state_esn_len(up);
|
|
|
|
|
|
- if (xfrm_replay_state_esn_len(replay_esn) !=
|
|
|
- xfrm_replay_state_esn_len(up))
|
|
|
+ if (nla_len(rp) < ulen || xfrm_replay_state_esn_len(replay_esn) != ulen)
|
|
|
return -EINVAL;
|
|
|
|
|
|
return 0;
|
|
@@ -388,22 +401,28 @@ static int xfrm_alloc_replay_state_esn(struct xfrm_replay_state_esn **replay_esn
|
|
|
struct nlattr *rta)
|
|
|
{
|
|
|
struct xfrm_replay_state_esn *p, *pp, *up;
|
|
|
+ int klen, ulen;
|
|
|
|
|
|
if (!rta)
|
|
|
return 0;
|
|
|
|
|
|
up = nla_data(rta);
|
|
|
+ klen = xfrm_replay_state_esn_len(up);
|
|
|
+ ulen = nla_len(rta) >= klen ? klen : sizeof(*up);
|
|
|
|
|
|
- p = kmemdup(up, xfrm_replay_state_esn_len(up), GFP_KERNEL);
|
|
|
+ p = kzalloc(klen, GFP_KERNEL);
|
|
|
if (!p)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
- pp = kmemdup(up, xfrm_replay_state_esn_len(up), GFP_KERNEL);
|
|
|
+ pp = kzalloc(klen, GFP_KERNEL);
|
|
|
if (!pp) {
|
|
|
kfree(p);
|
|
|
return -ENOMEM;
|
|
|
}
|
|
|
|
|
|
+ memcpy(p, up, ulen);
|
|
|
+ memcpy(pp, up, ulen);
|
|
|
+
|
|
|
*replay_esn = p;
|
|
|
*preplay_esn = pp;
|
|
|
|
|
@@ -442,10 +461,11 @@ static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info *
|
|
|
* somehow made shareable and move it to xfrm_state.c - JHS
|
|
|
*
|
|
|
*/
|
|
|
-static void xfrm_update_ae_params(struct xfrm_state *x, struct nlattr **attrs)
|
|
|
+static void xfrm_update_ae_params(struct xfrm_state *x, struct nlattr **attrs,
|
|
|
+ int update_esn)
|
|
|
{
|
|
|
struct nlattr *rp = attrs[XFRMA_REPLAY_VAL];
|
|
|
- struct nlattr *re = attrs[XFRMA_REPLAY_ESN_VAL];
|
|
|
+ struct nlattr *re = update_esn ? attrs[XFRMA_REPLAY_ESN_VAL] : NULL;
|
|
|
struct nlattr *lt = attrs[XFRMA_LTIME_VAL];
|
|
|
struct nlattr *et = attrs[XFRMA_ETIMER_THRESH];
|
|
|
struct nlattr *rt = attrs[XFRMA_REPLAY_THRESH];
|
|
@@ -555,7 +575,7 @@ static struct xfrm_state *xfrm_state_construct(struct net *net,
|
|
|
goto error;
|
|
|
|
|
|
/* override default values from above */
|
|
|
- xfrm_update_ae_params(x, attrs);
|
|
|
+ xfrm_update_ae_params(x, attrs, 0);
|
|
|
|
|
|
return x;
|
|
|
|
|
@@ -689,6 +709,7 @@ out:
|
|
|
|
|
|
static void copy_to_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p)
|
|
|
{
|
|
|
+ memset(p, 0, sizeof(*p));
|
|
|
memcpy(&p->id, &x->id, sizeof(p->id));
|
|
|
memcpy(&p->sel, &x->sel, sizeof(p->sel));
|
|
|
memcpy(&p->lft, &x->lft, sizeof(p->lft));
|
|
@@ -742,7 +763,7 @@ static int copy_to_user_auth(struct xfrm_algo_auth *auth, struct sk_buff *skb)
|
|
|
return -EMSGSIZE;
|
|
|
|
|
|
algo = nla_data(nla);
|
|
|
- strcpy(algo->alg_name, auth->alg_name);
|
|
|
+ strncpy(algo->alg_name, auth->alg_name, sizeof(algo->alg_name));
|
|
|
memcpy(algo->alg_key, auth->alg_key, (auth->alg_key_len + 7) / 8);
|
|
|
algo->alg_key_len = auth->alg_key_len;
|
|
|
|
|
@@ -878,6 +899,7 @@ static struct sk_buff *xfrm_state_netlink(struct sk_buff *in_skb,
|
|
|
{
|
|
|
struct xfrm_dump_info info;
|
|
|
struct sk_buff *skb;
|
|
|
+ int err;
|
|
|
|
|
|
skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
|
|
|
if (!skb)
|
|
@@ -888,9 +910,10 @@ static struct sk_buff *xfrm_state_netlink(struct sk_buff *in_skb,
|
|
|
info.nlmsg_seq = seq;
|
|
|
info.nlmsg_flags = 0;
|
|
|
|
|
|
- if (dump_one_state(x, 0, &info)) {
|
|
|
+ err = dump_one_state(x, 0, &info);
|
|
|
+ if (err) {
|
|
|
kfree_skb(skb);
|
|
|
- return NULL;
|
|
|
+ return ERR_PTR(err);
|
|
|
}
|
|
|
|
|
|
return skb;
|
|
@@ -1317,6 +1340,7 @@ static void copy_from_user_policy(struct xfrm_policy *xp, struct xfrm_userpolicy
|
|
|
|
|
|
static void copy_to_user_policy(struct xfrm_policy *xp, struct xfrm_userpolicy_info *p, int dir)
|
|
|
{
|
|
|
+ memset(p, 0, sizeof(*p));
|
|
|
memcpy(&p->sel, &xp->selector, sizeof(p->sel));
|
|
|
memcpy(&p->lft, &xp->lft, sizeof(p->lft));
|
|
|
memcpy(&p->curlft, &xp->curlft, sizeof(p->curlft));
|
|
@@ -1421,6 +1445,7 @@ static int copy_to_user_tmpl(struct xfrm_policy *xp, struct sk_buff *skb)
|
|
|
struct xfrm_user_tmpl *up = &vec[i];
|
|
|
struct xfrm_tmpl *kp = &xp->xfrm_vec[i];
|
|
|
|
|
|
+ memset(up, 0, sizeof(*up));
|
|
|
memcpy(&up->id, &kp->id, sizeof(up->id));
|
|
|
up->family = kp->encap_family;
|
|
|
memcpy(&up->saddr, &kp->saddr, sizeof(up->saddr));
|
|
@@ -1546,6 +1571,7 @@ static struct sk_buff *xfrm_policy_netlink(struct sk_buff *in_skb,
|
|
|
{
|
|
|
struct xfrm_dump_info info;
|
|
|
struct sk_buff *skb;
|
|
|
+ int err;
|
|
|
|
|
|
skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
|
|
if (!skb)
|
|
@@ -1556,9 +1582,10 @@ static struct sk_buff *xfrm_policy_netlink(struct sk_buff *in_skb,
|
|
|
info.nlmsg_seq = seq;
|
|
|
info.nlmsg_flags = 0;
|
|
|
|
|
|
- if (dump_one_policy(xp, dir, 0, &info) < 0) {
|
|
|
+ err = dump_one_policy(xp, dir, 0, &info);
|
|
|
+ if (err) {
|
|
|
kfree_skb(skb);
|
|
|
- return NULL;
|
|
|
+ return ERR_PTR(err);
|
|
|
}
|
|
|
|
|
|
return skb;
|
|
@@ -1822,7 +1849,7 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
|
|
|
goto out;
|
|
|
|
|
|
spin_lock_bh(&x->lock);
|
|
|
- xfrm_update_ae_params(x, attrs);
|
|
|
+ xfrm_update_ae_params(x, attrs, 1);
|
|
|
spin_unlock_bh(&x->lock);
|
|
|
|
|
|
c.event = nlh->nlmsg_type;
|