diff options
author | Christian Brauner <christian.brauner@ubuntu.com> | 2020-02-27 04:37:11 +0100 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2020-02-26 20:07:25 -0800 |
commit | f70ce185687bbe4e2d7ff126a8c890631f5fc2af (patch) | |
tree | fa62764ac154c9e86c2fa446aa534eebefeedb32 /fs/sysfs | |
parent | d1c73cbdf9d3f6181a50398568372ef41b1f485c (diff) |
sysfs: add sysfs_file_change_owner()
Add helpers to change the owner of a sysfs files.
This function will be used to correctly account for kobject ownership
changes, e.g. when moving network devices between network namespaces.
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>
Diffstat (limited to 'fs/sysfs')
-rw-r--r-- | fs/sysfs/file.c | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 130fc6fbcc03..4ca936ca3ba4 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -558,3 +558,50 @@ void sysfs_remove_bin_file(struct kobject *kobj, kernfs_remove_by_name(kobj->sd, attr->attr.name); } EXPORT_SYMBOL_GPL(sysfs_remove_bin_file); + +static int internal_change_owner(struct kernfs_node *kn, kuid_t kuid, + kgid_t kgid) +{ + struct iattr newattrs = { + .ia_valid = ATTR_UID | ATTR_GID, + .ia_uid = kuid, + .ia_gid = kgid, + }; + return kernfs_setattr(kn, &newattrs); +} + +/** + * sysfs_file_change_owner - change owner of a sysfs file. + * @kobj: object. + * @name: name of the file to change. + * @kuid: new owner's kuid + * @kgid: new owner's kgid + * + * This function looks up the sysfs entry @name under @kobj and changes the + * ownership to @kuid/@kgid. + * + * Returns 0 on success or error code on failure. + */ +int sysfs_file_change_owner(struct kobject *kobj, const char *name, kuid_t kuid, + kgid_t kgid) +{ + struct kernfs_node *kn; + int error; + + if (!name) + return -EINVAL; + + if (!kobj->state_in_sysfs) + return -EINVAL; + + kn = kernfs_find_and_get(kobj->sd, name); + if (!kn) + return -ENOENT; + + error = internal_change_owner(kn, kuid, kgid); + + kernfs_put(kn); + + return error; +} +EXPORT_SYMBOL_GPL(sysfs_file_change_owner); |