Skip to content

Commit d8a2107

Browse files
idoschkuba-moo
authored andcommitted
nexthop: Fix out-of-bounds access during attribute validation
Passing a maximum attribute type to nlmsg_parse() that is larger than the size of the passed policy will result in an out-of-bounds access [1] when the attribute type is used as an index into the policy array. Fix by setting the maximum attribute type according to the policy size, as is already done for RTM_NEWNEXTHOP messages. Add a test case that triggers the bug. No regressions in fib nexthops tests: # ./fib_nexthops.sh [...] Tests passed: 236 Tests failed: 0 [1] BUG: KASAN: global-out-of-bounds in __nla_validate_parse+0x1e53/0x2940 Read of size 1 at addr ffffffff99ab4d20 by task ip/610 CPU: 3 PID: 610 Comm: ip Not tainted 6.8.0-rc7-custom-gd435d6e3e161 #9 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.2-1.fc38 04/01/2014 Call Trace: <TASK> dump_stack_lvl+0x8f/0xe0 print_report+0xcf/0x670 kasan_report+0xd8/0x110 __nla_validate_parse+0x1e53/0x2940 __nla_parse+0x40/0x50 rtm_del_nexthop+0x1bd/0x400 rtnetlink_rcv_msg+0x3cc/0xf20 netlink_rcv_skb+0x170/0x440 netlink_unicast+0x540/0x820 netlink_sendmsg+0x8d3/0xdb0 ____sys_sendmsg+0x31f/0xa60 ___sys_sendmsg+0x13a/0x1e0 __sys_sendmsg+0x11c/0x1f0 do_syscall_64+0xc5/0x1d0 entry_SYSCALL_64_after_hwframe+0x63/0x6b [...] The buggy address belongs to the variable: rtm_nh_policy_del+0x20/0x40 Fixes: 2118f93 ("net: nexthop: Adjust netlink policy parsing for a new attribute") Reported-by: Eric Dumazet <edumazet@google.com> Closes: https://lore.kernel.org/netdev/CANn89i+UNcG0PJMW5X7gOMunF38ryMh=L1aeZUKH3kL4UdUqag@mail.gmail.com/ Reported-by: syzbot+65bb09a7208ce3d4a633@syzkaller.appspotmail.com Closes: https://lore.kernel.org/netdev/00000000000088981b06133bc07b@google.com/ Signed-off-by: Ido Schimmel <idosch@nvidia.com> Reviewed-by: David Ahern <dsahern@kernel.org> Link: https://lore.kernel.org/r/20240311162307.545385-4-idosch@nvidia.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent 262a68a commit d8a2107

File tree

2 files changed

+23
-12
lines changed

2 files changed

+23
-12
lines changed

net/ipv4/nexthop.c

+17-12
Original file line numberDiff line numberDiff line change
@@ -3244,8 +3244,8 @@ static int nh_valid_get_del_req(const struct nlmsghdr *nlh,
32443244
static int rtm_del_nexthop(struct sk_buff *skb, struct nlmsghdr *nlh,
32453245
struct netlink_ext_ack *extack)
32463246
{
3247+
struct nlattr *tb[ARRAY_SIZE(rtm_nh_policy_del)];
32473248
struct net *net = sock_net(skb->sk);
3248-
struct nlattr *tb[NHA_MAX + 1];
32493249
struct nl_info nlinfo = {
32503250
.nlh = nlh,
32513251
.nl_net = net,
@@ -3255,8 +3255,9 @@ static int rtm_del_nexthop(struct sk_buff *skb, struct nlmsghdr *nlh,
32553255
int err;
32563256
u32 id;
32573257

3258-
err = nlmsg_parse(nlh, sizeof(struct nhmsg), tb, NHA_MAX,
3259-
rtm_nh_policy_del, extack);
3258+
err = nlmsg_parse(nlh, sizeof(struct nhmsg), tb,
3259+
ARRAY_SIZE(rtm_nh_policy_del) - 1, rtm_nh_policy_del,
3260+
extack);
32603261
if (err < 0)
32613262
return err;
32623263

@@ -3277,16 +3278,17 @@ static int rtm_del_nexthop(struct sk_buff *skb, struct nlmsghdr *nlh,
32773278
static int rtm_get_nexthop(struct sk_buff *in_skb, struct nlmsghdr *nlh,
32783279
struct netlink_ext_ack *extack)
32793280
{
3281+
struct nlattr *tb[ARRAY_SIZE(rtm_nh_policy_get)];
32803282
struct net *net = sock_net(in_skb->sk);
3281-
struct nlattr *tb[NHA_MAX + 1];
32823283
struct sk_buff *skb = NULL;
32833284
struct nexthop *nh;
32843285
u32 op_flags;
32853286
int err;
32863287
u32 id;
32873288

3288-
err = nlmsg_parse(nlh, sizeof(struct nhmsg), tb, NHA_MAX,
3289-
rtm_nh_policy_get, extack);
3289+
err = nlmsg_parse(nlh, sizeof(struct nhmsg), tb,
3290+
ARRAY_SIZE(rtm_nh_policy_get) - 1, rtm_nh_policy_get,
3291+
extack);
32903292
if (err < 0)
32913293
return err;
32923294

@@ -3405,10 +3407,11 @@ static int nh_valid_dump_req(const struct nlmsghdr *nlh,
34053407
struct nh_dump_filter *filter,
34063408
struct netlink_callback *cb)
34073409
{
3408-
struct nlattr *tb[NHA_MAX + 1];
3410+
struct nlattr *tb[ARRAY_SIZE(rtm_nh_policy_dump)];
34093411
int err;
34103412

3411-
err = nlmsg_parse(nlh, sizeof(struct nhmsg), tb, NHA_MAX,
3413+
err = nlmsg_parse(nlh, sizeof(struct nhmsg), tb,
3414+
ARRAY_SIZE(rtm_nh_policy_dump) - 1,
34123415
rtm_nh_policy_dump, cb->extack);
34133416
if (err < 0)
34143417
return err;
@@ -3548,10 +3551,11 @@ static int nh_valid_dump_bucket_req(const struct nlmsghdr *nlh,
35483551
struct netlink_callback *cb)
35493552
{
35503553
struct nlattr *res_tb[ARRAY_SIZE(rtm_nh_res_bucket_policy_dump)];
3551-
struct nlattr *tb[NHA_MAX + 1];
3554+
struct nlattr *tb[ARRAY_SIZE(rtm_nh_policy_dump_bucket)];
35523555
int err;
35533556

3554-
err = nlmsg_parse(nlh, sizeof(struct nhmsg), tb, NHA_MAX,
3557+
err = nlmsg_parse(nlh, sizeof(struct nhmsg), tb,
3558+
ARRAY_SIZE(rtm_nh_policy_dump_bucket) - 1,
35553559
rtm_nh_policy_dump_bucket, NULL);
35563560
if (err < 0)
35573561
return err;
@@ -3716,10 +3720,11 @@ static int nh_valid_get_bucket_req(const struct nlmsghdr *nlh,
37163720
u32 *id, u16 *bucket_index,
37173721
struct netlink_ext_ack *extack)
37183722
{
3719-
struct nlattr *tb[NHA_MAX + 1];
3723+
struct nlattr *tb[ARRAY_SIZE(rtm_nh_policy_get_bucket)];
37203724
int err;
37213725

3722-
err = nlmsg_parse(nlh, sizeof(struct nhmsg), tb, NHA_MAX,
3726+
err = nlmsg_parse(nlh, sizeof(struct nhmsg), tb,
3727+
ARRAY_SIZE(rtm_nh_policy_get_bucket) - 1,
37233728
rtm_nh_policy_get_bucket, extack);
37243729
if (err < 0)
37253730
return err;

tools/testing/selftests/net/fib_nexthops.sh

+6
Original file line numberDiff line numberDiff line change
@@ -2066,6 +2066,12 @@ basic()
20662066
run_cmd "$IP nexthop get id 1"
20672067
log_test $? 2 "Nexthop get on non-existent id"
20682068

2069+
run_cmd "$IP nexthop del id 1"
2070+
log_test $? 2 "Nexthop del with non-existent id"
2071+
2072+
run_cmd "$IP nexthop del id 1 group 1/2/3/4/5/6/7/8"
2073+
log_test $? 2 "Nexthop del with non-existent id and extra attributes"
2074+
20692075
# attempt to create nh without a device or gw - fails
20702076
run_cmd "$IP nexthop add id 1"
20712077
log_test $? 2 "Nexthop with no device or gateway"

0 commit comments

Comments
 (0)