|
@@ -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;
|
|
|
|