b97c30
From 4388f1ebeee9ba362b6b94ea587e1006a8721a15 Mon Sep 17 00:00:00 2001
b97c30
From: David Lebrun <dlebrun@google.com>
b97c30
Date: Fri, 2 Sep 2022 10:45:06 +0100
b97c30
Subject: [PATCH] ipv6: sr: fix out-of-bounds read when setting HMAC data.
b97c30
Git-commit: 84a53580c5d2138c7361c7c3eea5b31827e63b35
b97c30
Patch-mainline: v6.0-rc5
b97c30
References: bsc#1211592
b97c30
b97c30
The SRv6 layer allows defining HMAC data that can later be used to sign IPv6
b97c30
Segment Routing Headers. This configuration is realised via netlink through
b97c30
four attributes: SEG6_ATTR_HMACKEYID, SEG6_ATTR_SECRET, SEG6_ATTR_SECRETLEN and
b97c30
SEG6_ATTR_ALGID. Because the SECRETLEN attribute is decoupled from the actual
b97c30
length of the SECRET attribute, it is possible to provide invalid combinations
b97c30
(e.g., secret = "", secretlen = 64). This case is not checked in the code and
b97c30
with an appropriately crafted netlink message, an out-of-bounds read of up
b97c30
to 64 bytes (max secret length) can occur past the skb end pointer and into
b97c30
skb_shared_info:
b97c30
b97c30
Breakpoint 1, seg6_genl_sethmac (skb=<optimized out>, info=<optimized out>) at net/ipv6/seg6.c:208
b97c30
208		memcpy(hinfo->secret, secret, slen);
b97c30
(gdb) bt
b97c30
 #0  seg6_genl_sethmac (skb=<optimized out>, info=<optimized out>) at net/ipv6/seg6.c:208
b97c30
 #1  0xffffffff81e012e9 in genl_family_rcv_msg_doit (skb=skb@entry=0xffff88800b1f9f00, nlh=nlh@entry=0xffff88800b1b7600,
b97c30
    extack=extack@entry=0xffffc90000ba7af0, ops=ops@entry=0xffffc90000ba7a80, hdrlen=4, net=0xffffffff84237580 <init_net>, family=<optimized out>,
b97c30
    family=<optimized out>) at net/netlink/genetlink.c:731
b97c30
 #2  0xffffffff81e01435 in genl_family_rcv_msg (extack=0xffffc90000ba7af0, nlh=0xffff88800b1b7600, skb=0xffff88800b1f9f00,
b97c30
    family=0xffffffff82fef6c0 <seg6_genl_family>) at net/netlink/genetlink.c:775
b97c30
 #3  genl_rcv_msg (skb=0xffff88800b1f9f00, nlh=0xffff88800b1b7600, extack=0xffffc90000ba7af0) at net/netlink/genetlink.c:792
b97c30
 #4  0xffffffff81dfffc3 in netlink_rcv_skb (skb=skb@entry=0xffff88800b1f9f00, cb=cb@entry=0xffffffff81e01350 <genl_rcv_msg>)
b97c30
    at net/netlink/af_netlink.c:2501
b97c30
 #5  0xffffffff81e00919 in genl_rcv (skb=0xffff88800b1f9f00) at net/netlink/genetlink.c:803
b97c30
 #6  0xffffffff81dff6ae in netlink_unicast_kernel (ssk=0xffff888010eec800, skb=0xffff88800b1f9f00, sk=0xffff888004aed000)
b97c30
    at net/netlink/af_netlink.c:1319
b97c30
 #7  netlink_unicast (ssk=ssk@entry=0xffff888010eec800, skb=skb@entry=0xffff88800b1f9f00, portid=portid@entry=0, nonblock=<optimized out>)
b97c30
    at net/netlink/af_netlink.c:1345
b97c30
 #8  0xffffffff81dff9a4 in netlink_sendmsg (sock=<optimized out>, msg=0xffffc90000ba7e48, len=<optimized out>) at net/netlink/af_netlink.c:1921
b97c30
...
b97c30
(gdb) p/x ((struct sk_buff *)0xffff88800b1f9f00)->head + ((struct sk_buff *)0xffff88800b1f9f00)->end
b97c30
$1 = 0xffff88800b1b76c0
b97c30
(gdb) p/x secret
b97c30
$2 = 0xffff88800b1b76c0
b97c30
(gdb) p slen
b97c30
$3 = 64 '@'
b97c30
b97c30
The OOB data can then be read back from userspace by dumping HMAC state. This
b97c30
commit fixes this by ensuring SECRETLEN cannot exceed the actual length of
b97c30
SECRET.
b97c30
b97c30
Reported-by: Lucas Leong <wmliang.tw@gmail.com>
b97c30
Tested: verified that EINVAL is correctly returned when secretlen > len(secret)
b97c30
Fixes: 4f4853dc1c9c1 ("ipv6: sr: implement API to control SR HMAC structure")
b97c30
Signed-off-by: David Lebrun <dlebrun@google.com>
b97c30
Signed-off-by: David S. Miller <davem@davemloft.net>
b97c30
Signed-off-by: Denis Kirjanov <denis.kirjanov@suse.com>
b97c30
---
b97c30
 net/ipv6/seg6.c | 5 +++++
b97c30
 1 file changed, 5 insertions(+)
b97c30
b97c30
diff --git a/net/ipv6/seg6.c b/net/ipv6/seg6.c
b97c30
index 4458e46977fe..c7f5e76d1544 100644
b97c30
--- a/net/ipv6/seg6.c
b97c30
+++ b/net/ipv6/seg6.c
b97c30
@@ -129,6 +129,11 @@ static int seg6_genl_sethmac(struct sk_buff *skb, struct genl_info *info)
b97c30
 		goto out_unlock;
b97c30
 	}
b97c30
 
b97c30
+	if (slen > nla_len(info->attrs[SEG6_ATTR_SECRET])) {
b97c30
+		err = -EINVAL;
b97c30
+		goto out_unlock;
b97c30
+	}
b97c30
+
b97c30
 	if (hinfo) {
b97c30
 		err = seg6_hmac_info_del(net, hmackeyid);
b97c30
 		if (err)
b97c30
-- 
b97c30
2.16.4
b97c30