1. 05 8月, 2021 1 次提交
  2. 09 6月, 2021 1 次提交
    • A
      usb: gadget: f_fs: Fix setting of device and driver data cross-references · ecfbd7b9
      Andrew Gabbasov 提交于
      FunctionFS device structure 'struct ffs_dev' and driver data structure
      'struct ffs_data' are bound to each other with cross-reference pointers
      'ffs_data->private_data' and 'ffs_dev->ffs_data'. While the first one
      is supposed to be valid through the whole life of 'struct ffs_data'
      (and while 'struct ffs_dev' exists non-freed), the second one is cleared
      in 'ffs_closed()' (called from 'ffs_data_reset()' or the last
      'ffs_data_put()'). This can be called several times, alternating in
      different order with 'ffs_free_inst()', that, if possible, clears
      the other cross-reference.
      
      As a result, different cases of these calls order may leave stale
      cross-reference pointers, used when the pointed structure is already
      freed. Even if it occasionally doesn't cause kernel crash, this error
      is reported by KASAN-enabled kernel configuration.
      
      For example, the case [last 'ffs_data_put()' - 'ffs_free_inst()'] was
      fixed by commit cdafb6d8 ("usb: gadget: f_fs: Fix use-after-free in
      ffs_free_inst").
      
      The other case ['ffs_data_reset()' - 'ffs_free_inst()' - 'ffs_data_put()']
      now causes KASAN reported error [1], when 'ffs_data_reset()' clears
      'ffs_dev->ffs_data', then 'ffs_free_inst()' frees the 'struct ffs_dev',
      but can't clear 'ffs_data->private_data', which is then accessed
      in 'ffs_closed()' called from 'ffs_data_put()'. This happens since
      'ffs_dev->ffs_data' reference is cleared too early.
      
      Moreover, one more use case, when 'ffs_free_inst()' is called immediately
      after mounting FunctionFS device (that is before the descriptors are
      written and 'ffs_ready()' is called), and then 'ffs_data_reset()'
      or 'ffs_data_put()' is called from accessing "ep0" file or unmounting
      the device. This causes KASAN error report like [2], since
      'ffs_dev->ffs_data' is not yet set when 'ffs_free_inst()' can't properly
      clear 'ffs_data->private_data', that is later accessed to freed structure.
      
      Fix these (and may be other) cases of stale pointers access by moving
      setting and clearing of the mentioned cross-references to the single
      places, setting both of them when 'struct ffs_data' is created and
      bound to 'struct ffs_dev', and clearing both of them when one of the
      structures is destroyed. It seems convenient to make this pointer
      initialization and structures binding in 'ffs_acquire_dev()' and
      make pointers clearing in 'ffs_release_dev()'. This required some
      changes in these functions parameters and return types.
      
      Also, 'ffs_release_dev()' calling requires some cleanup, fixing minor
      issues, like (1) 'ffs_release_dev()' is not called if 'ffs_free_inst()'
      is called without unmounting the device, and "release_dev" callback
      is not called at all, or (2) "release_dev" callback is called before
      "ffs_closed" callback on unmounting, which seems to be not correctly
      nested with "acquire_dev" and "ffs_ready" callbacks.
      Make this cleanup togther with other mentioned 'ffs_release_dev()' changes.
      
      [1]
      ==================================================================
      root@rcar-gen3:~# mkdir /dev/cfs
      root@rcar-gen3:~# mkdir /dev/ffs
      root@rcar-gen3:~# modprobe libcomposite
      root@rcar-gen3:~# mount -t configfs none /dev/cfs
      root@rcar-gen3:~# mkdir /dev/cfs/usb_gadget/g1
      root@rcar-gen3:~# mkdir /dev/cfs/usb_gadget/g1/functions/ffs.ffs
      [   64.340664] file system registered
      root@rcar-gen3:~# mount -t functionfs ffs /dev/ffs
      root@rcar-gen3:~# cd /dev/ffs
      root@rcar-gen3:/dev/ffs# /home/root/ffs-test
      ffs-test: info: ep0: writing descriptors (in v2 format)
      [   83.181442] read descriptors
      [   83.186085] read strings
      ffs-test: info: ep0: writing strings
      ffs-test: dbg:  ep1: starting
      ffs-test: dbg:  ep2: starting
      ffs-test: info: ep1: starts
      ffs-test: info: ep2: starts
      ffs-test: info: ep0: starts
      
      ^C
      root@rcar-gen3:/dev/ffs# cd /home/root/
      root@rcar-gen3:~# rmdir /dev/cfs/usb_gadget/g1/functions/ffs.ffs
      [   98.935061] unloading
      root@rcar-gen3:~# umount /dev/ffs
      [  102.734301] ==================================================================
      [  102.742059] BUG: KASAN: use-after-free in ffs_release_dev+0x64/0xa8 [usb_f_fs]
      [  102.749683] Write of size 1 at addr ffff0004d46ff549 by task umount/2997
      [  102.756709]
      [  102.758311] CPU: 0 PID: 2997 Comm: umount Not tainted 5.13.0-rc4+ #8
      [  102.764971] Hardware name: Renesas Salvator-X board based on r8a77951 (DT)
      [  102.772179] Call trace:
      [  102.774779]  dump_backtrace+0x0/0x330
      [  102.778653]  show_stack+0x20/0x2c
      [  102.782152]  dump_stack+0x11c/0x1ac
      [  102.785833]  print_address_description.constprop.0+0x30/0x274
      [  102.791862]  kasan_report+0x14c/0x1c8
      [  102.795719]  __asan_report_store1_noabort+0x34/0x58
      [  102.800840]  ffs_release_dev+0x64/0xa8 [usb_f_fs]
      [  102.805801]  ffs_fs_kill_sb+0x50/0x84 [usb_f_fs]
      [  102.810663]  deactivate_locked_super+0xa0/0xf0
      [  102.815339]  deactivate_super+0x98/0xac
      [  102.819378]  cleanup_mnt+0xd0/0x1b0
      [  102.823057]  __cleanup_mnt+0x1c/0x28
      [  102.826823]  task_work_run+0x104/0x180
      [  102.830774]  do_notify_resume+0x458/0x14e0
      [  102.835083]  work_pending+0xc/0x5f8
      [  102.838762]
      [  102.840357] Allocated by task 2988:
      [  102.844032]  kasan_save_stack+0x28/0x58
      [  102.848071]  kasan_set_track+0x28/0x3c
      [  102.852016]  ____kasan_kmalloc+0x84/0x9c
      [  102.856142]  __kasan_kmalloc+0x10/0x1c
      [  102.860088]  __kmalloc+0x214/0x2f8
      [  102.863678]  kzalloc.constprop.0+0x14/0x20 [usb_f_fs]
      [  102.868990]  ffs_alloc_inst+0x8c/0x208 [usb_f_fs]
      [  102.873942]  try_get_usb_function_instance+0xf0/0x164 [libcomposite]
      [  102.880629]  usb_get_function_instance+0x64/0x68 [libcomposite]
      [  102.886858]  function_make+0x128/0x1ec [libcomposite]
      [  102.892185]  configfs_mkdir+0x330/0x590 [configfs]
      [  102.897245]  vfs_mkdir+0x12c/0x1bc
      [  102.900835]  do_mkdirat+0x180/0x1d0
      [  102.904513]  __arm64_sys_mkdirat+0x80/0x94
      [  102.908822]  invoke_syscall+0xf8/0x25c
      [  102.912772]  el0_svc_common.constprop.0+0x150/0x1a0
      [  102.917891]  do_el0_svc+0xa0/0xd4
      [  102.921386]  el0_svc+0x24/0x34
      [  102.924613]  el0_sync_handler+0xcc/0x154
      [  102.928743]  el0_sync+0x198/0x1c0
      [  102.932238]
      [  102.933832] Freed by task 2996:
      [  102.937144]  kasan_save_stack+0x28/0x58
      [  102.941181]  kasan_set_track+0x28/0x3c
      [  102.945128]  kasan_set_free_info+0x28/0x4c
      [  102.949435]  ____kasan_slab_free+0x104/0x118
      [  102.953921]  __kasan_slab_free+0x18/0x24
      [  102.958047]  slab_free_freelist_hook+0x148/0x1f0
      [  102.962897]  kfree+0x318/0x440
      [  102.966123]  ffs_free_inst+0x164/0x2d8 [usb_f_fs]
      [  102.971075]  usb_put_function_instance+0x84/0xa4 [libcomposite]
      [  102.977302]  ffs_attr_release+0x18/0x24 [usb_f_fs]
      [  102.982344]  config_item_put+0x140/0x1a4 [configfs]
      [  102.987486]  configfs_rmdir+0x3fc/0x518 [configfs]
      [  102.992535]  vfs_rmdir+0x114/0x234
      [  102.996122]  do_rmdir+0x274/0x2b0
      [  102.999617]  __arm64_sys_unlinkat+0x94/0xc8
      [  103.004015]  invoke_syscall+0xf8/0x25c
      [  103.007961]  el0_svc_common.constprop.0+0x150/0x1a0
      [  103.013080]  do_el0_svc+0xa0/0xd4
      [  103.016575]  el0_svc+0x24/0x34
      [  103.019801]  el0_sync_handler+0xcc/0x154
      [  103.023930]  el0_sync+0x198/0x1c0
      [  103.027426]
      [  103.029020] The buggy address belongs to the object at ffff0004d46ff500
      [  103.029020]  which belongs to the cache kmalloc-128 of size 128
      [  103.042079] The buggy address is located 73 bytes inside of
      [  103.042079]  128-byte region [ffff0004d46ff500, ffff0004d46ff580)
      [  103.054236] The buggy address belongs to the page:
      [  103.059262] page:0000000021aa849b refcount:1 mapcount:0 mapping:0000000000000000 index:0xffff0004d46fee00 pfn:0x5146fe
      [  103.070437] head:0000000021aa849b order:1 compound_mapcount:0
      [  103.076456] flags: 0x8000000000010200(slab|head|zone=2)
      [  103.081948] raw: 8000000000010200 fffffc0013521a80 0000000d0000000d ffff0004c0002300
      [  103.090052] raw: ffff0004d46fee00 000000008020001e 00000001ffffffff 0000000000000000
      [  103.098150] page dumped because: kasan: bad access detected
      [  103.103985]
      [  103.105578] Memory state around the buggy address:
      [  103.110602]  ffff0004d46ff400: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
      [  103.118161]  ffff0004d46ff480: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
      [  103.125726] >ffff0004d46ff500: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
      [  103.133284]                                               ^
      [  103.139120]  ffff0004d46ff580: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
      [  103.146679]  ffff0004d46ff600: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
      [  103.154238] ==================================================================
      [  103.161792] Disabling lock debugging due to kernel taint
      [  103.167319] Unable to handle kernel paging request at virtual address 0037801d6000018e
      [  103.175406] Mem abort info:
      [  103.178457]   ESR = 0x96000004
      [  103.181609]   EC = 0x25: DABT (current EL), IL = 32 bits
      [  103.187020]   SET = 0, FnV = 0
      [  103.190185]   EA = 0, S1PTW = 0
      [  103.193417] Data abort info:
      [  103.196385]   ISV = 0, ISS = 0x00000004
      [  103.200315]   CM = 0, WnR = 0
      [  103.203366] [0037801d6000018e] address between user and kernel address ranges
      [  103.210611] Internal error: Oops: 96000004 [#1] PREEMPT SMP
      [  103.216231] Modules linked in: usb_f_fs libcomposite configfs ath9k_htc led_class mac80211 libarc4 ath9k_common ath9k_hw ath cfg80211 aes_ce_blk sata_rc4
      [  103.259233] CPU: 0 PID: 2997 Comm: umount Tainted: G    B             5.13.0-rc4+ #8
      [  103.267031] Hardware name: Renesas Salvator-X board based on r8a77951 (DT)
      [  103.273951] pstate: 00000005 (nzcv daif -PAN -UAO -TCO BTYPE=--)
      [  103.280001] pc : ffs_data_clear+0x138/0x370 [usb_f_fs]
      [  103.285197] lr : ffs_data_clear+0x124/0x370 [usb_f_fs]
      [  103.290385] sp : ffff800014777a80
      [  103.293725] x29: ffff800014777a80 x28: ffff0004d7649c80 x27: 0000000000000000
      [  103.300931] x26: ffff800014777fb0 x25: ffff60009aec9394 x24: ffff0004d7649ca4
      [  103.308136] x23: 1fffe0009a3d063a x22: dfff800000000000 x21: ffff0004d1e831d0
      [  103.315340] x20: e1c000eb00000bb4 x19: ffff0004d1e83000 x18: 0000000000000000
      [  103.322545] x17: 0000000000000000 x16: 0000000000000000 x15: 0000000000000000
      [  103.329748] x14: 0720072007200720 x13: 0720072007200720 x12: 1ffff000012ef658
      [  103.336952] x11: ffff7000012ef658 x10: 0720072007200720 x9 : ffff800011322648
      [  103.344157] x8 : ffff800014777818 x7 : ffff80000977b2c7 x6 : 0000000000000000
      [  103.351359] x5 : 0000000000000001 x4 : ffff7000012ef659 x3 : 0000000000000001
      [  103.358562] x2 : 0000000000000000 x1 : 1c38001d6000018e x0 : e1c000eb00000c70
      [  103.365766] Call trace:
      [  103.368235]  ffs_data_clear+0x138/0x370 [usb_f_fs]
      [  103.373076]  ffs_data_reset+0x20/0x304 [usb_f_fs]
      [  103.377829]  ffs_data_closed+0x1ec/0x244 [usb_f_fs]
      [  103.382755]  ffs_fs_kill_sb+0x70/0x84 [usb_f_fs]
      [  103.387420]  deactivate_locked_super+0xa0/0xf0
      [  103.391905]  deactivate_super+0x98/0xac
      [  103.395776]  cleanup_mnt+0xd0/0x1b0
      [  103.399299]  __cleanup_mnt+0x1c/0x28
      [  103.402906]  task_work_run+0x104/0x180
      [  103.406691]  do_notify_resume+0x458/0x14e0
      [  103.410823]  work_pending+0xc/0x5f8
      [  103.414351] Code: b4000a54 9102f280 12000802 d343fc01 (38f66821)
      [  103.420490] ---[ end trace 57b43a50e8244f57 ]---
      Segmentation fault
      root@rcar-gen3:~#
      ==================================================================
      
      [2]
      ==================================================================
      root@rcar-gen3:~# mkdir /dev/ffs
      root@rcar-gen3:~# modprobe libcomposite
      root@rcar-gen3:~#
      root@rcar-gen3:~# mount -t configfs none /dev/cfs
      root@rcar-gen3:~# mkdir /dev/cfs/usb_gadget/g1
      root@rcar-gen3:~# mkdir /dev/cfs/usb_gadget/g1/functions/ffs.ffs
      [   54.766480] file system registered
      root@rcar-gen3:~# mount -t functionfs ffs /dev/ffs
      root@rcar-gen3:~# rmdir /dev/cfs/usb_gadget/g1/functions/ffs.ffs
      [   63.197597] unloading
      root@rcar-gen3:~# cat /dev/ffs/ep0
      cat: read error:[   67.213506] ==================================================================
      [   67.222095] BUG: KASAN: use-after-free in ffs_data_clear+0x70/0x370 [usb_f_fs]
      [   67.229699] Write of size 1 at addr ffff0004c26e974a by task cat/2994
      [   67.236446]
      [   67.238045] CPU: 0 PID: 2994 Comm: cat Not tainted 5.13.0-rc4+ #8
      [   67.244431] Hardware name: Renesas Salvator-X board based on r8a77951 (DT)
      [   67.251624] Call trace:
      [   67.254212]  dump_backtrace+0x0/0x330
      [   67.258081]  show_stack+0x20/0x2c
      [   67.261579]  dump_stack+0x11c/0x1ac
      [   67.265260]  print_address_description.constprop.0+0x30/0x274
      [   67.271286]  kasan_report+0x14c/0x1c8
      [   67.275143]  __asan_report_store1_noabort+0x34/0x58
      [   67.280265]  ffs_data_clear+0x70/0x370 [usb_f_fs]
      [   67.285220]  ffs_data_reset+0x20/0x304 [usb_f_fs]
      [   67.290172]  ffs_data_closed+0x240/0x244 [usb_f_fs]
      [   67.295305]  ffs_ep0_release+0x40/0x54 [usb_f_fs]
      [   67.300256]  __fput+0x304/0x580
      [   67.303576]  ____fput+0x18/0x24
      [   67.306893]  task_work_run+0x104/0x180
      [   67.310846]  do_notify_resume+0x458/0x14e0
      [   67.315154]  work_pending+0xc/0x5f8
      [   67.318834]
      [   67.320429] Allocated by task 2988:
      [   67.324105]  kasan_save_stack+0x28/0x58
      [   67.328144]  kasan_set_track+0x28/0x3c
      [   67.332090]  ____kasan_kmalloc+0x84/0x9c
      [   67.336217]  __kasan_kmalloc+0x10/0x1c
      [   67.340163]  __kmalloc+0x214/0x2f8
      [   67.343754]  kzalloc.constprop.0+0x14/0x20 [usb_f_fs]
      [   67.349066]  ffs_alloc_inst+0x8c/0x208 [usb_f_fs]
      [   67.354017]  try_get_usb_function_instance+0xf0/0x164 [libcomposite]
      [   67.360705]  usb_get_function_instance+0x64/0x68 [libcomposite]
      [   67.366934]  function_make+0x128/0x1ec [libcomposite]
      [   67.372260]  configfs_mkdir+0x330/0x590 [configfs]
      [   67.377320]  vfs_mkdir+0x12c/0x1bc
      [   67.380911]  do_mkdirat+0x180/0x1d0
      [   67.384589]  __arm64_sys_mkdirat+0x80/0x94
      [   67.388899]  invoke_syscall+0xf8/0x25c
      [   67.392850]  el0_svc_common.constprop.0+0x150/0x1a0
      [   67.397969]  do_el0_svc+0xa0/0xd4
      [   67.401464]  el0_svc+0x24/0x34
      [   67.404691]  el0_sync_handler+0xcc/0x154
      [   67.408819]  el0_sync+0x198/0x1c0
      [   67.412315]
      [   67.413909] Freed by task 2993:
      [   67.417220]  kasan_save_stack+0x28/0x58
      [   67.421257]  kasan_set_track+0x28/0x3c
      [   67.425204]  kasan_set_free_info+0x28/0x4c
      [   67.429513]  ____kasan_slab_free+0x104/0x118
      [   67.434001]  __kasan_slab_free+0x18/0x24
      [   67.438128]  slab_free_freelist_hook+0x148/0x1f0
      [   67.442978]  kfree+0x318/0x440
      [   67.446205]  ffs_free_inst+0x164/0x2d8 [usb_f_fs]
      [   67.451156]  usb_put_function_instance+0x84/0xa4 [libcomposite]
      [   67.457385]  ffs_attr_release+0x18/0x24 [usb_f_fs]
      [   67.462428]  config_item_put+0x140/0x1a4 [configfs]
      [   67.467570]  configfs_rmdir+0x3fc/0x518 [configfs]
      [   67.472626]  vfs_rmdir+0x114/0x234
      [   67.476215]  do_rmdir+0x274/0x2b0
      [   67.479710]  __arm64_sys_unlinkat+0x94/0xc8
      [   67.484108]  invoke_syscall+0xf8/0x25c
      [   67.488055]  el0_svc_common.constprop.0+0x150/0x1a0
      [   67.493175]  do_el0_svc+0xa0/0xd4
      [   67.496671]  el0_svc+0x24/0x34
      [   67.499896]  el0_sync_handler+0xcc/0x154
      [   67.504024]  el0_sync+0x198/0x1c0
      [   67.507520]
      [   67.509114] The buggy address belongs to the object at ffff0004c26e9700
      [   67.509114]  which belongs to the cache kmalloc-128 of size 128
      [   67.522171] The buggy address is located 74 bytes inside of
      [   67.522171]  128-byte region [ffff0004c26e9700, ffff0004c26e9780)
      [   67.534328] The buggy address belongs to the page:
      [   67.539355] page:000000003177a217 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x5026e8
      [   67.549175] head:000000003177a217 order:1 compound_mapcount:0
      [   67.555195] flags: 0x8000000000010200(slab|head|zone=2)
      [   67.560687] raw: 8000000000010200 fffffc0013037100 0000000c00000002 ffff0004c0002300
      [   67.568791] raw: 0000000000000000 0000000080200020 00000001ffffffff 0000000000000000
      [   67.576890] page dumped because: kasan: bad access detected
      [   67.582725]
      [   67.584318] Memory state around the buggy address:
      [   67.589343]  ffff0004c26e9600: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
      [   67.596903]  ffff0004c26e9680: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
      [   67.604463] >ffff0004c26e9700: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
      [   67.612022]                                               ^
      [   67.617860]  ffff0004c26e9780: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
      [   67.625421]  ffff0004c26e9800: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
      [   67.632981] ==================================================================
      [   67.640535] Disabling lock debugging due to kernel taint
       File descriptor[   67.646100] Unable to handle kernel paging request at virtual address fabb801d4000018d
       in bad state
      [   67.655456] Mem abort info:
      [   67.659619]   ESR = 0x96000004
      [   67.662801]   EC = 0x25: DABT (current EL), IL = 32 bits
      [   67.668225]   SET = 0, FnV = 0
      [   67.671375]   EA = 0, S1PTW = 0
      [   67.674613] Data abort info:
      [   67.677587]   ISV = 0, ISS = 0x00000004
      [   67.681522]   CM = 0, WnR = 0
      [   67.684588] [fabb801d4000018d] address between user and kernel address ranges
      [   67.691849] Internal error: Oops: 96000004 [#1] PREEMPT SMP
      [   67.697470] Modules linked in: usb_f_fs libcomposite configfs ath9k_htc led_class mac80211 libarc4 ath9k_common ath9k_hw ath cfg80211 aes_ce_blk crypto_simd cryptd aes_ce_cipher ghash_ce gf128mul sha2_ce sha1_ce evdev sata_rcar libata xhci_plat_hcd scsi_mod xhci_hcd rene4
      [   67.740467] CPU: 0 PID: 2994 Comm: cat Tainted: G    B             5.13.0-rc4+ #8
      [   67.748005] Hardware name: Renesas Salvator-X board based on r8a77951 (DT)
      [   67.754924] pstate: 00000005 (nzcv daif -PAN -UAO -TCO BTYPE=--)
      [   67.760974] pc : ffs_data_clear+0x138/0x370 [usb_f_fs]
      [   67.766178] lr : ffs_data_clear+0x124/0x370 [usb_f_fs]
      [   67.771365] sp : ffff800014767ad0
      [   67.774706] x29: ffff800014767ad0 x28: ffff800009cf91c0 x27: ffff0004c54861a0
      [   67.781913] x26: ffff0004dc90b288 x25: 1fffe00099ec10f5 x24: 00000000000a801d
      [   67.789118] x23: 1fffe00099f6953a x22: dfff800000000000 x21: ffff0004cfb4a9d0
      [   67.796322] x20: d5e000ea00000bb1 x19: ffff0004cfb4a800 x18: 0000000000000000
      [   67.803526] x17: 0000000000000000 x16: 0000000000000000 x15: 0000000000000000
      [   67.810730] x14: 0720072007200720 x13: 0720072007200720 x12: 1ffff000028ecefa
      [   67.817934] x11: ffff7000028ecefa x10: 0720072007200720 x9 : ffff80001132c014
      [   67.825137] x8 : ffff8000147677d8 x7 : ffff8000147677d7 x6 : 0000000000000000
      [   67.832341] x5 : 0000000000000001 x4 : ffff7000028ecefb x3 : 0000000000000001
      [   67.839544] x2 : 0000000000000005 x1 : 1abc001d4000018d x0 : d5e000ea00000c6d
      [   67.846748] Call trace:
      [   67.849218]  ffs_data_clear+0x138/0x370 [usb_f_fs]
      [   67.854058]  ffs_data_reset+0x20/0x304 [usb_f_fs]
      [   67.858810]  ffs_data_closed+0x240/0x244 [usb_f_fs]
      [   67.863736]  ffs_ep0_release+0x40/0x54 [usb_f_fs]
      [   67.868488]  __fput+0x304/0x580
      [   67.871665]  ____fput+0x18/0x24
      [   67.874837]  task_work_run+0x104/0x180
      [   67.878622]  do_notify_resume+0x458/0x14e0
      [   67.882754]  work_pending+0xc/0x5f8
      [   67.886282] Code: b4000a54 9102f280 12000802 d343fc01 (38f66821)
      [   67.892422] ---[ end trace 6d7cedf53d7abbea ]---
      Segmentation fault
      root@rcar-gen3:~#
      ==================================================================
      
      Fixes: 4b187fce ("usb: gadget: FunctionFS: add devices management code")
      Fixes: 3262ad82 ("usb: gadget: f_fs: Stop ffs_closed NULL pointer dereference")
      Fixes: cdafb6d8 ("usb: gadget: f_fs: Fix use-after-free in ffs_free_inst")
      Reported-by: NBhuvanesh Surachari <bhuvanesh_surachari@mentor.com>
      Tested-by: NEugeniu Rosca <erosca@de.adit-jv.com>
      Reviewed-by: NEugeniu Rosca <erosca@de.adit-jv.com>
      Signed-off-by: NAndrew Gabbasov <andrew_gabbasov@mentor.com>
      Link: https://lore.kernel.org/r/20210603171507.22514-1-andrew_gabbasov@mentor.comSigned-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      ecfbd7b9
  3. 04 6月, 2021 1 次提交
  4. 23 3月, 2021 2 次提交
  5. 10 12月, 2020 2 次提交
  6. 04 12月, 2020 1 次提交
  7. 24 11月, 2020 1 次提交
  8. 10 7月, 2020 1 次提交
  9. 09 7月, 2020 1 次提交
    • L
      usb: gadget: function: f_fs: Demote function header which is clearly not kerneldoc · 8f9a0e10
      Lee Jones 提交于
      No attempt has been made to document the demoted function here.
      
      Fixes the following W=1 kernel build warning(s):
      
       drivers/usb/gadget/function/f_fs.c:2361: warning: Function parameter or member 'type' not described in '__ffs_data_do_os_desc'
       drivers/usb/gadget/function/f_fs.c:2361: warning: Function parameter or member 'h' not described in '__ffs_data_do_os_desc'
       drivers/usb/gadget/function/f_fs.c:2361: warning: Function parameter or member 'data' not described in '__ffs_data_do_os_desc'
       drivers/usb/gadget/function/f_fs.c:2361: warning: Function parameter or member 'len' not described in '__ffs_data_do_os_desc'
       drivers/usb/gadget/function/f_fs.c:2361: warning: Function parameter or member 'priv' not described in '__ffs_data_do_os_desc'
      
      Cc: Felipe Balbi <balbi@kernel.org>
      Cc: David Howells <dhowells@redhat.com>
      Cc: Michal Nazarewicz <mina86@mina86.com>
      Signed-off-by: NLee Jones <lee.jones@linaro.org>
      Link: https://lore.kernel.org/r/20200706133341.476881-12-lee.jones@linaro.orgSigned-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      8f9a0e10
  10. 11 6月, 2020 3 次提交
  11. 25 5月, 2020 1 次提交
  12. 16 4月, 2020 1 次提交
  13. 26 3月, 2020 1 次提交
  14. 21 3月, 2020 1 次提交
    • T
      completion: Use simple wait queues · a5c6234e
      Thomas Gleixner 提交于
      completion uses a wait_queue_head_t to enqueue waiters.
      
      wait_queue_head_t contains a spinlock_t to protect the list of waiters
      which excludes it from being used in truly atomic context on a PREEMPT_RT
      enabled kernel.
      
      The spinlock in the wait queue head cannot be replaced by a raw_spinlock
      because:
      
        - wait queues can have custom wakeup callbacks, which acquire other
          spinlock_t locks and have potentially long execution times
      
        - wake_up() walks an unbounded number of list entries during the wake up
          and may wake an unbounded number of waiters.
      
      For simplicity and performance reasons complete() should be usable on
      PREEMPT_RT enabled kernels.
      
      completions do not use custom wakeup callbacks and are usually single
      waiter, except for a few corner cases.
      
      Replace the wait queue in the completion with a simple wait queue (swait),
      which uses a raw_spinlock_t for protecting the waiter list and therefore is
      safe to use inside truly atomic regions on PREEMPT_RT.
      
      There is no semantical or functional change:
      
        - completions use the exclusive wait mode which is what swait provides
      
        - complete() wakes one exclusive waiter
      
        - complete_all() wakes all waiters while holding the lock which protects
          the wait queue against newly incoming waiters. The conversion to swait
          preserves this behaviour.
      
      complete_all() might cause unbound latencies with a large number of waiters
      being woken at once, but most complete_all() usage sites are either in
      testing or initialization code or have only a really small number of
      concurrent waiters which for now does not cause a latency problem. Keep it
      simple for now.
      
      The fixup of the warning check in the USB gadget driver is just a straight
      forward conversion of the lockless waiter check from one waitqueue type to
      the other.
      Signed-off-by: NThomas Gleixner <tglx@linutronix.de>
      Signed-off-by: NPeter Zijlstra (Intel) <peterz@infradead.org>
      Reviewed-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      Reviewed-by: NDavidlohr Bueso <dbueso@suse.de>
      Reviewed-by: NJoel Fernandes (Google) <joel@joelfernandes.org>
      Acked-by: NLinus Torvalds <torvalds@linux-foundation.org>
      Link: https://lkml.kernel.org/r/20200321113242.317954042@linutronix.de
      a5c6234e
  15. 11 2月, 2020 1 次提交
  16. 08 2月, 2020 2 次提交
  17. 15 1月, 2020 1 次提交
    • P
      usb: gadget: f_fs: set req->num_sgs as 0 for non-sg transfer · d2450c69
      Peter Chen 提交于
      The UDC core uses req->num_sgs to judge if scatter buffer list is used.
      Eg: usb_gadget_map_request_by_dev. For f_fs sync io mode, the request
      is re-used for each request, so if the 1st request->length > PAGE_SIZE,
      and the 2nd request->length is <= PAGE_SIZE, the f_fs uses the 1st
      req->num_sgs for the 2nd request, it causes the UDC core get the wrong
      req->num_sgs value (The 2nd request doesn't use sg). For f_fs async
      io mode, it is not harm to initialize req->num_sgs as 0 either, in case,
      the UDC driver doesn't zeroed request structure.
      
      Cc: Jun Li <jun.li@nxp.com>
      Cc: stable <stable@vger.kernel.org>
      Fixes: 772a7a72 ("usb: gadget: f_fs: Allow scatter-gather buffers")
      Signed-off-by: NPeter Chen <peter.chen@nxp.com>
      Signed-off-by: NFelipe Balbi <balbi@kernel.org>
      Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      d2450c69
  18. 10 12月, 2019 1 次提交
  19. 23 10月, 2019 1 次提交
  20. 19 9月, 2019 1 次提交
  21. 18 6月, 2019 2 次提交
    • A
      usb: gadget: Zero ffs_io_data · 50859551
      Andrzej Pietrasiewicz 提交于
      In some cases the "Allocate & copy" block in ffs_epfile_io() is not
      executed. Consequently, in such a case ffs_alloc_buffer() is never called
      and struct ffs_io_data is not initialized properly. This in turn leads to
      problems when ffs_free_buffer() is called at the end of ffs_epfile_io().
      
      This patch uses kzalloc() instead of kmalloc() in the aio case and memset()
      in non-aio case to properly initialize struct ffs_io_data.
      Signed-off-by: NAndrzej Pietrasiewicz <andrzej.p@collabora.com>
      Signed-off-by: NFelipe Balbi <felipe.balbi@linux.intel.com>
      50859551
    • F
      usb: gadget: f_fs: data_len used before properly set · 4833a94e
      Fei Yang 提交于
      The following line of code in function ffs_epfile_io is trying to set
      flag io_data->use_sg in case buffer required is larger than one page.
      
          io_data->use_sg = gadget->sg_supported && data_len > PAGE_SIZE;
      
      However at this point of time the variable data_len has not been set
      to the proper buffer size yet. The consequence is that io_data->use_sg
      is always set regardless what buffer size really is, because the condition
      (data_len > PAGE_SIZE) is effectively an unsigned comparison between
      -EINVAL and PAGE_SIZE which would always result in TRUE.
      
      Fixes: 772a7a72 ("usb: gadget: f_fs: Allow scatter-gather buffers")
      Signed-off-by: NFei Yang <fei.yang@intel.com>
      Cc: stable <stable@vger.kernel.org>
      Signed-off-by: NFelipe Balbi <felipe.balbi@linux.intel.com>
      4833a94e
  22. 03 5月, 2019 1 次提交
    • F
      usb: gadget: f_fs: don't free buffer prematurely · 73103c7f
      Fei Yang 提交于
      The following kernel panic happens due to the io_data buffer gets deallocated
      before the async io is completed. Add a check for the case where io_data buffer
      should be deallocated by ffs_user_copy_worker.
      
      [   41.663334] BUG: unable to handle kernel NULL pointer dereference at 0000000000000048
      [   41.672099] #PF error: [normal kernel read fault]
      [   41.677356] PGD 20c974067 P4D 20c974067 PUD 20c973067 PMD 0
      [   41.683687] Oops: 0000 [#1] PREEMPT SMP
      [   41.687976] CPU: 1 PID: 7 Comm: kworker/u8:0 Tainted: G     U            5.0.0-quilt-2e5dc0ac-00790-gd8c79f2-dirty #2
      [   41.705309] Workqueue: adb ffs_user_copy_worker
      [   41.705316] RIP: 0010:__vunmap+0x2a/0xc0
      [   41.705318] Code: 0f 1f 44 00 00 48 85 ff 0f 84 87 00 00 00 55 f7 c7 ff 0f 00 00 48 89 e5 41 55 41 89 f5 41 54 53 48 89 fb 75 71 e8 56 d7 ff ff <4c> 8b 60 48 4d 85 e4 74 76 48 89 df e8 25 ff ff ff 45 85 ed 74 46
      [   41.705320] RSP: 0018:ffffbc3a40053df0 EFLAGS: 00010286
      [   41.705322] RAX: 0000000000000000 RBX: ffffbc3a406f1000 RCX: 0000000000000000
      [   41.705323] RDX: 0000000000000001 RSI: 0000000000000001 RDI: 00000000ffffffff
      [   41.705324] RBP: ffffbc3a40053e08 R08: 000000000001fb79 R09: 0000000000000037
      [   41.705325] R10: ffffbc3a40053b68 R11: ffffbc3a40053cad R12: fffffffffffffff2
      [   41.705326] R13: 0000000000000001 R14: 0000000000000000 R15: ffffffffffffffff
      [   41.705328] FS:  0000000000000000(0000) GS:ffff9e2977a80000(0000) knlGS:0000000000000000
      [   41.705329] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
      [   41.705330] CR2: 0000000000000048 CR3: 000000020c994000 CR4: 00000000003406e0
      [   41.705331] Call Trace:
      [   41.705338]  vfree+0x50/0xb0
      [   41.705341]  ffs_user_copy_worker+0xe9/0x1c0
      [   41.705344]  process_one_work+0x19f/0x3e0
      [   41.705348]  worker_thread+0x3f/0x3b0
      [   41.829766]  kthread+0x12b/0x150
      [   41.833371]  ? process_one_work+0x3e0/0x3e0
      [   41.838045]  ? kthread_create_worker_on_cpu+0x70/0x70
      [   41.843695]  ret_from_fork+0x3a/0x50
      [   41.847689] Modules linked in: hci_uart bluetooth ecdh_generic rfkill_gpio dwc3_pci dwc3 snd_usb_audio mei_me tpm_crb snd_usbmidi_lib xhci_pci xhci_hcd mei tpm snd_hwdep cfg80211 snd_soc_skl snd_soc_skl_ipc snd_soc_sst_ipc snd_soc_sst_dsp snd_hda_ext_core snd_hda_core videobuf2_dma_sg crlmodule
      [   41.876880] CR2: 0000000000000048
      [   41.880584] ---[ end trace 2bc4addff0f2e673 ]---
      [   41.891346] RIP: 0010:__vunmap+0x2a/0xc0
      [   41.895734] Code: 0f 1f 44 00 00 48 85 ff 0f 84 87 00 00 00 55 f7 c7 ff 0f 00 00 48 89 e5 41 55 41 89 f5 41 54 53 48 89 fb 75 71 e8 56 d7 ff ff <4c> 8b 60 48 4d 85 e4 74 76 48 89 df e8 25 ff ff ff 45 85 ed 74 46
      [   41.916740] RSP: 0018:ffffbc3a40053df0 EFLAGS: 00010286
      [   41.922583] RAX: 0000000000000000 RBX: ffffbc3a406f1000 RCX: 0000000000000000
      [   41.930563] RDX: 0000000000000001 RSI: 0000000000000001 RDI: 00000000ffffffff
      [   41.938540] RBP: ffffbc3a40053e08 R08: 000000000001fb79 R09: 0000000000000037
      [   41.946520] R10: ffffbc3a40053b68 R11: ffffbc3a40053cad R12: fffffffffffffff2
      [   41.954502] R13: 0000000000000001 R14: 0000000000000000 R15: ffffffffffffffff
      [   41.962482] FS:  0000000000000000(0000) GS:ffff9e2977a80000(0000) knlGS:0000000000000000
      [   41.971536] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
      [   41.977960] CR2: 0000000000000048 CR3: 000000020c994000 CR4: 00000000003406e0
      [   41.985930] Kernel panic - not syncing: Fatal exception
      [   41.991817] Kernel Offset: 0x16000000 from 0xffffffff81000000 (relocation range: 0xffffffff80000000-0xffffffffbfffffff)
      [   42.009525] Rebooting in 10 seconds..
      [   52.014376] ACPI MEMORY or I/O RESET_REG.
      
      Fixes: 772a7a72 ("usb: gadget: f_fs: Allow scatter-gather buffers")
      Signed-off-by: NFei Yang <fei.yang@intel.com>
      Reviewed-by: NManu Gautam <mgautam@codeaurora.org>
      Tested-by: NJohn Stultz <john.stultz@linaro.org>
      Signed-off-by: NFelipe Balbi <felipe.balbi@linux.intel.com>
      73103c7f
  23. 11 2月, 2019 1 次提交
    • J
      usb: f_fs: Avoid crash due to out-of-scope stack ptr access · 54f64d5c
      John Stultz 提交于
      Since the 5.0 merge window opened, I've been seeing frequent
      crashes on suspend and reboot with the trace:
      
      [   36.911170] Unable to handle kernel paging request at virtual address ffffff801153d660
      [   36.912769] Unable to handle kernel paging request at virtual address ffffff800004b564
      ...
      [   36.950666] Call trace:
      [   36.950670]  queued_spin_lock_slowpath+0x1cc/0x2c8
      [   36.950681]  _raw_spin_lock_irqsave+0x64/0x78
      [   36.950692]  complete+0x28/0x70
      [   36.950703]  ffs_epfile_io_complete+0x3c/0x50
      [   36.950713]  usb_gadget_giveback_request+0x34/0x108
      [   36.950721]  dwc3_gadget_giveback+0x50/0x68
      [   36.950723]  dwc3_thread_interrupt+0x358/0x1488
      [   36.950731]  irq_thread_fn+0x30/0x88
      [   36.950734]  irq_thread+0x114/0x1b0
      [   36.950739]  kthread+0x104/0x130
      [   36.950747]  ret_from_fork+0x10/0x1c
      
      I isolated this down to in ffs_epfile_io():
      https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/usb/gadget/function/f_fs.c#n1065
      
      Where the completion done is setup on the stack:
        DECLARE_COMPLETION_ONSTACK(done);
      
      Then later we setup a request and queue it, and wait for it:
        if (unlikely(wait_for_completion_interruptible(&done))) {
          /*
          * To avoid race condition with ffs_epfile_io_complete,
          * dequeue the request first then check
          * status. usb_ep_dequeue API should guarantee no race
          * condition with req->complete callback.
          */
          usb_ep_dequeue(ep->ep, req);
          interrupted = ep->status < 0;
        }
      
      The problem is, that we end up being interrupted, dequeue the
      request, and exit.
      
      But then the irq triggers and we try calling complete() on the
      context pointer which points to now random stack space, which
      results in the panic.
      
      Alan Stern pointed out there is a bug here, in that the snippet
      above "assumes that usb_ep_dequeue() waits until the request has
      been completed." And that:
      
          wait_for_completion(&done);
      
      Is needed right after the usb_ep_dequeue().
      
      Thus this patch implements that change. With it I no longer see
      the crashes on suspend or reboot.
      
      This issue seems to have been uncovered by behavioral changes in
      the dwc3 driver in commit fec9095b ("usb: dwc3: gadget:
      remove wait_end_transfer").
      
      Cc: Alan Stern <stern@rowland.harvard.edu>
      Cc: Felipe Balbi <balbi@kernel.org>
      Cc: Zeng Tao <prime.zeng@hisilicon.com>
      Cc: Jack Pham <jackp@codeaurora.org>
      Cc: Thinh Nguyen <thinh.nguyen@synopsys.com>
      Cc: Chen Yu <chenyu56@huawei.com>
      Cc: Jerry Zhang <zhangjerry@google.com>
      Cc: Lars-Peter Clausen <lars@metafoo.de>
      Cc: Vincent Pelletier <plr.vincent@gmail.com>
      Cc: Andrzej Pietrasiewicz <andrzej.p@samsung.com>
      Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
      Cc: Linux USB List <linux-usb@vger.kernel.org>
      Suggested-by: NAlan Stern <stern@rowland.harvard.edu>
      Signed-off-by: NJohn Stultz <john.stultz@linaro.org>
      Signed-off-by: NFelipe Balbi <felipe.balbi@linux.intel.com>
      54f64d5c
  24. 07 2月, 2019 1 次提交
  25. 26 11月, 2018 2 次提交
  26. 14 11月, 2018 1 次提交
  27. 26 7月, 2018 1 次提交
    • J
      usb: gadget: f_fs: Only return delayed status when len is 0 · e610257e
      Jerry Zhang 提交于
      Commit 1b9ba000 ("Allow function drivers to pause control
      transfers") states that USB_GADGET_DELAYED_STATUS is only
      supported if data phase is 0 bytes.
      
      It seems that when the length is not 0 bytes, there is no
      need to explicitly delay the data stage since the transfer
      is not completed until the user responds. However, when the
      length is 0, there is no data stage and the transfer is
      finished once setup() returns, hence there is a need to
      explicitly delay completion.
      
      This manifests as the following bugs:
      
      Prior to 946ef68a ('Let setup() return
      USB_GADGET_DELAYED_STATUS'), when setup is 0 bytes, ffs
      would require user to queue a 0 byte request in order to
      clear setup state. However, that 0 byte request was actually
      not needed and would hang and cause errors in other setup
      requests.
      
      After the above commit, 0 byte setups work since the gadget
      now accepts empty queues to ep0 to clear the delay, but all
      other setups hang.
      
      Fixes: 946ef68a ("Let setup() return USB_GADGET_DELAYED_STATUS")
      Signed-off-by: NJerry Zhang <zhangjerry@google.com>
      Signed-off-by: NFelipe Balbi <felipe.balbi@linux.intel.com>
      e610257e
  28. 20 7月, 2018 1 次提交
    • J
      usb: gadget: f_fs: Only return delayed status when len is 0 · 4d644abf
      Jerry Zhang 提交于
      Commit 1b9ba000 ("Allow function drivers to pause control
      transfers") states that USB_GADGET_DELAYED_STATUS is only
      supported if data phase is 0 bytes.
      
      It seems that when the length is not 0 bytes, there is no
      need to explicitly delay the data stage since the transfer
      is not completed until the user responds. However, when the
      length is 0, there is no data stage and the transfer is
      finished once setup() returns, hence there is a need to
      explicitly delay completion.
      
      This manifests as the following bugs:
      
      Prior to 946ef68a ('Let setup() return
      USB_GADGET_DELAYED_STATUS'), when setup is 0 bytes, ffs
      would require user to queue a 0 byte request in order to
      clear setup state. However, that 0 byte request was actually
      not needed and would hang and cause errors in other setup
      requests.
      
      After the above commit, 0 byte setups work since the gadget
      now accepts empty queues to ep0 to clear the delay, but all
      other setups hang.
      
      Fixes: 946ef68a ("Let setup() return USB_GADGET_DELAYED_STATUS")
      Signed-off-by: NJerry Zhang <zhangjerry@google.com>
      Cc: stable <stable@vger.kernel.org>
      Acked-by: NFelipe Balbi <felipe.balbi@linux.intel.com>
      Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
      4d644abf
  29. 18 6月, 2018 1 次提交
    • V
      usb: gadget: ffs: Fix BUG when userland exits with submitted AIO transfers · d52e4d0c
      Vincent Pelletier 提交于
      This bug happens only when the UDC needs to sleep during usb_ep_dequeue,
      as is the case for (at least) dwc3.
      
      [  382.200896] BUG: scheduling while atomic: screen/1808/0x00000100
      [  382.207124] 4 locks held by screen/1808:
      [  382.211266]  #0:  (rcu_callback){....}, at: [<c10b4ff0>] rcu_process_callbacks+0x260/0x440
      [  382.219949]  #1:  (rcu_read_lock_sched){....}, at: [<c1358ba0>] percpu_ref_switch_to_atomic_rcu+0xb0/0x130
      [  382.230034]  #2:  (&(&ctx->ctx_lock)->rlock){....}, at: [<c11f0c73>] free_ioctx_users+0x23/0xd0
      [  382.230096]  #3:  (&(&ffs->eps_lock)->rlock){....}, at: [<f81e7710>] ffs_aio_cancel+0x20/0x60 [usb_f_fs]
      [  382.230160] Modules linked in: usb_f_fs libcomposite configfs bnep btsdio bluetooth ecdh_generic brcmfmac brcmutil intel_powerclamp coretemp dwc3 kvm_intel ulpi udc_core kvm irqbypass crc32_pclmul crc32c_intel pcbc dwc3_pci aesni_intel aes_i586 crypto_simd cryptd ehci_pci ehci_hcd gpio_keys usbcore basincove_gpadc industrialio usb_common
      [  382.230407] CPU: 1 PID: 1808 Comm: screen Not tainted 4.14.0-edison+ #117
      [  382.230416] Hardware name: Intel Corporation Merrifield/BODEGA BAY, BIOS 542 2015.01.21:18.19.48
      [  382.230425] Call Trace:
      [  382.230438]  <SOFTIRQ>
      [  382.230466]  dump_stack+0x47/0x62
      [  382.230498]  __schedule_bug+0x61/0x80
      [  382.230522]  __schedule+0x43/0x7a0
      [  382.230587]  schedule+0x5f/0x70
      [  382.230625]  dwc3_gadget_ep_dequeue+0x14c/0x270 [dwc3]
      [  382.230669]  ? do_wait_intr_irq+0x70/0x70
      [  382.230724]  usb_ep_dequeue+0x19/0x90 [udc_core]
      [  382.230770]  ffs_aio_cancel+0x37/0x60 [usb_f_fs]
      [  382.230798]  kiocb_cancel+0x31/0x40
      [  382.230822]  free_ioctx_users+0x4d/0xd0
      [  382.230858]  percpu_ref_switch_to_atomic_rcu+0x10a/0x130
      [  382.230881]  ? percpu_ref_exit+0x40/0x40
      [  382.230904]  rcu_process_callbacks+0x2b3/0x440
      [  382.230965]  __do_softirq+0xf8/0x26b
      [  382.231011]  ? __softirqentry_text_start+0x8/0x8
      [  382.231033]  do_softirq_own_stack+0x22/0x30
      [  382.231042]  </SOFTIRQ>
      [  382.231071]  irq_exit+0x45/0xc0
      [  382.231089]  smp_apic_timer_interrupt+0x13c/0x150
      [  382.231118]  apic_timer_interrupt+0x35/0x3c
      [  382.231132] EIP: __copy_user_ll+0xe2/0xf0
      [  382.231142] EFLAGS: 00210293 CPU: 1
      [  382.231154] EAX: bfd4508c EBX: 00000004 ECX: 00000003 EDX: f3d8fe50
      [  382.231165] ESI: f3d8fe51 EDI: bfd4508d EBP: f3d8fe14 ESP: f3d8fe08
      [  382.231176]  DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068
      [  382.231265]  core_sys_select+0x25f/0x320
      [  382.231346]  ? __wake_up_common_lock+0x62/0x80
      [  382.231399]  ? tty_ldisc_deref+0x13/0x20
      [  382.231438]  ? ldsem_up_read+0x1b/0x40
      [  382.231459]  ? tty_ldisc_deref+0x13/0x20
      [  382.231479]  ? tty_write+0x29f/0x2e0
      [  382.231514]  ? n_tty_ioctl+0xe0/0xe0
      [  382.231541]  ? tty_write_unlock+0x30/0x30
      [  382.231566]  ? __vfs_write+0x22/0x110
      [  382.231604]  ? security_file_permission+0x2f/0xd0
      [  382.231635]  ? rw_verify_area+0xac/0x120
      [  382.231677]  ? vfs_write+0x103/0x180
      [  382.231711]  SyS_select+0x87/0xc0
      [  382.231739]  ? SyS_write+0x42/0x90
      [  382.231781]  do_fast_syscall_32+0xd6/0x1a0
      [  382.231836]  entry_SYSENTER_32+0x47/0x71
      [  382.231848] EIP: 0xb7f75b05
      [  382.231857] EFLAGS: 00000246 CPU: 1
      [  382.231868] EAX: ffffffda EBX: 00000400 ECX: bfd4508c EDX: bfd4510c
      [  382.231878] ESI: 00000000 EDI: 00000000 EBP: 00000000 ESP: bfd45020
      [  382.231889]  DS: 007b ES: 007b FS: 0000 GS: 0033 SS: 007b
      [  382.232281] softirq: huh, entered softirq 9 RCU c10b4d90 with preempt_count 00000100, exited with 00000000?
      Tested-by: NSam Protsenko <semen.protsenko@linaro.org>
      Signed-off-by: NVincent Pelletier <plr.vincent@gmail.com>
      Signed-off-by: NFelipe Balbi <felipe.balbi@linux.intel.com>
      d52e4d0c
  30. 06 6月, 2018 1 次提交
    • D
      vfs: change inode times to use struct timespec64 · 95582b00
      Deepa Dinamani 提交于
      struct timespec is not y2038 safe. Transition vfs to use
      y2038 safe struct timespec64 instead.
      
      The change was made with the help of the following cocinelle
      script. This catches about 80% of the changes.
      All the header file and logic changes are included in the
      first 5 rules. The rest are trivial substitutions.
      I avoid changing any of the function signatures or any other
      filesystem specific data structures to keep the patch simple
      for review.
      
      The script can be a little shorter by combining different cases.
      But, this version was sufficient for my usecase.
      
      virtual patch
      
      @ depends on patch @
      identifier now;
      @@
      - struct timespec
      + struct timespec64
        current_time ( ... )
        {
      - struct timespec now = current_kernel_time();
      + struct timespec64 now = current_kernel_time64();
        ...
      - return timespec_trunc(
      + return timespec64_trunc(
        ... );
        }
      
      @ depends on patch @
      identifier xtime;
      @@
       struct \( iattr \| inode \| kstat \) {
       ...
      -       struct timespec xtime;
      +       struct timespec64 xtime;
       ...
       }
      
      @ depends on patch @
      identifier t;
      @@
       struct inode_operations {
       ...
      int (*update_time) (...,
      -       struct timespec t,
      +       struct timespec64 t,
      ...);
       ...
       }
      
      @ depends on patch @
      identifier t;
      identifier fn_update_time =~ "update_time$";
      @@
       fn_update_time (...,
      - struct timespec *t,
      + struct timespec64 *t,
       ...) { ... }
      
      @ depends on patch @
      identifier t;
      @@
      lease_get_mtime( ... ,
      - struct timespec *t
      + struct timespec64 *t
        ) { ... }
      
      @te depends on patch forall@
      identifier ts;
      local idexpression struct inode *inode_node;
      identifier i_xtime =~ "^i_[acm]time$";
      identifier ia_xtime =~ "^ia_[acm]time$";
      identifier fn_update_time =~ "update_time$";
      identifier fn;
      expression e, E3;
      local idexpression struct inode *node1;
      local idexpression struct inode *node2;
      local idexpression struct iattr *attr1;
      local idexpression struct iattr *attr2;
      local idexpression struct iattr attr;
      identifier i_xtime1 =~ "^i_[acm]time$";
      identifier i_xtime2 =~ "^i_[acm]time$";
      identifier ia_xtime1 =~ "^ia_[acm]time$";
      identifier ia_xtime2 =~ "^ia_[acm]time$";
      @@
      (
      (
      - struct timespec ts;
      + struct timespec64 ts;
      |
      - struct timespec ts = current_time(inode_node);
      + struct timespec64 ts = current_time(inode_node);
      )
      
      <+... when != ts
      (
      - timespec_equal(&inode_node->i_xtime, &ts)
      + timespec64_equal(&inode_node->i_xtime, &ts)
      |
      - timespec_equal(&ts, &inode_node->i_xtime)
      + timespec64_equal(&ts, &inode_node->i_xtime)
      |
      - timespec_compare(&inode_node->i_xtime, &ts)
      + timespec64_compare(&inode_node->i_xtime, &ts)
      |
      - timespec_compare(&ts, &inode_node->i_xtime)
      + timespec64_compare(&ts, &inode_node->i_xtime)
      |
      ts = current_time(e)
      |
      fn_update_time(..., &ts,...)
      |
      inode_node->i_xtime = ts
      |
      node1->i_xtime = ts
      |
      ts = inode_node->i_xtime
      |
      <+... attr1->ia_xtime ...+> = ts
      |
      ts = attr1->ia_xtime
      |
      ts.tv_sec
      |
      ts.tv_nsec
      |
      btrfs_set_stack_timespec_sec(..., ts.tv_sec)
      |
      btrfs_set_stack_timespec_nsec(..., ts.tv_nsec)
      |
      - ts = timespec64_to_timespec(
      + ts =
      ...
      -)
      |
      - ts = ktime_to_timespec(
      + ts = ktime_to_timespec64(
      ...)
      |
      - ts = E3
      + ts = timespec_to_timespec64(E3)
      |
      - ktime_get_real_ts(&ts)
      + ktime_get_real_ts64(&ts)
      |
      fn(...,
      - ts
      + timespec64_to_timespec(ts)
      ,...)
      )
      ...+>
      (
      <... when != ts
      - return ts;
      + return timespec64_to_timespec(ts);
      ...>
      )
      |
      - timespec_equal(&node1->i_xtime1, &node2->i_xtime2)
      + timespec64_equal(&node1->i_xtime2, &node2->i_xtime2)
      |
      - timespec_equal(&node1->i_xtime1, &attr2->ia_xtime2)
      + timespec64_equal(&node1->i_xtime2, &attr2->ia_xtime2)
      |
      - timespec_compare(&node1->i_xtime1, &node2->i_xtime2)
      + timespec64_compare(&node1->i_xtime1, &node2->i_xtime2)
      |
      node1->i_xtime1 =
      - timespec_trunc(attr1->ia_xtime1,
      + timespec64_trunc(attr1->ia_xtime1,
      ...)
      |
      - attr1->ia_xtime1 = timespec_trunc(attr2->ia_xtime2,
      + attr1->ia_xtime1 =  timespec64_trunc(attr2->ia_xtime2,
      ...)
      |
      - ktime_get_real_ts(&attr1->ia_xtime1)
      + ktime_get_real_ts64(&attr1->ia_xtime1)
      |
      - ktime_get_real_ts(&attr.ia_xtime1)
      + ktime_get_real_ts64(&attr.ia_xtime1)
      )
      
      @ depends on patch @
      struct inode *node;
      struct iattr *attr;
      identifier fn;
      identifier i_xtime =~ "^i_[acm]time$";
      identifier ia_xtime =~ "^ia_[acm]time$";
      expression e;
      @@
      (
      - fn(node->i_xtime);
      + fn(timespec64_to_timespec(node->i_xtime));
      |
       fn(...,
      - node->i_xtime);
      + timespec64_to_timespec(node->i_xtime));
      |
      - e = fn(attr->ia_xtime);
      + e = fn(timespec64_to_timespec(attr->ia_xtime));
      )
      
      @ depends on patch forall @
      struct inode *node;
      struct iattr *attr;
      identifier i_xtime =~ "^i_[acm]time$";
      identifier ia_xtime =~ "^ia_[acm]time$";
      identifier fn;
      @@
      {
      + struct timespec ts;
      <+...
      (
      + ts = timespec64_to_timespec(node->i_xtime);
      fn (...,
      - &node->i_xtime,
      + &ts,
      ...);
      |
      + ts = timespec64_to_timespec(attr->ia_xtime);
      fn (...,
      - &attr->ia_xtime,
      + &ts,
      ...);
      )
      ...+>
      }
      
      @ depends on patch forall @
      struct inode *node;
      struct iattr *attr;
      struct kstat *stat;
      identifier ia_xtime =~ "^ia_[acm]time$";
      identifier i_xtime =~ "^i_[acm]time$";
      identifier xtime =~ "^[acm]time$";
      identifier fn, ret;
      @@
      {
      + struct timespec ts;
      <+...
      (
      + ts = timespec64_to_timespec(node->i_xtime);
      ret = fn (...,
      - &node->i_xtime,
      + &ts,
      ...);
      |
      + ts = timespec64_to_timespec(node->i_xtime);
      ret = fn (...,
      - &node->i_xtime);
      + &ts);
      |
      + ts = timespec64_to_timespec(attr->ia_xtime);
      ret = fn (...,
      - &attr->ia_xtime,
      + &ts,
      ...);
      |
      + ts = timespec64_to_timespec(attr->ia_xtime);
      ret = fn (...,
      - &attr->ia_xtime);
      + &ts);
      |
      + ts = timespec64_to_timespec(stat->xtime);
      ret = fn (...,
      - &stat->xtime);
      + &ts);
      )
      ...+>
      }
      
      @ depends on patch @
      struct inode *node;
      struct inode *node2;
      identifier i_xtime1 =~ "^i_[acm]time$";
      identifier i_xtime2 =~ "^i_[acm]time$";
      identifier i_xtime3 =~ "^i_[acm]time$";
      struct iattr *attrp;
      struct iattr *attrp2;
      struct iattr attr ;
      identifier ia_xtime1 =~ "^ia_[acm]time$";
      identifier ia_xtime2 =~ "^ia_[acm]time$";
      struct kstat *stat;
      struct kstat stat1;
      struct timespec64 ts;
      identifier xtime =~ "^[acmb]time$";
      expression e;
      @@
      (
      ( node->i_xtime2 \| attrp->ia_xtime2 \| attr.ia_xtime2 \) = node->i_xtime1  ;
      |
       node->i_xtime2 = \( node2->i_xtime1 \| timespec64_trunc(...) \);
      |
       node->i_xtime2 = node->i_xtime1 = node->i_xtime3 = \(ts \| current_time(...) \);
      |
       node->i_xtime1 = node->i_xtime3 = \(ts \| current_time(...) \);
      |
       stat->xtime = node2->i_xtime1;
      |
       stat1.xtime = node2->i_xtime1;
      |
      ( node->i_xtime2 \| attrp->ia_xtime2 \) = attrp->ia_xtime1  ;
      |
      ( attrp->ia_xtime1 \| attr.ia_xtime1 \) = attrp2->ia_xtime2;
      |
      - e = node->i_xtime1;
      + e = timespec64_to_timespec( node->i_xtime1 );
      |
      - e = attrp->ia_xtime1;
      + e = timespec64_to_timespec( attrp->ia_xtime1 );
      |
      node->i_xtime1 = current_time(...);
      |
       node->i_xtime2 = node->i_xtime1 = node->i_xtime3 =
      - e;
      + timespec_to_timespec64(e);
      |
       node->i_xtime1 = node->i_xtime3 =
      - e;
      + timespec_to_timespec64(e);
      |
      - node->i_xtime1 = e;
      + node->i_xtime1 = timespec_to_timespec64(e);
      )
      Signed-off-by: NDeepa Dinamani <deepa.kernel@gmail.com>
      Cc: <anton@tuxera.com>
      Cc: <balbi@kernel.org>
      Cc: <bfields@fieldses.org>
      Cc: <darrick.wong@oracle.com>
      Cc: <dhowells@redhat.com>
      Cc: <dsterba@suse.com>
      Cc: <dwmw2@infradead.org>
      Cc: <hch@lst.de>
      Cc: <hirofumi@mail.parknet.co.jp>
      Cc: <hubcap@omnibond.com>
      Cc: <jack@suse.com>
      Cc: <jaegeuk@kernel.org>
      Cc: <jaharkes@cs.cmu.edu>
      Cc: <jslaby@suse.com>
      Cc: <keescook@chromium.org>
      Cc: <mark@fasheh.com>
      Cc: <miklos@szeredi.hu>
      Cc: <nico@linaro.org>
      Cc: <reiserfs-devel@vger.kernel.org>
      Cc: <richard@nod.at>
      Cc: <sage@redhat.com>
      Cc: <sfrench@samba.org>
      Cc: <swhiteho@redhat.com>
      Cc: <tj@kernel.org>
      Cc: <trond.myklebust@primarydata.com>
      Cc: <tytso@mit.edu>
      Cc: <viro@zeniv.linux.org.uk>
      95582b00
  31. 15 5月, 2018 1 次提交
  32. 13 3月, 2018 2 次提交
    • L
      usb: gadget: ffs: Let setup() return USB_GADGET_DELAYED_STATUS · 946ef68a
      Lars-Peter Clausen 提交于
      Some UDC drivers (like the DWC3) expect that the response to a setup()
      request is queued from within the setup function itself so that it is
      available as soon as setup() has completed.
      
      Upon receiving a setup request the function fs driver creates an event that
      is made available to userspace. And only once userspace has acknowledged
      that event the response to the setup request is queued.
      
      So it violates the requirement of those UDC drivers and random failures can
      be observed. This is basically a race condition and if userspace is able to
      read the event and queue the response fast enough all is good. But if it is
      not, for example because other processes are currently scheduled to run,
      the USB host that sent the setup request will observe an error.
      
      To avoid this the gadget framework provides the USB_GADGET_DELAYED_STATUS
      return code. If a setup() callback returns this value the UDC driver is
      aware that response is not yet available and can uses the appropriate
      methods to handle this case.
      
      Since in the case of function fs the response will never be available when
      the setup() function returns make sure that this status code is used.
      
      This fixed random occasional failures that were previously observed on a
      DWC3 based system under high system load.
      Signed-off-by: NLars-Peter Clausen <lars@metafoo.de>
      Signed-off-by: NFelipe Balbi <felipe.balbi@linux.intel.com>
      946ef68a
    • L
      usb: gadget: ffs: Execute copy_to_user() with USER_DS set · 4058ebf3
      Lars-Peter Clausen 提交于
      When using a AIO read() operation on the function FS gadget driver a URB is
      submitted asynchronously and on URB completion the received data is copied
      to the userspace buffer associated with the read operation.
      
      This is done from a kernel worker thread invoking copy_to_user() (through
      copy_to_iter()). And while the user space process memory is made available
      to the kernel thread using use_mm(), some architecture require in addition
      to this that the operation runs with USER_DS set. Otherwise the userspace
      memory access will fail.
      
      For example on ARM64 with Privileged Access Never (PAN) and User Access
      Override (UAO) enabled the following crash occurs.
      
      	Internal error: Accessing user space memory with fs=KERNEL_DS: 9600004f [#1] SMP
      	Modules linked in:
      	CPU: 2 PID: 1636 Comm: kworker/2:1 Not tainted 4.9.0-04081-g8ab2dfb-dirty #487
      	Hardware name: ZynqMP ZCU102 Rev1.0 (DT)
      	Workqueue: events ffs_user_copy_worker
      	task: ffffffc87afc8080 task.stack: ffffffc87a00c000
      	PC is at __arch_copy_to_user+0x190/0x220
      	LR is at copy_to_iter+0x78/0x3c8
      	[...]
      	[<ffffff800847b790>] __arch_copy_to_user+0x190/0x220
      	[<ffffff80086f25d8>] ffs_user_copy_worker+0x70/0x130
      	[<ffffff80080b8c64>] process_one_work+0x1dc/0x460
      	[<ffffff80080b8f38>] worker_thread+0x50/0x4b0
      	[<ffffff80080bf5a0>] kthread+0xd8/0xf0
      	[<ffffff8008083680>] ret_from_fork+0x10/0x50
      
      Address this by placing a set_fs(USER_DS) before of the copy operation
      and revert it again once the copy operation has finished.
      
      This patch is analogous to commit d7ffde35 ("vhost: use USER_DS in
      vhost_worker thread") which addresses the same underlying issue.
      Signed-off-by: NLars-Peter Clausen <lars@metafoo.de>
      Signed-off-by: NFelipe Balbi <felipe.balbi@linux.intel.com>
      4058ebf3