Skip to content

Commit d370656

Browse files
YueHaibingdavem330
authored andcommitted
net: netrom: Fix error cleanup path of nr_proto_init
Syzkaller report this: BUG: unable to handle kernel paging request at fffffbfff830524b PGD 237fe8067 P4D 237fe8067 PUD 237e64067 PMD 1c9716067 PTE 0 Oops: 0000 [foundriesio#1] SMP KASAN PTI CPU: 1 PID: 4465 Comm: syz-executor.0 Not tainted 5.0.0+ foundriesio#5 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1ubuntu1 04/01/2014 RIP: 0010:__list_add_valid+0x21/0xe0 lib/list_debug.c:23 Code: 8b 0c 24 e9 17 fd ff ff 90 55 48 89 fd 48 8d 7a 08 53 48 89 d3 48 b8 00 00 00 00 00 fc ff df 48 89 fa 48 c1 ea 03 48 83 ec 08 <80> 3c 02 00 0f 85 8b 00 00 00 48 8b 53 08 48 39 f2 75 35 48 89 f2 RSP: 0018:ffff8881ea2278d0 EFLAGS: 00010282 RAX: dffffc0000000000 RBX: ffffffffc1829250 RCX: 1ffff1103d444ef4 RDX: 1ffffffff830524b RSI: ffffffff85659300 RDI: ffffffffc1829258 RBP: ffffffffc1879250 R08: fffffbfff0acb269 R09: fffffbfff0acb269 R10: ffff8881ea2278f0 R11: fffffbfff0acb268 R12: ffffffffc1829250 R13: dffffc0000000000 R14: 0000000000000008 R15: ffffffffc187c830 FS: 00007fe0361df700(0000) GS:ffff8881f7300000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: fffffbfff830524b CR3: 00000001eb39a001 CR4: 00000000007606e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 PKRU: 55555554 Call Trace: __list_add include/linux/list.h:60 [inline] list_add include/linux/list.h:79 [inline] proto_register+0x444/0x8f0 net/core/sock.c:3375 nr_proto_init+0x73/0x4b3 [netrom] ? 0xffffffffc1628000 ? 0xffffffffc1628000 do_one_initcall+0xbc/0x47d init/main.c:887 do_init_module+0x1b5/0x547 kernel/module.c:3456 load_module+0x6405/0x8c10 kernel/module.c:3804 __do_sys_finit_module+0x162/0x190 kernel/module.c:3898 do_syscall_64+0x9f/0x450 arch/x86/entry/common.c:290 entry_SYSCALL_64_after_hwframe+0x49/0xbe RIP: 0033:0x462e99 Code: f7 d8 64 89 02 b8 ff ff ff ff c3 66 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 bc ff ff ff f7 d8 64 89 01 48 RSP: 002b:00007fe0361dec58 EFLAGS: 00000246 ORIG_RAX: 0000000000000139 RAX: ffffffffffffffda RBX: 000000000073bf00 RCX: 0000000000462e99 RDX: 0000000000000000 RSI: 0000000020000100 RDI: 0000000000000003 RBP: 00007fe0361dec70 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000246 R12: 00007fe0361df6bc R13: 00000000004bcefa R14: 00000000006f6fb0 R15: 0000000000000004 Modules linked in: netrom(+) ax25 fcrypt pcbc af_alg arizona_ldo1 v4l2_common videodev media v4l2_dv_timings hdlc ide_cd_mod snd_soc_sigmadsp_regmap snd_soc_sigmadsp intel_spi_platform intel_spi mtd spi_nor snd_usbmidi_lib usbcore lcd ti_ads7950 hi6421_regulator snd_soc_kbl_rt5663_max98927 snd_soc_hdac_hdmi snd_hda_ext_core snd_hda_core snd_soc_rt5663 snd_soc_core snd_pcm_dmaengine snd_compress snd_soc_rl6231 mac80211 rtc_rc5t583 spi_slave_time leds_pwm hid_gt683r hid industrialio_triggered_buffer kfifo_buf industrialio ir_kbd_i2c rc_core led_class_flash dwc_xlgmac snd_ymfpci gameport snd_mpu401_uart snd_rawmidi snd_ac97_codec snd_pcm ac97_bus snd_opl3_lib snd_timer snd_seq_device snd_hwdep snd soundcore iptable_security iptable_raw iptable_mangle iptable_nat nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 iptable_filter bpfilter ip6_vti ip_vti ip_gre ipip sit tunnel4 ip_tunnel hsr veth netdevsim vxcan batman_adv cfg80211 rfkill chnl_net caif nlmon dummy team bonding vcan bridge stp llc ip6_gre gre ip6_tunnel tunnel6 tun joydev mousedev ppdev tpm kvm_intel kvm irqbypass crct10dif_pclmul crc32_pclmul crc32c_intel ghash_clmulni_intel ide_pci_generic piix aesni_intel aes_x86_64 crypto_simd cryptd glue_helper ide_core psmouse input_leds i2c_piix4 serio_raw intel_agp intel_gtt ata_generic agpgart pata_acpi parport_pc rtc_cmos parport floppy sch_fq_codel ip_tables x_tables sha1_ssse3 sha1_generic ipv6 [last unloaded: rxrpc] Dumping ftrace buffer: (ftrace buffer empty) CR2: fffffbfff830524b ---[ end trace 039ab24b305c4b19 ]--- If nr_proto_init failed, it may forget to call proto_unregister, tiggering this issue.This patch rearrange code of nr_proto_init to avoid such issues. Reported-by: Hulk Robot <[email protected]> Signed-off-by: YueHaibing <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent d7c3a20 commit d370656

5 files changed

Lines changed: 61 additions & 26 deletions

File tree

include/net/netrom.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ void nr_stop_idletimer(struct sock *);
266266
int nr_t1timer_running(struct sock *);
267267

268268
/* sysctl_net_netrom.c */
269-
void nr_register_sysctl(void);
269+
int nr_register_sysctl(void);
270270
void nr_unregister_sysctl(void);
271271

272272
#endif

net/netrom/af_netrom.c

Lines changed: 54 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1392,18 +1392,22 @@ static int __init nr_proto_init(void)
13921392
int i;
13931393
int rc = proto_register(&nr_proto, 0);
13941394

1395-
if (rc != 0)
1396-
goto out;
1395+
if (rc)
1396+
return rc;
13971397

13981398
if (nr_ndevs > 0x7fffffff/sizeof(struct net_device *)) {
1399-
printk(KERN_ERR "NET/ROM: nr_proto_init - nr_ndevs parameter to large\n");
1400-
return -1;
1399+
pr_err("NET/ROM: %s - nr_ndevs parameter too large\n",
1400+
__func__);
1401+
rc = -EINVAL;
1402+
goto unregister_proto;
14011403
}
14021404

14031405
dev_nr = kcalloc(nr_ndevs, sizeof(struct net_device *), GFP_KERNEL);
1404-
if (dev_nr == NULL) {
1405-
printk(KERN_ERR "NET/ROM: nr_proto_init - unable to allocate device array\n");
1406-
return -1;
1406+
if (!dev_nr) {
1407+
pr_err("NET/ROM: %s - unable to allocate device array\n",
1408+
__func__);
1409+
rc = -ENOMEM;
1410+
goto unregister_proto;
14071411
}
14081412

14091413
for (i = 0; i < nr_ndevs; i++) {
@@ -1413,50 +1417,78 @@ static int __init nr_proto_init(void)
14131417
sprintf(name, "nr%d", i);
14141418
dev = alloc_netdev(0, name, NET_NAME_UNKNOWN, nr_setup);
14151419
if (!dev) {
1416-
printk(KERN_ERR "NET/ROM: nr_proto_init - unable to allocate device structure\n");
1420+
rc = -ENOMEM;
14171421
goto fail;
14181422
}
14191423

14201424
dev->base_addr = i;
1421-
if (register_netdev(dev)) {
1422-
printk(KERN_ERR "NET/ROM: nr_proto_init - unable to register network device\n");
1425+
rc = register_netdev(dev);
1426+
if (rc) {
14231427
free_netdev(dev);
14241428
goto fail;
14251429
}
14261430
nr_set_lockdep_key(dev);
14271431
dev_nr[i] = dev;
14281432
}
14291433

1430-
if (sock_register(&nr_family_ops)) {
1431-
printk(KERN_ERR "NET/ROM: nr_proto_init - unable to register socket family\n");
1434+
rc = sock_register(&nr_family_ops);
1435+
if (rc)
14321436
goto fail;
1433-
}
14341437

1435-
register_netdevice_notifier(&nr_dev_notifier);
1438+
rc = register_netdevice_notifier(&nr_dev_notifier);
1439+
if (rc)
1440+
goto out_sock;
14361441

14371442
ax25_register_pid(&nr_pid);
14381443
ax25_linkfail_register(&nr_linkfail_notifier);
14391444

14401445
#ifdef CONFIG_SYSCTL
1441-
nr_register_sysctl();
1446+
rc = nr_register_sysctl();
1447+
if (rc)
1448+
goto out_sysctl;
14421449
#endif
14431450

14441451
nr_loopback_init();
14451452

1446-
proc_create_seq("nr", 0444, init_net.proc_net, &nr_info_seqops);
1447-
proc_create_seq("nr_neigh", 0444, init_net.proc_net, &nr_neigh_seqops);
1448-
proc_create_seq("nr_nodes", 0444, init_net.proc_net, &nr_node_seqops);
1449-
out:
1450-
return rc;
1453+
rc = -ENOMEM;
1454+
if (!proc_create_seq("nr", 0444, init_net.proc_net, &nr_info_seqops))
1455+
goto proc_remove1;
1456+
if (!proc_create_seq("nr_neigh", 0444, init_net.proc_net,
1457+
&nr_neigh_seqops))
1458+
goto proc_remove2;
1459+
if (!proc_create_seq("nr_nodes", 0444, init_net.proc_net,
1460+
&nr_node_seqops))
1461+
goto proc_remove3;
1462+
1463+
return 0;
1464+
1465+
proc_remove3:
1466+
remove_proc_entry("nr_neigh", init_net.proc_net);
1467+
proc_remove2:
1468+
remove_proc_entry("nr", init_net.proc_net);
1469+
proc_remove1:
1470+
1471+
nr_loopback_clear();
1472+
nr_rt_free();
1473+
1474+
#ifdef CONFIG_SYSCTL
1475+
nr_unregister_sysctl();
1476+
out_sysctl:
1477+
#endif
1478+
ax25_linkfail_release(&nr_linkfail_notifier);
1479+
ax25_protocol_release(AX25_P_NETROM);
1480+
unregister_netdevice_notifier(&nr_dev_notifier);
1481+
out_sock:
1482+
sock_unregister(PF_NETROM);
14511483
fail:
14521484
while (--i >= 0) {
14531485
unregister_netdev(dev_nr[i]);
14541486
free_netdev(dev_nr[i]);
14551487
}
14561488
kfree(dev_nr);
1489+
unregister_proto:
14571490
proto_unregister(&nr_proto);
1458-
rc = -1;
1459-
goto out;
1491+
return rc;
14601492
}
14611493

14621494
module_init(nr_proto_init);

net/netrom/nr_loopback.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ static void nr_loopback_timer(struct timer_list *unused)
7070
}
7171
}
7272

73-
void __exit nr_loopback_clear(void)
73+
void nr_loopback_clear(void)
7474
{
7575
del_timer_sync(&loopback_timer);
7676
skb_queue_purge(&loopback_queue);

net/netrom/nr_route.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -953,7 +953,7 @@ const struct seq_operations nr_neigh_seqops = {
953953
/*
954954
* Free all memory associated with the nodes and routes lists.
955955
*/
956-
void __exit nr_rt_free(void)
956+
void nr_rt_free(void)
957957
{
958958
struct nr_neigh *s = NULL;
959959
struct nr_node *t = NULL;

net/netrom/sysctl_net_netrom.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,9 +146,12 @@ static struct ctl_table nr_table[] = {
146146
{ }
147147
};
148148

149-
void __init nr_register_sysctl(void)
149+
int __init nr_register_sysctl(void)
150150
{
151151
nr_table_header = register_net_sysctl(&init_net, "net/netrom", nr_table);
152+
if (!nr_table_header)
153+
return -ENOMEM;
154+
return 0;
152155
}
153156

154157
void nr_unregister_sysctl(void)

0 commit comments

Comments
 (0)