Skip to content

Commit 8fe533c

Browse files
herbertxgregkh
authored andcommitted
af_key: Fix send_acquire race with pfkey_register
[ Upstream commit 7f57f81 ] The function pfkey_send_acquire may race with pfkey_register (which could even be in a different name space). This may result in a buffer overrun. Allocating the maximum amount of memory that could be used prevents this. Reported-by: [email protected] Fixes: 1da177e ("Linux-2.6.12-rc2") Signed-off-by: Herbert Xu <[email protected]> Reviewed-by: Sabrina Dubroca <[email protected]> Reviewed-by: Eric Dumazet <[email protected]> Signed-off-by: Steffen Klassert <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent 0c69a46 commit 8fe533c

File tree

1 file changed

+22
-10
lines changed

1 file changed

+22
-10
lines changed

net/key/af_key.c

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2905,7 +2905,7 @@ static int count_ah_combs(const struct xfrm_tmpl *t)
29052905
break;
29062906
if (!aalg->pfkey_supported)
29072907
continue;
2908-
if (aalg_tmpl_set(t, aalg) && aalg->available)
2908+
if (aalg_tmpl_set(t, aalg))
29092909
sz += sizeof(struct sadb_comb);
29102910
}
29112911
return sz + sizeof(struct sadb_prop);
@@ -2923,7 +2923,7 @@ static int count_esp_combs(const struct xfrm_tmpl *t)
29232923
if (!ealg->pfkey_supported)
29242924
continue;
29252925

2926-
if (!(ealg_tmpl_set(t, ealg) && ealg->available))
2926+
if (!(ealg_tmpl_set(t, ealg)))
29272927
continue;
29282928

29292929
for (k = 1; ; k++) {
@@ -2934,16 +2934,17 @@ static int count_esp_combs(const struct xfrm_tmpl *t)
29342934
if (!aalg->pfkey_supported)
29352935
continue;
29362936

2937-
if (aalg_tmpl_set(t, aalg) && aalg->available)
2937+
if (aalg_tmpl_set(t, aalg))
29382938
sz += sizeof(struct sadb_comb);
29392939
}
29402940
}
29412941
return sz + sizeof(struct sadb_prop);
29422942
}
29432943

2944-
static void dump_ah_combs(struct sk_buff *skb, const struct xfrm_tmpl *t)
2944+
static int dump_ah_combs(struct sk_buff *skb, const struct xfrm_tmpl *t)
29452945
{
29462946
struct sadb_prop *p;
2947+
int sz = 0;
29472948
int i;
29482949

29492950
p = skb_put(skb, sizeof(struct sadb_prop));
@@ -2971,13 +2972,17 @@ static void dump_ah_combs(struct sk_buff *skb, const struct xfrm_tmpl *t)
29712972
c->sadb_comb_soft_addtime = 20*60*60;
29722973
c->sadb_comb_hard_usetime = 8*60*60;
29732974
c->sadb_comb_soft_usetime = 7*60*60;
2975+
sz += sizeof(*c);
29742976
}
29752977
}
2978+
2979+
return sz + sizeof(*p);
29762980
}
29772981

2978-
static void dump_esp_combs(struct sk_buff *skb, const struct xfrm_tmpl *t)
2982+
static int dump_esp_combs(struct sk_buff *skb, const struct xfrm_tmpl *t)
29792983
{
29802984
struct sadb_prop *p;
2985+
int sz = 0;
29812986
int i, k;
29822987

29832988
p = skb_put(skb, sizeof(struct sadb_prop));
@@ -3019,8 +3024,11 @@ static void dump_esp_combs(struct sk_buff *skb, const struct xfrm_tmpl *t)
30193024
c->sadb_comb_soft_addtime = 20*60*60;
30203025
c->sadb_comb_hard_usetime = 8*60*60;
30213026
c->sadb_comb_soft_usetime = 7*60*60;
3027+
sz += sizeof(*c);
30223028
}
30233029
}
3030+
3031+
return sz + sizeof(*p);
30243032
}
30253033

30263034
static int key_notify_policy_expire(struct xfrm_policy *xp, const struct km_event *c)
@@ -3150,6 +3158,7 @@ static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct
31503158
struct sadb_x_sec_ctx *sec_ctx;
31513159
struct xfrm_sec_ctx *xfrm_ctx;
31523160
int ctx_size = 0;
3161+
int alg_size = 0;
31533162

31543163
sockaddr_size = pfkey_sockaddr_size(x->props.family);
31553164
if (!sockaddr_size)
@@ -3161,16 +3170,16 @@ static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct
31613170
sizeof(struct sadb_x_policy);
31623171

31633172
if (x->id.proto == IPPROTO_AH)
3164-
size += count_ah_combs(t);
3173+
alg_size = count_ah_combs(t);
31653174
else if (x->id.proto == IPPROTO_ESP)
3166-
size += count_esp_combs(t);
3175+
alg_size = count_esp_combs(t);
31673176

31683177
if ((xfrm_ctx = x->security)) {
31693178
ctx_size = PFKEY_ALIGN8(xfrm_ctx->ctx_len);
31703179
size += sizeof(struct sadb_x_sec_ctx) + ctx_size;
31713180
}
31723181

3173-
skb = alloc_skb(size + 16, GFP_ATOMIC);
3182+
skb = alloc_skb(size + alg_size + 16, GFP_ATOMIC);
31743183
if (skb == NULL)
31753184
return -ENOMEM;
31763185

@@ -3224,10 +3233,13 @@ static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct
32243233
pol->sadb_x_policy_priority = xp->priority;
32253234

32263235
/* Set sadb_comb's. */
3236+
alg_size = 0;
32273237
if (x->id.proto == IPPROTO_AH)
3228-
dump_ah_combs(skb, t);
3238+
alg_size = dump_ah_combs(skb, t);
32293239
else if (x->id.proto == IPPROTO_ESP)
3230-
dump_esp_combs(skb, t);
3240+
alg_size = dump_esp_combs(skb, t);
3241+
3242+
hdr->sadb_msg_len += alg_size / 8;
32313243

32323244
/* security context */
32333245
if (xfrm_ctx) {

0 commit comments

Comments
 (0)