Commit 0666a3ae authored by Christian Brauner's avatar Christian Brauner Committed by David S. Miller
Browse files

sysfs: add sysfs_link_change_owner()



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

Reviewed-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarChristian Brauner <christian.brauner@ubuntu.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f70ce185
Loading
Loading
Loading
Loading
+41 −0
Original line number Diff line number Diff line
@@ -570,6 +570,47 @@ static int internal_change_owner(struct kernfs_node *kn, kuid_t kuid,
	return kernfs_setattr(kn, &newattrs);
}

/**
 *	sysfs_link_change_owner - change owner of a sysfs file.
 *	@kobj:	object of the kernfs_node the symlink is located in.
 *	@targ:	object of the kernfs_node the symlink points to.
 *	@name:	name of the link.
 *	@kuid:	new owner's kuid
 *	@kgid:	new owner's kgid
 *
 * This function looks up the sysfs symlink entry @name under @kobj and changes
 * the ownership to @kuid/@kgid. The symlink is looked up in the namespace of
 * @targ.
 *
 * Returns 0 on success or error code on failure.
 */
int sysfs_link_change_owner(struct kobject *kobj, struct kobject *targ,
			    const char *name, kuid_t kuid, kgid_t kgid)
{
	struct kernfs_node *kn = NULL;
	int error;

	if (!name || !kobj->state_in_sysfs || !targ->state_in_sysfs)
		return -EINVAL;

	error = -ENOENT;
	kn = kernfs_find_and_get_ns(kobj->sd, name, targ->sd->ns);
	if (!kn)
		goto out;

	error = -EINVAL;
	if (kernfs_type(kn) != KERNFS_LINK)
		goto out;
	if (kn->symlink.target_kn->priv != targ)
		goto out;

	error = internal_change_owner(kn, kuid, kgid);

out:
	kernfs_put(kn);
	return error;
}

/**
 *	sysfs_file_change_owner - change owner of a sysfs file.
 *	@kobj:	object.
+10 −0
Original line number Diff line number Diff line
@@ -312,6 +312,8 @@ static inline void sysfs_enable_ns(struct kernfs_node *kn)

int sysfs_file_change_owner(struct kobject *kobj, const char *name, kuid_t kuid,
			    kgid_t kgid);
int sysfs_link_change_owner(struct kobject *kobj, struct kobject *targ,
			    const char *name, kuid_t kuid, kgid_t kgid);

#else /* CONFIG_SYSFS */

@@ -532,6 +534,14 @@ static inline int sysfs_file_change_owner(struct kobject *kobj,
	return 0;
}

static inline int sysfs_link_change_owner(struct kobject *kobj,
					  struct kobject *targ,
					  const char *name, kuid_t kuid,
					  kgid_t kgid)
{
	return 0;
}

#endif /* CONFIG_SYSFS */

static inline int __must_check sysfs_create_file(struct kobject *kobj,