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

sysfs: add sysfs_change_owner()

Add a helper to change the owner of sysfs objects.
This function will be used to correctly account for kobject ownership
changes, e.g. when moving network devices between network namespaces.

This mirrors how a kobject is added through driver core which in its guts is
done via kobject_add_internal() which in summary creates the main directory via
create_dir(), populates that directory with the groups associated with the
ktype of the kobject (if any) and populates the directory with the basic
attributes associated with the ktype of the kobject (if any). These are the
basic steps that are associated with adding a kobject in sysfs.
Any additional properties are added by the specific subsystem itself (not by
driver core) after it has registered the device. So for the example of network
devices, a network device will e.g. register a queue subdirectory under the
basic sysfs directory for the network device and than further subdirectories
within that queues subdirectory. But that is all specific to network devices
and they call the corresponding sysfs functions to do that directly when they
create those queue objects. So anything that a subsystem adds outside of what
driver core does must also be changed by it (That's already true for removal of
files it created outside of driver core.) and it's the same for ownership
changes.

Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Christian Brauner and committed by
David S. Miller
2c4f9401 303a4276

+66
+60
fs/sysfs/file.c
··· 646 646 return error; 647 647 } 648 648 EXPORT_SYMBOL_GPL(sysfs_file_change_owner); 649 + 650 + /** 651 + * sysfs_change_owner - change owner of the given object. 652 + * @kobj: object. 653 + * @kuid: new owner's kuid 654 + * @kgid: new owner's kgid 655 + * 656 + * Change the owner of the default directory, files, groups, and attributes of 657 + * @kobj to @kuid/@kgid. Note that sysfs_change_owner mirrors how the sysfs 658 + * entries for a kobject are added by driver core. In summary, 659 + * sysfs_change_owner() takes care of the default directory entry for @kobj, 660 + * the default attributes associated with the ktype of @kobj and the default 661 + * attributes associated with the ktype of @kobj. 662 + * Additional properties not added by driver core have to be changed by the 663 + * driver or subsystem which created them. This is similar to how 664 + * driver/subsystem specific entries are removed. 665 + * 666 + * Returns 0 on success or error code on failure. 667 + */ 668 + int sysfs_change_owner(struct kobject *kobj, kuid_t kuid, kgid_t kgid) 669 + { 670 + int error; 671 + const struct kobj_type *ktype; 672 + 673 + if (!kobj->state_in_sysfs) 674 + return -EINVAL; 675 + 676 + /* Change the owner of the kobject itself. */ 677 + error = internal_change_owner(kobj->sd, kuid, kgid); 678 + if (error) 679 + return error; 680 + 681 + ktype = get_ktype(kobj); 682 + if (ktype) { 683 + struct attribute **kattr; 684 + 685 + /* 686 + * Change owner of the default attributes associated with the 687 + * ktype of @kobj. 688 + */ 689 + for (kattr = ktype->default_attrs; kattr && *kattr; kattr++) { 690 + error = sysfs_file_change_owner(kobj, (*kattr)->name, 691 + kuid, kgid); 692 + if (error) 693 + return error; 694 + } 695 + 696 + /* 697 + * Change owner of the default groups associated with the 698 + * ktype of @kobj. 699 + */ 700 + error = sysfs_groups_change_owner(kobj, ktype->default_groups, 701 + kuid, kgid); 702 + if (error) 703 + return error; 704 + } 705 + 706 + return 0; 707 + } 708 + EXPORT_SYMBOL_GPL(sysfs_change_owner);
+6
include/linux/sysfs.h
··· 312 312 313 313 int sysfs_file_change_owner(struct kobject *kobj, const char *name, kuid_t kuid, 314 314 kgid_t kgid); 315 + int sysfs_change_owner(struct kobject *kobj, kuid_t kuid, kgid_t kgid); 315 316 int sysfs_link_change_owner(struct kobject *kobj, struct kobject *targ, 316 317 const char *name, kuid_t kuid, kgid_t kgid); 317 318 int sysfs_groups_change_owner(struct kobject *kobj, ··· 545 544 struct kobject *targ, 546 545 const char *name, kuid_t kuid, 547 546 kgid_t kgid) 547 + { 548 + return 0; 549 + } 550 + 551 + static inline int sysfs_change_owner(struct kobject *kobj, kuid_t kuid, kgid_t kgid) 548 552 { 549 553 return 0; 550 554 }