All of lore.kernel.org
 help / color / mirror / Atom feed
* [BUG] use-after-free after removing UDC with USB Ethernet gadget
@ 2022-10-25  6:54 Ahmad Fatoum
  2022-10-25  8:12 ` Greg KH
  0 siblings, 1 reply; 4+ messages in thread
From: Ahmad Fatoum @ 2022-10-25  6:54 UTC (permalink / raw)
  To: netdev, linux-usb
  Cc: Peter Chen, Felipe Balbi, johannes.berg, Pengutronix Kernel Team,
	Alvin Šipraga

Hi everybody,

I am running v6.0.2 and can reliably trigger a use-after-free by allocating
a USB gadget, binding it to the chipidea UDC and the removing the UDC.

The network interface is not removed, but the chipidea SoC glue driver will
remove the platform_device it had allocated in the probe, which is apparently
the parent of the network device. When rtnl_fill_ifinfo runs, it will access the
device parent's name for IFLA_PARENT_DEV_NAME, which is now freed memory.

Steps to reproduce (on an i.MX8MM):

  cd /sys/kernel/config/usb_gadget/
  mkdir -p mygadget
  cd mygadget

  mkdir -p configs/c.1/strings/0x409
  echo "C1:Composite Device" > configs/c.1/strings/0x409/configuration

  mkdir -p functions/ecm.usb0
  ln -s functions/ecm.usb0 configs/c.1/

  echo "ci_hdrc.0" > UDC
  echo ci_hdrc.0 > /sys/class/udc/ci_hdrc.0/device/driver/unbind

  ip --details link show usb0

This gives me following KASAN report (v6.0.2 line numbers):

  [40645.265092] BUG: KASAN: use-after-free in rtnl_fill_ifinfo (./include/linux/device.h:704 ./net/core/rtnetlink.c:1859)
  [40645.271855] Read of size 8 at addr ffff000007350550 by task systemd-udevd/348
  [40645.279028]
  [40645.280552] CPU: 2 PID: 348 Comm: systemd-udevd Not tainted 6.0.2-00001-g749cbdda068b #17
  [40645.288761] Hardware name: InnoComm WB15-EVK (DT)
  [40645.293510] Call trace:
  [40645.295983] dump_backtrace (./arch/arm64/kernel/stacktrace.c:184)
  [40645.299782] show_stack (./arch/arm64/kernel/stacktrace.c:191)
  [40645.303109] dump_stack_lvl (./lib/dump_stack.c:107 (discriminator 1))
  [40645.306789] print_report (./include/linux/mm.h:851 ./mm/kasan/report.c:214 ./mm/kasan/report.c:315 ./mm/kasan/report.c:433)
  [40645.310463] kasan_report (./mm/kasan/report.c:497)
  [40645.313962] __asan_report_load8_noabort (./mm/kasan/report_generic.c:307 (discriminator 4))
  [40645.318764] rtnl_fill_ifinfo (./include/linux/device.h:704 ./net/core/rtnetlink.c:1859)
  [40645.322956] rtnl_getlink (./net/core/rtnetlink.c:3695)
  [40645.326624] rtnetlink_rcv_msg (./net/core/rtnetlink.c:6090)
  [40645.330735] netlink_rcv_skb (./net/netlink/af_netlink.c:2501)
  [40645.334670] rtnetlink_rcv (./net/core/rtnetlink.c:6109)
  [40645.338255] netlink_unicast (./net/netlink/af_netlink.c:1320 ./net/netlink/af_netlink.c:1345)
  [40645.342189] netlink_sendmsg (./net/netlink/af_netlink.c:1921)
  [40645.346122] __sys_sendto (./net/socket.c:717 ./net/socket.c:734 ./net/socket.c:2117)
  [40645.349797] __arm64_sys_sendto (./net/socket.c:2125)
  [40645.353905] invoke_syscall (./arch/arm64/kernel/syscall.c:38 ./arch/arm64/kernel/syscall.c:52)
  [40645.357671] el0_svc_common.constprop.0 (./arch/arm64/kernel/syscall.c:149)
  [40645.362560] do_el0_svc (./arch/arm64/kernel/syscall.c:207)
  [40645.365884] el0_svc (./arch/arm64/kernel/entry-common.c:133 ./arch/arm64/kernel/entry-common.c:142 ./arch/arm64/kernel/entry-common.c:625)
  [40645.368952] el0t_64_sync_handler (./arch/arm64/kernel/entry-common.c:643)
  [40645.373233] el0t_64_sync (./arch/arm64/kernel/entry.S:581)
  [40645.376906]
  [40645.378402] Allocated by task 9:
  [40645.381637] kasan_save_stack (./mm/kasan/common.c:39)
  [40645.385486] __kasan_kmalloc (./mm/kasan/common.c:45 ./mm/kasan/common.c:437 ./mm/kasan/common.c:516 ./mm/kasan/common.c:525)
  [40645.389246] __kmalloc_node_track_caller (./include/linux/kasan.h:234 ./mm/slub.c:4969)
  [40645.394221] devm_kmalloc (./drivers/base/devres.c:116 ./drivers/base/devres.c:823)
  [40645.397810] ci_hdrc_probe (./include/linux/device.h:209 ./drivers/usb/chipidea/core.c:1021)
  [40645.401574] platform_probe (./drivers/base/platform.c:1401)
  [40645.405331] really_probe (./drivers/base/dd.c:560 ./drivers/base/dd.c:639)
  [40645.409001] __driver_probe_device (./drivers/base/dd.c:778)
  [40645.413451] driver_probe_device (./drivers/base/dd.c:808)
  [40645.417644] __device_attach_driver (./drivers/base/dd.c:937)
  [40645.422182] bus_for_each_drv (./drivers/base/bus.c:427)
  [40645.426203] __device_attach (./drivers/base/dd.c:1010)
  [40645.430132] device_initial_probe (./drivers/base/dd.c:1058)
  [40645.434326] bus_probe_device (./drivers/base/bus.c:489)
  [40645.438341] device_add (./drivers/base/core.c:3524)
  [40645.441926] platform_device_add (./drivers/base/platform.c:717)
  [40645.446205] ci_hdrc_add_device (./drivers/usb/chipidea/core.c:879 ./drivers/usb/chipidea/core.c:847)
  [40645.450401] ci_hdrc_imx_probe (./drivers/usb/chipidea/ci_hdrc_imx.c:449)
  [40645.454593] platform_probe (./drivers/base/platform.c:1401)
  [40645.458349] really_probe (./drivers/base/dd.c:560 ./drivers/base/dd.c:639)
  [40645.462017] __driver_probe_device (./drivers/base/dd.c:778)
  [40645.466470] driver_probe_device (./drivers/base/dd.c:808)
  [40645.470662] __device_attach_driver (./drivers/base/dd.c:937)
  [40645.475201] bus_for_each_drv (./drivers/base/bus.c:427)
  [40645.479220] __device_attach (./drivers/base/dd.c:1010)
  [40645.483151] device_initial_probe (./drivers/base/dd.c:1058)
  [40645.487343] bus_probe_device (./drivers/base/bus.c:489)
  [40645.491359] deferred_probe_work_func (./drivers/base/dd.c:124)
  [40645.496072] process_one_work (./arch/arm64/include/asm/jump_label.h:21 ./include/linux/jump_label.h:207 ./include/trace/events/workqueue.h:108 ./kernel/workqueue.c:2294)
  [40645.500179] worker_thread (./include/linux/list.h:292 ./kernel/workqueue.c:2349 ./kernel/workqueue.c:2441)
  [40645.503934] kthread (./kernel/kthread.c:376)
  [40645.507173] ret_from_fork (./arch/arm64/kernel/entry.S:861)
  [40645.510758]
  [40645.512252] Freed by task 343:
  [40645.515312] kasan_save_stack (./mm/kasan/common.c:39)
  [40645.519158] kasan_set_track (./mm/kasan/common.c:45)
  [40645.522917] kasan_set_free_info (./include/linux/kasan.h:59 ./mm/kasan/generic.c:372)
  [40645.527024] ____kasan_slab_free (./mm/kasan/common.c:369 ./mm/kasan/common.c:329)
  [40645.531306] __kasan_slab_free (./mm/kasan/common.c:376)
  [40645.535237] slab_free_freelist_hook (./mm/slub.c:1785)
  [40645.539778] kfree (./mm/slub.c:3539 (discriminator 4) ./mm/slub.c:4567 (discriminator 4))
  [40645.542756] release_nodes (./drivers/base/devres.c:498)
  [40645.546427] devres_release_all (./drivers/base/devres.c:531)
  [40645.550621] device_unbind_cleanup (./drivers/base/dd.c:532)
  [40645.554985] device_release_driver_internal (./drivers/base/dd.c:1257 ./drivers/base/dd.c:1275)
  [40645.560221] device_driver_detach (./drivers/base/dd.c:1312)
  [40645.564414] unbind_store (./drivers/base/bus.c:196)
  [40645.568087] drv_attr_store (./drivers/base/bus.c:79)
  [40645.571760] sysfs_kf_write (./fs/sysfs/file.c:137)
  [40645.575520] kernfs_fop_write_iter (./fs/kernfs/file.c:354)
  [40645.579973] vfs_write (./include/linux/fs.h:2187 ./fs/read_write.c:491 ./fs/read_write.c:584)
  [40645.583385] ksys_write (./fs/read_write.c:637)
  [40645.586796] __arm64_sys_write (./fs/read_write.c:646)
  [40645.590730] invoke_syscall (./arch/arm64/kernel/syscall.c:38 ./arch/arm64/kernel/syscall.c:52)
  [40645.594488] el0_svc_common.constprop.0 (./arch/arm64/include/asm/daifflags.h:28 ./arch/arm64/kernel/syscall.c:150)
  [40645.599289] do_el0_svc (./arch/arm64/kernel/syscall.c:207)
  [40645.602615] el0_svc (./arch/arm64/kernel/entry-common.c:133 ./arch/arm64/kernel/entry-common.c:142 ./arch/arm64/kernel/entry-common.c:625)
  [40645.605678] el0t_64_sync_handler (./arch/arm64/kernel/entry-common.c:643)
  [40645.609958] el0t_64_sync (./arch/arm64/kernel/entry.S:581)
  [40645.613626]
  [40645.615121] Last potentially related work creation:
  [40645.620002] kasan_save_stack (./mm/kasan/common.c:39)
  [40645.623848] __kasan_record_aux_stack (./mm/kasan/generic.c:348)
  [40645.628388] kasan_record_aux_stack_noalloc (./mm/kasan/generic.c:359)
  [40645.633448] insert_work (./include/asm-generic/bitops/generic-non-atomic.h:128 ./kernel/workqueue.c:635 ./kernel/workqueue.c:642 ./kernel/workqueue.c:1361)
  [40645.636944] __queue_work (./kernel/workqueue.c:1520)
  [40645.640614] queue_work_on (./kernel/workqueue.c:1546)
  [40645.644197] usb_gadget_set_state (./drivers/usb/gadget/udc/core.c:1049)
  [40645.648390] ci_hdrc_gadget_connect (./include/asm-generic/qspinlock.h:128 ./include/linux/spinlock.h:202 ./include/linux/spinlock_api_smp.h:158 ./include/linux/spinlock.h:399 ./drivers/usb/chipidea/udc.c:1684)
  [40645.652931] ci_udc_start (./drivers/usb/chipidea/udc.c:1955)
  [40645.656603] gadget_bind_driver (./drivers/usb/gadget/udc/core.c:1121 ./drivers/usb/gadget/udc/core.c:1499)
  [40645.660794] really_probe (./drivers/base/dd.c:560 ./drivers/base/dd.c:639)
  [40645.664463] __driver_probe_device (./drivers/base/dd.c:778)
  [40645.668913] driver_probe_device (./drivers/base/dd.c:808)
  [40645.673104] __driver_attach (./drivers/base/dd.c:1191)
  [40645.677035] bus_for_each_dev (./drivers/base/bus.c:301)
  [40645.681053] driver_attach (./drivers/base/dd.c:1208)
  [40645.684637] bus_add_driver (./drivers/base/bus.c:618)
  [40645.688481] driver_register (./drivers/base/driver.c:246)
  [40645.692412] usb_gadget_register_driver_owner (./drivers/usb/gadget/udc/core.c:1560)
  [40645.697732] gadget_dev_desc_UDC_store (./drivers/usb/gadget/configfs.c:287)
  [40645.702535] configfs_write_iter (./fs/configfs/file.c:207 ./fs/configfs/file.c:229)
  [40645.706815] vfs_write (./include/linux/fs.h:2187 ./fs/read_write.c:491 ./fs/read_write.c:584)
  [40645.710226] ksys_write (./fs/read_write.c:637)
  [40645.713636] __arm64_sys_write (./fs/read_write.c:646)
  [40645.717567] invoke_syscall (./arch/arm64/kernel/syscall.c:38 ./arch/arm64/kernel/syscall.c:52)
  [40645.721328] el0_svc_common.constprop.0 (./arch/arm64/include/asm/daifflags.h:28 ./arch/arm64/kernel/syscall.c:150)
  [40645.726129] do_el0_svc (./arch/arm64/kernel/syscall.c:207)
  [40645.729452] el0_svc (./arch/arm64/kernel/entry-common.c:133 ./arch/arm64/kernel/entry-common.c:142 ./arch/arm64/kernel/entry-common.c:625)
  [40645.732514] el0t_64_sync_handler (./arch/arm64/kernel/entry-common.c:643)
  [40645.736793] el0t_64_sync (./arch/arm64/kernel/entry.S:581)
  [40645.740461]
  [40645.741955] Second to last potentially related work creation:
  [40645.747706] kasan_save_stack (./mm/kasan/common.c:39)
  [40645.751552] __kasan_record_aux_stack (./mm/kasan/generic.c:348)
  [40645.756089] kasan_record_aux_stack_noalloc (./mm/kasan/generic.c:359)
  [40645.761151] insert_work (./include/asm-generic/bitops/generic-non-atomic.h:128 ./kernel/workqueue.c:635 ./kernel/workqueue.c:642 ./kernel/workqueue.c:1361)
  [40645.764646] __queue_work (./kernel/workqueue.c:1520)
  [40645.768317] queue_work_on (./kernel/workqueue.c:1546)
  [40645.771900] usb_add_gadget (./drivers/usb/gadget/udc/core.c:1310)
  [40645.775741] usb_add_gadget_udc (./drivers/usb/gadget/udc/core.c:1360 ./drivers/usb/gadget/udc/core.c:1407)
  [40645.779934] ci_hdrc_gadget_init (./drivers/usb/chipidea/udc.c:2121 ./drivers/usb/chipidea/udc.c:2207)
  [40645.784212] ci_hdrc_probe (./drivers/usb/chipidea/core.c:1121)
  [40645.788061] platform_probe (./drivers/base/platform.c:1401)
  [40645.791819] really_probe (./drivers/base/dd.c:560 ./drivers/base/dd.c:639)
  [40645.795486] __driver_probe_device (./drivers/base/dd.c:778)
  [40645.799939] driver_probe_device (./drivers/base/dd.c:808)
  [40645.804129] __device_attach_driver (./drivers/base/dd.c:937)
  [40645.808668] bus_for_each_drv (./drivers/base/bus.c:427)
  [40645.812688] __device_attach (./drivers/base/dd.c:1010)
  [40645.816618] device_initial_probe (./drivers/base/dd.c:1058)
  [40645.820808] bus_probe_device (./drivers/base/bus.c:489)
  [40645.824826] device_add (./drivers/base/core.c:3524)
  [40645.828413] platform_device_add (./drivers/base/platform.c:717)
  [40645.832690] ci_hdrc_add_device (./drivers/usb/chipidea/core.c:879 ./drivers/usb/chipidea/core.c:847)
  [40645.836882] ci_hdrc_imx_probe (./drivers/usb/chipidea/ci_hdrc_imx.c:449)
  [40645.841075] platform_probe (./drivers/base/platform.c:1401)
  [40645.844835] really_probe (./drivers/base/dd.c:560 ./drivers/base/dd.c:639)
  [40645.848504] __driver_probe_device (./drivers/base/dd.c:778)
  [40645.852956] driver_probe_device (./drivers/base/dd.c:808)
  [40645.857148] __device_attach_driver (./drivers/base/dd.c:937)
  [40645.861687] bus_for_each_drv (./drivers/base/bus.c:427)
  [40645.865705] __device_attach (./drivers/base/dd.c:1010)
  [40645.869634] device_initial_probe (./drivers/base/dd.c:1058)
  [40645.873825] bus_probe_device (./drivers/base/bus.c:489)
  [40645.877843] deferred_probe_work_func (./drivers/base/dd.c:124)
  [40645.882554] process_one_work (./arch/arm64/include/asm/jump_label.h:21 ./include/linux/jump_label.h:207 ./include/trace/events/workqueue.h:108 ./kernel/workqueue.c:2294)
  [40645.886657] worker_thread (./include/linux/list.h:292 ./kernel/workqueue.c:2349 ./kernel/workqueue.c:2441)
  [40645.890416] kthread (./kernel/kthread.c:376)
  [40645.893652] ret_from_fork (./arch/arm64/kernel/entry.S:861)
  [40645.897238]
  [40645.898732] The buggy address belongs to the object at ffff000007350000
  [40645.898732]  which belongs to the cache kmalloc-8k of size 8192
  [40645.911255] The buggy address is located 1360 bytes inside of
  [40645.911255]  8192-byte region [ffff000007350000, ffff000007352000)
  [40645.923174]
  [40645.924668] The buggy address belongs to the physical page:
  [40645.930249] page:000000007de421b8 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x47350
  [40645.939590] head:000000007de421b8 order:3 compound_mapcount:0 compound_pincount:0
  [40645.947080] flags: 0x10200(slab|head|node=0|zone=0)
  [40645.951980] raw: 0000000000010200 0000000000000000 dead000000000122 ffff000003c02c00
  [40645.959728] raw: 0000000000000000 0000000080020002 00000001ffffffff 0000000000000000
  [40645.967474] page dumped because: kasan: bad access detected
  [40645.973049]
  [40645.974541] Memory state around the buggy address:
  [40645.979340]  ffff000007350400: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
  [40645.986568]  ffff000007350480: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
  [40645.993795] >ffff000007350500: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
  [40646.001021]                                                  ^
  [40646.006860]  ffff000007350580: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
  [40646.014089]  ffff000007350600: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
  [40646.021315] ==================================================================
  [40646.028664] Disabling lock debugging due to kernel taint


I originally thought it to be a regression, because after going from
v5.18.5 to v6.0.2, an oops started to appear on every reboot.
With the script above I can reproduce this with v5.18.5 though too.
Looks like the freed memory is now reused in my configuration, whereas before
it wasn't. Nevertheless, here's the KASAN log during shutdown (line numbers
are a bit off, because the system below is running v6.0.2 with PREEMPT_RT and
a couple more patches):


  [  538.506709] ==================================================================
  [  538.514542] BUG: KASAN: use-after-free in rtnl_fill_ifinfo (./include/linux/device.h:704 (discriminator 1) ./net/core/rtnetlink.c:1859 (discriminator 1))
  [  538.521316] Read of size 8 at addr ffff0000075ec568 by task mdnsd/908
  [  538.527795]
  [  538.529311] CPU: 1 PID: 908 Comm: mdnsd Tainted: G           O       6.0.2-20221018-2-rt9 #1
  [  538.529328] Hardware name: Some i.MX8MM Innocomm WB15 based system (DT)
  [  538.529339] Call trace:
  [  538.529343] dump_backtrace (./arch/arm64/kernel/stacktrace.c:184)
  [  538.529368] show_stack (./arch/arm64/kernel/stacktrace.c:191)
  [  538.529382] dump_stack_lvl (./lib/dump_stack.c:107 (discriminator 1))
  [  538.529405] print_report (./include/linux/mm.h:851 ./mm/kasan/report.c:214 ./mm/kasan/report.c:315 ./mm/kasan/report.c:433)
  [  538.529422] kasan_report (./mm/kasan/report.c:162 ./mm/kasan/report.c:497)
  [  538.529437] __asan_load8 (./mm/kasan/generic.c:256)
  [  538.529451] rtnl_fill_ifinfo (./include/linux/device.h:704 (discriminator 1) ./net/core/rtnetlink.c:1859 (discriminator 1))
  [  538.529474] rtnl_dump_ifinfo (./net/core/rtnetlink.c:2193)
  [  538.529495] netlink_dump (./net/netlink/af_netlink.c:2275)
  [  538.529515] netlink_recvmsg (./net/netlink/af_netlink.c:2002)
  [  538.529533] ____sys_recvmsg (./net/socket.c:995 ./net/socket.c:1013 ./net/socket.c:2701)
  [  538.529551] ___sys_recvmsg (./net/socket.c:2743)
  [  538.529568] __sys_recvmsg (./include/linux/file.h:31 ./net/socket.c:2775)
  [  538.529584] __arm64_sys_recvmsg (./net/socket.c:2780)
  [  538.529602] invoke_syscall (./arch/arm64/kernel/syscall.c:38 ./arch/arm64/kernel/syscall.c:52)
  [  538.529622] el0_svc_common.constprop.0 (./arch/arm64/include/asm/daifflags.h:28 ./arch/arm64/kernel/syscall.c:150)
  [  538.529644] do_el0_svc (./arch/arm64/kernel/syscall.c:207)
  [  538.529662] el0_svc (./arch/arm64/kernel/entry-common.c:133 ./arch/arm64/kernel/entry-common.c:142 ./arch/arm64/kernel/entry-common.c:625)
  [  538.529679] el0t_64_sync_handler (./arch/arm64/kernel/entry-common.c:643)
  [  538.529700] el0t_64_sync (./arch/arm64/kernel/entry.S:581)
  [  538.529781]
  [  538.623543] Allocated by task 0:
  [  538.627558] (stack is not available)
  [  538.631183]
  [  538.634283] Freed by task 2480:
  [  538.637460] kasan_save_stack (./mm/kasan/common.c:39)
  [  538.641409] kasan_set_track (./mm/kasan/common.c:45)
  [  538.645261] kasan_set_free_info (./include/linux/kasan.h:59 ./mm/kasan/generic.c:372)
  [  538.649415] ____kasan_slab_free (./mm/kasan/common.c:369 ./mm/kasan/common.c:329)
  [  538.654041] __kasan_slab_free (./mm/kasan/common.c:376)
  [  538.658057] slab_free_freelist_hook (./mm/slub.c:1696)
  [  538.662640] kfree (./mm/slub.c:3622 (discriminator 4) ./mm/slub.c:4648 (discriminator 4))
  [  538.667522] release_nodes (./drivers/base/devres.c:498 (discriminator 3))
  [  538.671171] devres_release_all (./drivers/base/devres.c:513)
  [  538.675325] device_unbind_cleanup (./drivers/base/dd.c:532)
  [  538.680658] device_release_driver_internal (./drivers/base/dd.c:1257 ./drivers/base/dd.c:1275)
  [  538.687827] device_release_driver (./drivers/base/dd.c:1299)
  [  538.692164] bus_remove_device (./drivers/base/bus.c:530)
  [  538.696317] device_del (./drivers/base/core.c:3705)
  [  538.700697] platform_device_del.part.0 (./drivers/base/platform.c:753)
  [  538.705473] platform_device_unregister (./drivers/base/platform.c:551 ./drivers/base/platform.c:794)
  [  538.710239] ci_hdrc_remove_device (./drivers/usb/chipidea/core.c:897)
  [  538.714619] ci_hdrc_imx_remove (./drivers/usb/chipidea/ci_hdrc_imx.c:526)
  [  538.718805] ci_hdrc_imx_shutdown (./drivers/usb/chipidea/ci_hdrc_imx.c:542)
  [  538.723046] platform_shutdown (./drivers/base/platform.c:1439)
  [  538.727565] device_shutdown (./include/linux/device.h:850 ./drivers/base/core.c:4668)
  [  538.731561] kernel_restart (./kernel/reboot.c:258)
  [  538.735277] __do_sys_reboot (./kernel/reboot.c:769)


Any pointers as to which UDC does this correctly, so the chipidea driver can
mimic it? Or is this something the network stack should've taken care of?

Thanks,
Ahmad

-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [BUG] use-after-free after removing UDC with USB Ethernet gadget
  2022-10-25  6:54 [BUG] use-after-free after removing UDC with USB Ethernet gadget Ahmad Fatoum
@ 2022-10-25  8:12 ` Greg KH
  2022-10-25  9:28   ` Ahmad Fatoum
  0 siblings, 1 reply; 4+ messages in thread
From: Greg KH @ 2022-10-25  8:12 UTC (permalink / raw)
  To: Ahmad Fatoum
  Cc: netdev, linux-usb, Peter Chen, Felipe Balbi, johannes.berg,
	Pengutronix Kernel Team, Alvin Šipraga

On Tue, Oct 25, 2022 at 08:54:58AM +0200, Ahmad Fatoum wrote:
> Hi everybody,
> 
> I am running v6.0.2 and can reliably trigger a use-after-free by allocating
> a USB gadget, binding it to the chipidea UDC and the removing the UDC.

How do you remove the UDC?

> The network interface is not removed, but the chipidea SoC glue driver will
> remove the platform_device it had allocated in the probe, which is apparently
> the parent of the network device. When rtnl_fill_ifinfo runs, it will access the
> device parent's name for IFLA_PARENT_DEV_NAME, which is now freed memory.

The gadget removal logic is almost non-existant for most of the function
code.  See Lee's patch to try to fix up the f_hid.c driver last week as
one example.  I imagine they all have this same issue as no one has ever
tried the "remove the gadget device from the running Linux system"
before as it was not an expected use case.

Is this now an expected use case of the kernel?  If so, patches are
welcome to address this in all gadget drivers.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [BUG] use-after-free after removing UDC with USB Ethernet gadget
  2022-10-25  8:12 ` Greg KH
@ 2022-10-25  9:28   ` Ahmad Fatoum
  2022-10-25 10:29     ` Greg KH
  0 siblings, 1 reply; 4+ messages in thread
From: Ahmad Fatoum @ 2022-10-25  9:28 UTC (permalink / raw)
  To: Greg KH
  Cc: netdev, linux-usb, Peter Chen, Felipe Balbi, johannes.berg,
	Pengutronix Kernel Team, Alvin Šipraga

Hello Greg,

On 25.10.22 10:12, Greg KH wrote:
> On Tue, Oct 25, 2022 at 08:54:58AM +0200, Ahmad Fatoum wrote:
>> Hi everybody,
>>
>> I am running v6.0.2 and can reliably trigger a use-after-free by allocating
>> a USB gadget, binding it to the chipidea UDC and the removing the UDC.
> 
> How do you remove the UDC?

I originally saw this while doing reboot -f on the device. The imx_usb driver's
shutdown handler is equivalent to the remove handler and that removes the UDC.

It could also be triggered with:

  echo ci_hdrc.0 > /sys/class/udc/ci_hdrc.0/device/driver/unbind

>> The network interface is not removed, but the chipidea SoC glue driver will
>> remove the platform_device it had allocated in the probe, which is apparently
>> the parent of the network device. When rtnl_fill_ifinfo runs, it will access the
>> device parent's name for IFLA_PARENT_DEV_NAME, which is now freed memory.
> 
> The gadget removal logic is almost non-existant for most of the function
> code.  See Lee's patch to try to fix up the f_hid.c driver last week as
> one example.  I imagine they all have this same issue as no one has ever
> tried the "remove the gadget device from the running Linux system"
> before as it was not an expected use case.

I see.

FTR: https://lore.kernel.org/all/20221017112737.230772-1-lee@kernel.org/
 
> Is this now an expected use case of the kernel?  If so, patches are
> welcome to address this in all gadget drivers.

I don't really care for unbinding via sysfs. I want to avoid the
use-after-free on reboot/shutdown. See the last splat in my original mail.

Cheers,
Ahmad


> 
> thanks,
> 
> greg k-h
> 


-- 
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [BUG] use-after-free after removing UDC with USB Ethernet gadget
  2022-10-25  9:28   ` Ahmad Fatoum
@ 2022-10-25 10:29     ` Greg KH
  0 siblings, 0 replies; 4+ messages in thread
From: Greg KH @ 2022-10-25 10:29 UTC (permalink / raw)
  To: Ahmad Fatoum
  Cc: netdev, linux-usb, Peter Chen, Felipe Balbi, johannes.berg,
	Pengutronix Kernel Team, Alvin Šipraga

On Tue, Oct 25, 2022 at 11:28:24AM +0200, Ahmad Fatoum wrote:
> Hello Greg,
> 
> On 25.10.22 10:12, Greg KH wrote:
> > On Tue, Oct 25, 2022 at 08:54:58AM +0200, Ahmad Fatoum wrote:
> >> Hi everybody,
> >>
> >> I am running v6.0.2 and can reliably trigger a use-after-free by allocating
> >> a USB gadget, binding it to the chipidea UDC and the removing the UDC.
> > 
> > How do you remove the UDC?
> 
> I originally saw this while doing reboot -f on the device. The imx_usb driver's
> shutdown handler is equivalent to the remove handler and that removes the UDC.

That's odd, why isn't the network device being shutdown first?  The tree
of devices should be walked in child-first order and tear it down
correctly.

> It could also be triggered with:
> 
>   echo ci_hdrc.0 > /sys/class/udc/ci_hdrc.0/device/driver/unbind

Yes, manual removal as root can cause problems as I said.  The code was
never designed to handle this.

> >> The network interface is not removed, but the chipidea SoC glue driver will
> >> remove the platform_device it had allocated in the probe, which is apparently
> >> the parent of the network device. When rtnl_fill_ifinfo runs, it will access the
> >> device parent's name for IFLA_PARENT_DEV_NAME, which is now freed memory.
> > 
> > The gadget removal logic is almost non-existant for most of the function
> > code.  See Lee's patch to try to fix up the f_hid.c driver last week as
> > one example.  I imagine they all have this same issue as no one has ever
> > tried the "remove the gadget device from the running Linux system"
> > before as it was not an expected use case.
> 
> I see.
> 
> FTR: https://lore.kernel.org/all/20221017112737.230772-1-lee@kernel.org/
>  
> > Is this now an expected use case of the kernel?  If so, patches are
> > welcome to address this in all gadget drivers.
> 
> I don't really care for unbinding via sysfs. I want to avoid the
> use-after-free on reboot/shutdown. See the last splat in my original mail.

Maybe try to figure out what is tearing down the bus's devices in the
incorrect order?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2022-10-25 10:29 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-10-25  6:54 [BUG] use-after-free after removing UDC with USB Ethernet gadget Ahmad Fatoum
2022-10-25  8:12 ` Greg KH
2022-10-25  9:28   ` Ahmad Fatoum
2022-10-25 10:29     ` Greg KH

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.