|
@@ -66,6 +66,10 @@ struct pfkey_sock {
|
|
|
struct mutex dump_lock;
|
|
|
};
|
|
|
|
|
|
+static int parse_sockaddr_pair(struct sockaddr *sa, int ext_len,
|
|
|
+ xfrm_address_t *saddr, xfrm_address_t *daddr,
|
|
|
+ u16 *family);
|
|
|
+
|
|
|
static inline struct pfkey_sock *pfkey_sk(struct sock *sk)
|
|
|
{
|
|
|
return (struct pfkey_sock *)sk;
|
|
@@ -1939,19 +1943,14 @@ parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq)
|
|
|
|
|
|
/* addresses present only in tunnel mode */
|
|
|
if (t->mode == XFRM_MODE_TUNNEL) {
|
|
|
- u8 *sa = (u8 *) (rq + 1);
|
|
|
- int family, socklen;
|
|
|
+ int err;
|
|
|
|
|
|
- family = pfkey_sockaddr_extract((struct sockaddr *)sa,
|
|
|
- &t->saddr);
|
|
|
- if (!family)
|
|
|
- return -EINVAL;
|
|
|
-
|
|
|
- socklen = pfkey_sockaddr_len(family);
|
|
|
- if (pfkey_sockaddr_extract((struct sockaddr *)(sa + socklen),
|
|
|
- &t->id.daddr) != family)
|
|
|
- return -EINVAL;
|
|
|
- t->encap_family = family;
|
|
|
+ err = parse_sockaddr_pair(
|
|
|
+ (struct sockaddr *)(rq + 1),
|
|
|
+ rq->sadb_x_ipsecrequest_len - sizeof(*rq),
|
|
|
+ &t->saddr, &t->id.daddr, &t->encap_family);
|
|
|
+ if (err)
|
|
|
+ return err;
|
|
|
} else
|
|
|
t->encap_family = xp->family;
|
|
|
|
|
@@ -1971,7 +1970,11 @@ parse_ipsecrequests(struct xfrm_policy *xp, struct sadb_x_policy *pol)
|
|
|
if (pol->sadb_x_policy_len * 8 < sizeof(struct sadb_x_policy))
|
|
|
return -EINVAL;
|
|
|
|
|
|
- while (len >= sizeof(struct sadb_x_ipsecrequest)) {
|
|
|
+ while (len >= sizeof(*rq)) {
|
|
|
+ if (len < rq->sadb_x_ipsecrequest_len ||
|
|
|
+ rq->sadb_x_ipsecrequest_len < sizeof(*rq))
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
if ((err = parse_ipsecrequest(xp, rq)) < 0)
|
|
|
return err;
|
|
|
len -= rq->sadb_x_ipsecrequest_len;
|
|
@@ -2434,7 +2437,6 @@ out:
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
-#ifdef CONFIG_NET_KEY_MIGRATE
|
|
|
static int pfkey_sockaddr_pair_size(sa_family_t family)
|
|
|
{
|
|
|
return PFKEY_ALIGN8(pfkey_sockaddr_len(family) * 2);
|
|
@@ -2446,7 +2448,7 @@ static int parse_sockaddr_pair(struct sockaddr *sa, int ext_len,
|
|
|
{
|
|
|
int af, socklen;
|
|
|
|
|
|
- if (ext_len < pfkey_sockaddr_pair_size(sa->sa_family))
|
|
|
+ if (ext_len < 2 || ext_len < pfkey_sockaddr_pair_size(sa->sa_family))
|
|
|
return -EINVAL;
|
|
|
|
|
|
af = pfkey_sockaddr_extract(sa, saddr);
|
|
@@ -2462,6 +2464,7 @@ static int parse_sockaddr_pair(struct sockaddr *sa, int ext_len,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+#ifdef CONFIG_NET_KEY_MIGRATE
|
|
|
static int ipsecrequests_to_migrate(struct sadb_x_ipsecrequest *rq1, int len,
|
|
|
struct xfrm_migrate *m)
|
|
|
{
|
|
@@ -2469,13 +2472,14 @@ static int ipsecrequests_to_migrate(struct sadb_x_ipsecrequest *rq1, int len,
|
|
|
struct sadb_x_ipsecrequest *rq2;
|
|
|
int mode;
|
|
|
|
|
|
- if (len <= sizeof(struct sadb_x_ipsecrequest) ||
|
|
|
- len < rq1->sadb_x_ipsecrequest_len)
|
|
|
+ if (len < sizeof(*rq1) ||
|
|
|
+ len < rq1->sadb_x_ipsecrequest_len ||
|
|
|
+ rq1->sadb_x_ipsecrequest_len < sizeof(*rq1))
|
|
|
return -EINVAL;
|
|
|
|
|
|
/* old endoints */
|
|
|
err = parse_sockaddr_pair((struct sockaddr *)(rq1 + 1),
|
|
|
- rq1->sadb_x_ipsecrequest_len,
|
|
|
+ rq1->sadb_x_ipsecrequest_len - sizeof(*rq1),
|
|
|
&m->old_saddr, &m->old_daddr,
|
|
|
&m->old_family);
|
|
|
if (err)
|
|
@@ -2484,13 +2488,14 @@ static int ipsecrequests_to_migrate(struct sadb_x_ipsecrequest *rq1, int len,
|
|
|
rq2 = (struct sadb_x_ipsecrequest *)((u8 *)rq1 + rq1->sadb_x_ipsecrequest_len);
|
|
|
len -= rq1->sadb_x_ipsecrequest_len;
|
|
|
|
|
|
- if (len <= sizeof(struct sadb_x_ipsecrequest) ||
|
|
|
- len < rq2->sadb_x_ipsecrequest_len)
|
|
|
+ if (len <= sizeof(*rq2) ||
|
|
|
+ len < rq2->sadb_x_ipsecrequest_len ||
|
|
|
+ rq2->sadb_x_ipsecrequest_len < sizeof(*rq2))
|
|
|
return -EINVAL;
|
|
|
|
|
|
/* new endpoints */
|
|
|
err = parse_sockaddr_pair((struct sockaddr *)(rq2 + 1),
|
|
|
- rq2->sadb_x_ipsecrequest_len,
|
|
|
+ rq2->sadb_x_ipsecrequest_len - sizeof(*rq2),
|
|
|
&m->new_saddr, &m->new_daddr,
|
|
|
&m->new_family);
|
|
|
if (err)
|