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.

fbdev: Use device_create_with_groups() to fix sysfs groups registration race

The fbdev sysfs attributes are registered after sending the uevent for
the device creation, leaving a race window where e.g. udev rules may
not be able to access the sysfs attributes because the registration is
not done yet.

Fix this by switching to device_create_with_groups(). This also results in
a nice cleanup. After switching to device_create_with_groups() all that
is left of fb_init_device() is setting the drvdata and that can be passed
to device_create[_with_groups]() too. After which fb_init_device() can
be completely removed.

Dropping fb_init_device() + fb_cleanup_device() in turn allows removing
fb_info.class_flag as they were the only user of this field.

Fixes: 5fc830d6aca1 ("fbdev: Register sysfs groups through device_add_group")
Cc: stable@vger.kernel.org
Cc: Shixiong Ou <oushixiong@kylinos.cn>
Signed-off-by: Hans de Goede <johannes.goede@oss.qualcomm.com>
Signed-off-by: Helge Deller <deller@gmx.de>

authored by

Hans de Goede and committed by
Helge Deller
68eeb087 120adae7

+3 -34
+3 -33
drivers/video/fbdev/core/fbsysfs.c
··· 12 12 13 13 #include "fb_internal.h" 14 14 15 - #define FB_SYSFS_FLAG_ATTR 1 16 - 17 15 static int activate(struct fb_info *fb_info, struct fb_var_screeninfo *var) 18 16 { 19 17 int err; ··· 449 451 NULL, 450 452 }; 451 453 452 - static const struct attribute_group fb_device_attr_group = { 453 - .attrs = fb_device_attrs, 454 - }; 455 - 456 - static int fb_init_device(struct fb_info *fb_info) 457 - { 458 - int ret; 459 - 460 - dev_set_drvdata(fb_info->dev, fb_info); 461 - 462 - fb_info->class_flag |= FB_SYSFS_FLAG_ATTR; 463 - 464 - ret = device_add_group(fb_info->dev, &fb_device_attr_group); 465 - if (ret) 466 - fb_info->class_flag &= ~FB_SYSFS_FLAG_ATTR; 467 - 468 - return 0; 469 - } 470 - 471 - static void fb_cleanup_device(struct fb_info *fb_info) 472 - { 473 - if (fb_info->class_flag & FB_SYSFS_FLAG_ATTR) { 474 - device_remove_group(fb_info->dev, &fb_device_attr_group); 475 - 476 - fb_info->class_flag &= ~FB_SYSFS_FLAG_ATTR; 477 - } 478 - } 454 + ATTRIBUTE_GROUPS(fb_device); 479 455 480 456 int fb_device_create(struct fb_info *fb_info) 481 457 { ··· 457 485 dev_t devt = MKDEV(FB_MAJOR, node); 458 486 int ret; 459 487 460 - fb_info->dev = device_create(fb_class, fb_info->device, devt, NULL, "fb%d", node); 488 + fb_info->dev = device_create_with_groups(fb_class, fb_info->device, devt, fb_info, 489 + fb_device_groups, "fb%d", node); 461 490 if (IS_ERR(fb_info->dev)) { 462 491 /* Not fatal */ 463 492 ret = PTR_ERR(fb_info->dev); 464 493 pr_warn("Unable to create device for framebuffer %d; error %d\n", node, ret); 465 494 fb_info->dev = NULL; 466 - } else { 467 - fb_init_device(fb_info); 468 495 } 469 496 470 497 return 0; ··· 476 505 if (!fb_info->dev) 477 506 return; 478 507 479 - fb_cleanup_device(fb_info); 480 508 device_destroy(fb_class, devt); 481 509 fb_info->dev = NULL; 482 510 }
-1
include/linux/fb.h
··· 493 493 #if defined(CONFIG_FB_DEVICE) 494 494 struct device *dev; /* This is this fb device */ 495 495 #endif 496 - int class_flag; /* private sysfs flags */ 497 496 #ifdef CONFIG_FB_TILEBLITTING 498 497 struct fb_tile_ops *tileops; /* Tile Blitting */ 499 498 #endif