Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'dpll-fixes'

Arkadiusz Kubalewski says:

====================
dpll: fix unordered unbind/bind registerer issues

Fix issues when performing unordered unbind/bind of a kernel modules
which are using a dpll device with DPLL_PIN_TYPE_MUX pins.
Currently only serialized bind/unbind of such use case works, fix
the issues and allow for unserialized kernel module bind order.

The issues are observed on the ice driver, i.e.,

$ echo 0000:af:00.0 > /sys/bus/pci/drivers/ice/unbind
$ echo 0000:af:00.1 > /sys/bus/pci/drivers/ice/unbind

results in:

ice 0000:af:00.0: Removed PTP clock
BUG: kernel NULL pointer dereference, address: 0000000000000010
PF: supervisor read access in kernel mode
PF: error_code(0x0000) - not-present page
PGD 0 P4D 0
Oops: 0000 [#1] PREEMPT SMP PTI
CPU: 7 PID: 71848 Comm: bash Kdump: loaded Not tainted 6.6.0-rc5_next-queue_19th-Oct-2023-01625-g039e5d15e451 #1
Hardware name: Intel Corporation S2600STB/S2600STB, BIOS SE5C620.86B.02.01.0008.031920191559 03/19/2019
RIP: 0010:ice_dpll_rclk_state_on_pin_get+0x2f/0x90 [ice]
Code: 41 57 4d 89 cf 41 56 41 55 4d 89 c5 41 54 55 48 89 f5 53 4c 8b 66 08 48 89 cb 4d 8d b4 24 f0 49 00 00 4c 89 f7 e8 71 ec 1f c5 <0f> b6 5b 10 41 0f b6 84 24 30 4b 00 00 29 c3 41 0f b6 84 24 28 4b
RSP: 0018:ffffc902b179fb60 EFLAGS: 00010246
RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000
RDX: ffff8882c1398000 RSI: ffff888c7435cc60 RDI: ffff888c7435cb90
RBP: ffff888c7435cc60 R08: ffffc902b179fbb0 R09: 0000000000000000
R10: ffff888ef1fc8050 R11: fffffffffff82700 R12: ffff888c743581a0
R13: ffffc902b179fbb0 R14: ffff888c7435cb90 R15: 0000000000000000
FS: 00007fdc7dae0740(0000) GS:ffff888c105c0000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000000000010 CR3: 0000000132c24002 CR4: 00000000007706e0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
PKRU: 55555554
Call Trace:
<TASK>
? __die+0x20/0x70
? page_fault_oops+0x76/0x170
? exc_page_fault+0x65/0x150
? asm_exc_page_fault+0x22/0x30
? ice_dpll_rclk_state_on_pin_get+0x2f/0x90 [ice]
? __pfx_ice_dpll_rclk_state_on_pin_get+0x10/0x10 [ice]
dpll_msg_add_pin_parents+0x142/0x1d0
dpll_pin_event_send+0x7d/0x150
dpll_pin_on_pin_unregister+0x3f/0x100
ice_dpll_deinit_pins+0xa1/0x230 [ice]
ice_dpll_deinit+0x29/0xe0 [ice]
ice_remove+0xcd/0x200 [ice]
pci_device_remove+0x33/0xa0
device_release_driver_internal+0x193/0x200
unbind_store+0x9d/0xb0
kernfs_fop_write_iter+0x128/0x1c0
vfs_write+0x2bb/0x3e0
ksys_write+0x5f/0xe0
do_syscall_64+0x59/0x90
? filp_close+0x1b/0x30
? do_dup2+0x7d/0xd0
? syscall_exit_work+0x103/0x130
? syscall_exit_to_user_mode+0x22/0x40
? do_syscall_64+0x69/0x90
? syscall_exit_work+0x103/0x130
? syscall_exit_to_user_mode+0x22/0x40
? do_syscall_64+0x69/0x90
entry_SYSCALL_64_after_hwframe+0x6e/0xd8
RIP: 0033:0x7fdc7d93eb97
Code: 0b 00 f7 d8 64 89 02 48 c7 c0 ff ff ff ff eb b7 0f 1f 00 f3 0f 1e fa 64 8b 04 25 18 00 00 00 85 c0 75 10 b8 01 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 51 c3 48 83 ec 28 48 89 54 24 18 48 89 74 24
RSP: 002b:00007fff2aa91028 EFLAGS: 00000246 ORIG_RAX: 0000000000000001
RAX: ffffffffffffffda RBX: 000000000000000d RCX: 00007fdc7d93eb97
RDX: 000000000000000d RSI: 00005644814ec9b0 RDI: 0000000000000001
RBP: 00005644814ec9b0 R08: 0000000000000000 R09: 00007fdc7d9b14e0
R10: 00007fdc7d9b13e0 R11: 0000000000000246 R12: 000000000000000d
R13: 00007fdc7d9fb780 R14: 000000000000000d R15: 00007fdc7d9f69e0
</TASK>
Modules linked in: uinput vfio_pci vfio_pci_core vfio_iommu_type1 vfio irqbypass ixgbevf snd_seq_dummy snd_hrtimer snd_seq snd_timer snd_seq_device snd soundcore overlay qrtr rfkill vfat fat xfs libcrc32c rpcrdma sunrpc rdma_ucm ib_srpt ib_isert iscsi_target_mod target_core_mod ib_iser libiscsi scsi_transport_iscsi rdma_cm iw_cm ib_cm intel_rapl_msr intel_rapl_common intel_uncore_frequency intel_uncore_frequency_common isst_if_common skx_edac nfit libnvdimm ipmi_ssif x86_pkg_temp_thermal intel_powerclamp coretemp irdma rapl intel_cstate ib_uverbs iTCO_wdt iTCO_vendor_support acpi_ipmi intel_uncore mei_me ipmi_si pcspkr i2c_i801 ib_core mei ipmi_devintf intel_pch_thermal ioatdma i2c_smbus ipmi_msghandler lpc_ich joydev acpi_power_meter acpi_pad ext4 mbcache jbd2 sd_mod t10_pi sg ast i2c_algo_bit drm_shmem_helper drm_kms_helper ice crct10dif_pclmul ixgbe crc32_pclmul drm crc32c_intel ahci i40e libahci ghash_clmulni_intel libata mdio dca gnss wmi fuse [last unloaded: iavf]
CR2: 0000000000000010

v6:
- fix memory corruption on error path in patch [v5 2/4]
====================

Acked-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
Signed-off-by: David S. Miller <davem@davemloft.net>

+100 -29
+57 -11
drivers/dpll/dpll_core.c
··· 29 29 WARN_ON_ONCE(!xa_get_mark(&dpll_device_xa, (d)->id, DPLL_REGISTERED)) 30 30 #define ASSERT_DPLL_NOT_REGISTERED(d) \ 31 31 WARN_ON_ONCE(xa_get_mark(&dpll_device_xa, (d)->id, DPLL_REGISTERED)) 32 - #define ASSERT_PIN_REGISTERED(p) \ 33 - WARN_ON_ONCE(!xa_get_mark(&dpll_pin_xa, (p)->id, DPLL_REGISTERED)) 34 32 35 33 struct dpll_device_registration { 36 34 struct list_head list; ··· 423 425 } 424 426 EXPORT_SYMBOL_GPL(dpll_device_unregister); 425 427 428 + static void dpll_pin_prop_free(struct dpll_pin_properties *prop) 429 + { 430 + kfree(prop->package_label); 431 + kfree(prop->panel_label); 432 + kfree(prop->board_label); 433 + kfree(prop->freq_supported); 434 + } 435 + 436 + static int dpll_pin_prop_dup(const struct dpll_pin_properties *src, 437 + struct dpll_pin_properties *dst) 438 + { 439 + memcpy(dst, src, sizeof(*dst)); 440 + if (src->freq_supported && src->freq_supported_num) { 441 + size_t freq_size = src->freq_supported_num * 442 + sizeof(*src->freq_supported); 443 + dst->freq_supported = kmemdup(src->freq_supported, 444 + freq_size, GFP_KERNEL); 445 + if (!src->freq_supported) 446 + return -ENOMEM; 447 + } 448 + if (src->board_label) { 449 + dst->board_label = kstrdup(src->board_label, GFP_KERNEL); 450 + if (!dst->board_label) 451 + goto err_board_label; 452 + } 453 + if (src->panel_label) { 454 + dst->panel_label = kstrdup(src->panel_label, GFP_KERNEL); 455 + if (!dst->panel_label) 456 + goto err_panel_label; 457 + } 458 + if (src->package_label) { 459 + dst->package_label = kstrdup(src->package_label, GFP_KERNEL); 460 + if (!dst->package_label) 461 + goto err_package_label; 462 + } 463 + 464 + return 0; 465 + 466 + err_package_label: 467 + kfree(dst->panel_label); 468 + err_panel_label: 469 + kfree(dst->board_label); 470 + err_board_label: 471 + kfree(dst->freq_supported); 472 + return -ENOMEM; 473 + } 474 + 426 475 static struct dpll_pin * 427 476 dpll_pin_alloc(u64 clock_id, u32 pin_idx, struct module *module, 428 477 const struct dpll_pin_properties *prop) ··· 486 441 if (WARN_ON(prop->type < DPLL_PIN_TYPE_MUX || 487 442 prop->type > DPLL_PIN_TYPE_MAX)) { 488 443 ret = -EINVAL; 489 - goto err; 444 + goto err_pin_prop; 490 445 } 491 - pin->prop = prop; 446 + ret = dpll_pin_prop_dup(prop, &pin->prop); 447 + if (ret) 448 + goto err_pin_prop; 492 449 refcount_set(&pin->refcount, 1); 493 450 xa_init_flags(&pin->dpll_refs, XA_FLAGS_ALLOC); 494 451 xa_init_flags(&pin->parent_refs, XA_FLAGS_ALLOC); 495 452 ret = xa_alloc_cyclic(&dpll_pin_xa, &pin->id, pin, xa_limit_32b, 496 453 &dpll_pin_xa_id, GFP_KERNEL); 497 454 if (ret) 498 - goto err; 455 + goto err_xa_alloc; 499 456 return pin; 500 - err: 457 + err_xa_alloc: 501 458 xa_destroy(&pin->dpll_refs); 502 459 xa_destroy(&pin->parent_refs); 460 + dpll_pin_prop_free(&pin->prop); 461 + err_pin_prop: 503 462 kfree(pin); 504 463 return ERR_PTR(ret); 505 464 } ··· 563 514 xa_destroy(&pin->dpll_refs); 564 515 xa_destroy(&pin->parent_refs); 565 516 xa_erase(&dpll_pin_xa, pin->id); 517 + dpll_pin_prop_free(&pin->prop); 566 518 kfree(pin); 567 519 } 568 520 mutex_unlock(&dpll_lock); ··· 613 563 if (WARN_ON(!ops) || 614 564 WARN_ON(!ops->state_on_dpll_get) || 615 565 WARN_ON(!ops->direction_get)) 616 - return -EINVAL; 617 - if (ASSERT_DPLL_REGISTERED(dpll)) 618 566 return -EINVAL; 619 567 620 568 mutex_lock(&dpll_lock); ··· 684 636 unsigned long i, stop; 685 637 int ret; 686 638 687 - if (WARN_ON(parent->prop->type != DPLL_PIN_TYPE_MUX)) 639 + if (WARN_ON(parent->prop.type != DPLL_PIN_TYPE_MUX)) 688 640 return -EINVAL; 689 641 690 642 if (WARN_ON(!ops) || 691 643 WARN_ON(!ops->state_on_pin_get) || 692 644 WARN_ON(!ops->direction_get)) 693 - return -EINVAL; 694 - if (ASSERT_PIN_REGISTERED(parent)) 695 645 return -EINVAL; 696 646 697 647 mutex_lock(&dpll_lock);
+2 -2
drivers/dpll/dpll_core.h
··· 44 44 * @module: module of creator 45 45 * @dpll_refs: hold referencees to dplls pin was registered with 46 46 * @parent_refs: hold references to parent pins pin was registered with 47 - * @prop: pointer to pin properties given by registerer 47 + * @prop: pin properties copied from the registerer 48 48 * @rclk_dev_name: holds name of device when pin can recover clock from it 49 49 * @refcount: refcount 50 50 **/ ··· 55 55 struct module *module; 56 56 struct xarray dpll_refs; 57 57 struct xarray parent_refs; 58 - const struct dpll_pin_properties *prop; 58 + struct dpll_pin_properties prop; 59 59 refcount_t refcount; 60 60 }; 61 61
+41 -16
drivers/dpll/dpll_netlink.c
··· 303 303 if (nla_put_64bit(msg, DPLL_A_PIN_FREQUENCY, sizeof(freq), &freq, 304 304 DPLL_A_PIN_PAD)) 305 305 return -EMSGSIZE; 306 - for (fs = 0; fs < pin->prop->freq_supported_num; fs++) { 306 + for (fs = 0; fs < pin->prop.freq_supported_num; fs++) { 307 307 nest = nla_nest_start(msg, DPLL_A_PIN_FREQUENCY_SUPPORTED); 308 308 if (!nest) 309 309 return -EMSGSIZE; 310 - freq = pin->prop->freq_supported[fs].min; 310 + freq = pin->prop.freq_supported[fs].min; 311 311 if (nla_put_64bit(msg, DPLL_A_PIN_FREQUENCY_MIN, sizeof(freq), 312 312 &freq, DPLL_A_PIN_PAD)) { 313 313 nla_nest_cancel(msg, nest); 314 314 return -EMSGSIZE; 315 315 } 316 - freq = pin->prop->freq_supported[fs].max; 316 + freq = pin->prop.freq_supported[fs].max; 317 317 if (nla_put_64bit(msg, DPLL_A_PIN_FREQUENCY_MAX, sizeof(freq), 318 318 &freq, DPLL_A_PIN_PAD)) { 319 319 nla_nest_cancel(msg, nest); ··· 329 329 { 330 330 int fs; 331 331 332 - for (fs = 0; fs < pin->prop->freq_supported_num; fs++) 333 - if (freq >= pin->prop->freq_supported[fs].min && 334 - freq <= pin->prop->freq_supported[fs].max) 332 + for (fs = 0; fs < pin->prop.freq_supported_num; fs++) 333 + if (freq >= pin->prop.freq_supported[fs].min && 334 + freq <= pin->prop.freq_supported[fs].max) 335 335 return true; 336 336 return false; 337 337 } ··· 421 421 dpll_cmd_pin_get_one(struct sk_buff *msg, struct dpll_pin *pin, 422 422 struct netlink_ext_ack *extack) 423 423 { 424 - const struct dpll_pin_properties *prop = pin->prop; 424 + const struct dpll_pin_properties *prop = &pin->prop; 425 425 struct dpll_pin_ref *ref; 426 426 int ret; 427 427 ··· 553 553 return dpll_device_event_send(DPLL_CMD_DEVICE_CHANGE_NTF, dpll); 554 554 } 555 555 556 + static bool dpll_pin_available(struct dpll_pin *pin) 557 + { 558 + struct dpll_pin_ref *par_ref; 559 + unsigned long i; 560 + 561 + if (!xa_get_mark(&dpll_pin_xa, pin->id, DPLL_REGISTERED)) 562 + return false; 563 + xa_for_each(&pin->parent_refs, i, par_ref) 564 + if (xa_get_mark(&dpll_pin_xa, par_ref->pin->id, 565 + DPLL_REGISTERED)) 566 + return true; 567 + xa_for_each(&pin->dpll_refs, i, par_ref) 568 + if (xa_get_mark(&dpll_device_xa, par_ref->dpll->id, 569 + DPLL_REGISTERED)) 570 + return true; 571 + return false; 572 + } 573 + 556 574 /** 557 575 * dpll_device_change_ntf - notify that the dpll device has been changed 558 576 * @dpll: registered dpll pointer ··· 597 579 int ret = -ENOMEM; 598 580 void *hdr; 599 581 600 - if (WARN_ON(!xa_get_mark(&dpll_pin_xa, pin->id, DPLL_REGISTERED))) 582 + if (!dpll_pin_available(pin)) 601 583 return -ENODEV; 602 584 603 585 msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); ··· 735 717 int ret; 736 718 737 719 if (!(DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE & 738 - pin->prop->capabilities)) { 720 + pin->prop.capabilities)) { 739 721 NL_SET_ERR_MSG(extack, "state changing is not allowed"); 740 722 return -EOPNOTSUPP; 741 723 } ··· 771 753 int ret; 772 754 773 755 if (!(DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE & 774 - pin->prop->capabilities)) { 756 + pin->prop.capabilities)) { 775 757 NL_SET_ERR_MSG(extack, "state changing is not allowed"); 776 758 return -EOPNOTSUPP; 777 759 } ··· 798 780 int ret; 799 781 800 782 if (!(DPLL_PIN_CAPABILITIES_PRIORITY_CAN_CHANGE & 801 - pin->prop->capabilities)) { 783 + pin->prop.capabilities)) { 802 784 NL_SET_ERR_MSG(extack, "prio changing is not allowed"); 803 785 return -EOPNOTSUPP; 804 786 } ··· 826 808 int ret; 827 809 828 810 if (!(DPLL_PIN_CAPABILITIES_DIRECTION_CAN_CHANGE & 829 - pin->prop->capabilities)) { 811 + pin->prop.capabilities)) { 830 812 NL_SET_ERR_MSG(extack, "direction changing is not allowed"); 831 813 return -EOPNOTSUPP; 832 814 } ··· 856 838 int ret; 857 839 858 840 phase_adj = nla_get_s32(phase_adj_attr); 859 - if (phase_adj > pin->prop->phase_range.max || 860 - phase_adj < pin->prop->phase_range.min) { 841 + if (phase_adj > pin->prop.phase_range.max || 842 + phase_adj < pin->prop.phase_range.min) { 861 843 NL_SET_ERR_MSG_ATTR(extack, phase_adj_attr, 862 844 "phase adjust value not supported"); 863 845 return -EINVAL; ··· 1041 1023 unsigned long i; 1042 1024 1043 1025 xa_for_each_marked(&dpll_pin_xa, i, pin, DPLL_REGISTERED) { 1044 - prop = pin->prop; 1026 + prop = &pin->prop; 1045 1027 cid_match = clock_id ? pin->clock_id == clock_id : true; 1046 1028 mod_match = mod_name_attr && module_name(pin->module) ? 1047 1029 !nla_strcmp(mod_name_attr, ··· 1148 1130 } 1149 1131 pin = dpll_pin_find_from_nlattr(info); 1150 1132 if (!IS_ERR(pin)) { 1133 + if (!dpll_pin_available(pin)) { 1134 + nlmsg_free(msg); 1135 + return -ENODEV; 1136 + } 1151 1137 ret = dpll_msg_add_pin_handle(msg, pin); 1152 1138 if (ret) { 1153 1139 nlmsg_free(msg); ··· 1201 1179 1202 1180 xa_for_each_marked_start(&dpll_pin_xa, i, pin, DPLL_REGISTERED, 1203 1181 ctx->idx) { 1182 + if (!dpll_pin_available(pin)) 1183 + continue; 1204 1184 hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, 1205 1185 cb->nlh->nlmsg_seq, 1206 1186 &dpll_nl_family, NLM_F_MULTI, ··· 1465 1441 } 1466 1442 info->user_ptr[0] = xa_load(&dpll_pin_xa, 1467 1443 nla_get_u32(info->attrs[DPLL_A_PIN_ID])); 1468 - if (!info->user_ptr[0]) { 1444 + if (!info->user_ptr[0] || 1445 + !dpll_pin_available(info->user_ptr[0])) { 1469 1446 NL_SET_ERR_MSG(info->extack, "pin not found"); 1470 1447 ret = -ENODEV; 1471 1448 goto unlock_dev;