Skip to content

Commit 11cbf29

Browse files
ARC-CPSgregkh
authored andcommitted
net: af_key: zero aligned sockaddr tail in PF_KEY exports
[ Upstream commit 426c355 ] PF_KEY export paths use `pfkey_sockaddr_size()` when reserving sockaddr payload space, so IPv6 addresses occupy 32 bytes on the wire. However, `pfkey_sockaddr_fill()` initializes only the first 28 bytes of `struct sockaddr_in6`, leaving the final 4 aligned bytes uninitialized. Not every PF_KEY message is affected. The state and policy dump builders already zero the whole message buffer before filling the sockaddr payloads. Keep the fix to the export paths that still append aligned sockaddr payloads with plain `skb_put()`: - `SADB_ACQUIRE` - `SADB_X_NAT_T_NEW_MAPPING` - `SADB_X_MIGRATE` Fix those paths by clearing only the aligned sockaddr tail after `pfkey_sockaddr_fill()`. Fixes: 1da177e ("Linux-2.6.12-rc2") Fixes: 08de61b ("[PFKEYV2]: Extension for dynamic update of endpoint address(es)") Reported-by: Yifan Wu <yifanwucs@gmail.com> Reported-by: Juefei Pu <tomapufckgml@gmail.com> Co-developed-by: Yuan Tan <yuantan098@gmail.com> Signed-off-by: Yuan Tan <yuantan098@gmail.com> Suggested-by: Xin Liu <bird@lzu.edu.cn> Tested-by: Xiao Liu <lx24@stu.ynu.edu.cn> Signed-off-by: Zhengchuan Liang <zcliangcn@gmail.com> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 3e223a7 commit 11cbf29

1 file changed

Lines changed: 34 additions & 18 deletions

File tree

net/key/af_key.c

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -757,6 +757,22 @@ static unsigned int pfkey_sockaddr_fill(const xfrm_address_t *xaddr, __be16 port
757757
return 0;
758758
}
759759

760+
static unsigned int pfkey_sockaddr_fill_zero_tail(const xfrm_address_t *xaddr,
761+
__be16 port,
762+
struct sockaddr *sa,
763+
unsigned short family)
764+
{
765+
unsigned int prefixlen;
766+
int sockaddr_len = pfkey_sockaddr_len(family);
767+
int sockaddr_size = pfkey_sockaddr_size(family);
768+
769+
prefixlen = pfkey_sockaddr_fill(xaddr, port, sa, family);
770+
if (sockaddr_size > sockaddr_len)
771+
memset((u8 *)sa + sockaddr_len, 0, sockaddr_size - sockaddr_len);
772+
773+
return prefixlen;
774+
}
775+
760776
static struct sk_buff *__pfkey_xfrm_state2msg(const struct xfrm_state *x,
761777
int add_keys, int hsc)
762778
{
@@ -3206,9 +3222,9 @@ static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct
32063222
addr->sadb_address_proto = 0;
32073223
addr->sadb_address_reserved = 0;
32083224
addr->sadb_address_prefixlen =
3209-
pfkey_sockaddr_fill(&x->props.saddr, 0,
3210-
(struct sockaddr *) (addr + 1),
3211-
x->props.family);
3225+
pfkey_sockaddr_fill_zero_tail(&x->props.saddr, 0,
3226+
(struct sockaddr *)(addr + 1),
3227+
x->props.family);
32123228
if (!addr->sadb_address_prefixlen)
32133229
BUG();
32143230

@@ -3221,9 +3237,9 @@ static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct
32213237
addr->sadb_address_proto = 0;
32223238
addr->sadb_address_reserved = 0;
32233239
addr->sadb_address_prefixlen =
3224-
pfkey_sockaddr_fill(&x->id.daddr, 0,
3225-
(struct sockaddr *) (addr + 1),
3226-
x->props.family);
3240+
pfkey_sockaddr_fill_zero_tail(&x->id.daddr, 0,
3241+
(struct sockaddr *)(addr + 1),
3242+
x->props.family);
32273243
if (!addr->sadb_address_prefixlen)
32283244
BUG();
32293245

@@ -3421,9 +3437,9 @@ static int pfkey_send_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr,
34213437
addr->sadb_address_proto = 0;
34223438
addr->sadb_address_reserved = 0;
34233439
addr->sadb_address_prefixlen =
3424-
pfkey_sockaddr_fill(&x->props.saddr, 0,
3425-
(struct sockaddr *) (addr + 1),
3426-
x->props.family);
3440+
pfkey_sockaddr_fill_zero_tail(&x->props.saddr, 0,
3441+
(struct sockaddr *)(addr + 1),
3442+
x->props.family);
34273443
if (!addr->sadb_address_prefixlen)
34283444
BUG();
34293445

@@ -3443,9 +3459,9 @@ static int pfkey_send_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr,
34433459
addr->sadb_address_proto = 0;
34443460
addr->sadb_address_reserved = 0;
34453461
addr->sadb_address_prefixlen =
3446-
pfkey_sockaddr_fill(ipaddr, 0,
3447-
(struct sockaddr *) (addr + 1),
3448-
x->props.family);
3462+
pfkey_sockaddr_fill_zero_tail(ipaddr, 0,
3463+
(struct sockaddr *)(addr + 1),
3464+
x->props.family);
34493465
if (!addr->sadb_address_prefixlen)
34503466
BUG();
34513467

@@ -3474,15 +3490,15 @@ static int set_sadb_address(struct sk_buff *skb, int sasize, int type,
34743490
switch (type) {
34753491
case SADB_EXT_ADDRESS_SRC:
34763492
addr->sadb_address_prefixlen = sel->prefixlen_s;
3477-
pfkey_sockaddr_fill(&sel->saddr, 0,
3478-
(struct sockaddr *)(addr + 1),
3479-
sel->family);
3493+
pfkey_sockaddr_fill_zero_tail(&sel->saddr, 0,
3494+
(struct sockaddr *)(addr + 1),
3495+
sel->family);
34803496
break;
34813497
case SADB_EXT_ADDRESS_DST:
34823498
addr->sadb_address_prefixlen = sel->prefixlen_d;
3483-
pfkey_sockaddr_fill(&sel->daddr, 0,
3484-
(struct sockaddr *)(addr + 1),
3485-
sel->family);
3499+
pfkey_sockaddr_fill_zero_tail(&sel->daddr, 0,
3500+
(struct sockaddr *)(addr + 1),
3501+
sel->family);
34863502
break;
34873503
default:
34883504
return -EINVAL;

0 commit comments

Comments
 (0)