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