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

Configure Feed

Select the types of activity you want to include in your feed.

drm/xe/pf: Fix sysfs initialization

In case of devm_add_action_or_reset() failure the provided cleanup
action will be run immediately on the not yet initialized kobject.
This may lead to errors like:

[ ] kobject: '(null)' (ff110001393608e0): is not initialized, yet kobject_put() is being called.
[ ] WARNING: lib/kobject.c:734 at kobject_put+0xd9/0x250, CPU#0: kworker/0:0/9
[ ] RIP: 0010:kobject_put+0xdf/0x250
[ ] Call Trace:
[ ] xe_sriov_pf_sysfs_init+0x21/0x100 [xe]
[ ] xe_sriov_pf_init_late+0x87/0x2b0 [xe]
[ ] xe_sriov_init_late+0x5f/0x2c0 [xe]
[ ] xe_device_probe+0x5f2/0xc20 [xe]
[ ] xe_pci_probe+0x396/0x610 [xe]
[ ] local_pci_probe+0x47/0xb0

[ ] refcount_t: underflow; use-after-free.
[ ] WARNING: lib/refcount.c:28 at refcount_warn_saturate+0x68/0xb0, CPU#0: kworker/0:0/9
[ ] RIP: 0010:refcount_warn_saturate+0x68/0xb0
[ ] Call Trace:
[ ] kobject_put+0x174/0x250
[ ] xe_sriov_pf_sysfs_init+0x21/0x100 [xe]
[ ] xe_sriov_pf_init_late+0x87/0x2b0 [xe]
[ ] xe_sriov_init_late+0x5f/0x2c0 [xe]
[ ] xe_device_probe+0x5f2/0xc20 [xe]
[ ] xe_pci_probe+0x396/0x610 [xe]
[ ] local_pci_probe+0x47/0xb0

Fix that by calling kobject_init() and kobject_add() separately
and register cleanup action after the kobject is initialized.

Also make this cleanup registration a part of the create helper to
fix another mistake, as in the loop we were wrongly passing parent
kobject while registering cleanup action, and this resulted in some
undetected leaks.

Fixes: 5c170a4d9c53 ("drm/xe/pf: Prepare sysfs for SR-IOV admin attributes")
Signed-off-by: Michal Wajdeczko <michal.wajdeczko@intel.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Reviewed-by: Shuicheng Lin <shuicheng.lin@intel.com>
Link: https://patch.msgid.link/20260203235332.1350-1-michal.wajdeczko@intel.com

+26 -28
+26 -28
drivers/gpu/drm/xe/xe_sriov_pf_sysfs.c
··· 349 349 350 350 /* no user serviceable parts below */ 351 351 352 - static struct kobject *create_xe_sriov_kobj(struct xe_device *xe, unsigned int vfid) 352 + static void action_put_kobject(void *arg) 353 + { 354 + struct kobject *kobj = arg; 355 + 356 + kobject_put(kobj); 357 + } 358 + 359 + static struct kobject *create_xe_sriov_kobj(struct xe_device *xe, unsigned int vfid, 360 + const struct kobj_type *ktype) 353 361 { 354 362 struct xe_sriov_kobj *vkobj; 363 + int err; 355 364 356 365 xe_sriov_pf_assert_vfid(xe, vfid); 357 366 358 367 vkobj = kzalloc(sizeof(*vkobj), GFP_KERNEL); 359 368 if (!vkobj) 360 - return NULL; 369 + return ERR_PTR(-ENOMEM); 361 370 362 371 vkobj->xe = xe; 363 372 vkobj->vfid = vfid; 373 + kobject_init(&vkobj->base, ktype); 374 + 375 + err = devm_add_action_or_reset(xe->drm.dev, action_put_kobject, &vkobj->base); 376 + if (err) 377 + return ERR_PTR(err); 378 + 364 379 return &vkobj->base; 365 380 } 366 381 ··· 478 463 xe_sriov_dbg(xe, "Failed to setup sysfs %s (%pe)\n", what, ERR_PTR(err)); 479 464 } 480 465 481 - static void action_put_kobject(void *arg) 482 - { 483 - struct kobject *kobj = arg; 484 - 485 - kobject_put(kobj); 486 - } 487 - 488 466 static int pf_setup_root(struct xe_device *xe) 489 467 { 490 468 struct kobject *parent = &xe->drm.dev->kobj; 491 469 struct kobject *root; 492 470 int err; 493 471 494 - root = create_xe_sriov_kobj(xe, PFID); 495 - if (!root) 496 - return pf_sysfs_error(xe, -ENOMEM, "root obj"); 472 + root = create_xe_sriov_kobj(xe, PFID, &xe_sriov_dev_ktype); 473 + if (IS_ERR(root)) 474 + return pf_sysfs_error(xe, PTR_ERR(root), "root obj"); 497 475 498 - err = devm_add_action_or_reset(xe->drm.dev, action_put_kobject, root); 499 - if (err) 500 - return pf_sysfs_error(xe, err, "root action"); 501 - 502 - err = kobject_init_and_add(root, &xe_sriov_dev_ktype, parent, "sriov_admin"); 476 + err = kobject_add(root, parent, "sriov_admin"); 503 477 if (err) 504 478 return pf_sysfs_error(xe, err, "root init"); 505 479 ··· 509 505 root = xe->sriov.pf.sysfs.root; 510 506 511 507 for (n = 0; n <= totalvfs; n++) { 512 - kobj = create_xe_sriov_kobj(xe, VFID(n)); 513 - if (!kobj) 514 - return pf_sysfs_error(xe, -ENOMEM, "tree obj"); 515 - 516 - err = devm_add_action_or_reset(xe->drm.dev, action_put_kobject, root); 517 - if (err) 518 - return pf_sysfs_error(xe, err, "tree action"); 508 + kobj = create_xe_sriov_kobj(xe, VFID(n), &xe_sriov_vf_ktype); 509 + if (IS_ERR(kobj)) 510 + return pf_sysfs_error(xe, PTR_ERR(kobj), "tree obj"); 519 511 520 512 if (n) 521 - err = kobject_init_and_add(kobj, &xe_sriov_vf_ktype, 522 - root, "vf%u", n); 513 + err = kobject_add(kobj, root, "vf%u", n); 523 514 else 524 - err = kobject_init_and_add(kobj, &xe_sriov_vf_ktype, 525 - root, "pf"); 515 + err = kobject_add(kobj, root, "pf"); 526 516 if (err) 527 517 return pf_sysfs_error(xe, err, "tree init"); 528 518