Commit e1a9e3db authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'driver-core-5.13-rc4' of...

Merge tag 'driver-core-5.13-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core

Pull driver core fixes from Greg KH:
 "Here are three small driver core / debugfs fixes for 5.13-rc4:

   - debugfs fix for incorrect "lockdown" mode for selinux accesses

   - two device link changes, one bugfix and one cleanup

  All of these have been in linux-next for over a week with no reported
  problems"

* tag 'driver-core-5.13-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core:
  drivers: base: Reduce device link removal code duplication
  drivers: base: Fix device link removal
  debugfs: fix security_locked_down() call for SELinux
parents 494b99f7 0c871315
Loading
Loading
Loading
Loading
+36 −32
Original line number Diff line number Diff line
@@ -194,6 +194,17 @@ int device_links_read_lock_held(void)
{
	return srcu_read_lock_held(&device_links_srcu);
}

static void device_link_synchronize_removal(void)
{
	synchronize_srcu(&device_links_srcu);
}

static void device_link_remove_from_lists(struct device_link *link)
{
	list_del_rcu(&link->s_node);
	list_del_rcu(&link->c_node);
}
#else /* !CONFIG_SRCU */
static DECLARE_RWSEM(device_links_lock);

@@ -224,6 +235,16 @@ int device_links_read_lock_held(void)
	return lockdep_is_held(&device_links_lock);
}
#endif

static inline void device_link_synchronize_removal(void)
{
}

static void device_link_remove_from_lists(struct device_link *link)
{
	list_del(&link->s_node);
	list_del(&link->c_node);
}
#endif /* !CONFIG_SRCU */

static bool device_is_ancestor(struct device *dev, struct device *target)
@@ -445,8 +466,13 @@ static struct attribute *devlink_attrs[] = {
};
ATTRIBUTE_GROUPS(devlink);

static void device_link_free(struct device_link *link)
static void device_link_release_fn(struct work_struct *work)
{
	struct device_link *link = container_of(work, struct device_link, rm_work);

	/* Ensure that all references to the link object have been dropped. */
	device_link_synchronize_removal();

	while (refcount_dec_not_one(&link->rpm_active))
		pm_runtime_put(link->supplier);

@@ -455,24 +481,19 @@ static void device_link_free(struct device_link *link)
	kfree(link);
}

#ifdef CONFIG_SRCU
static void __device_link_free_srcu(struct rcu_head *rhead)
{
	device_link_free(container_of(rhead, struct device_link, rcu_head));
}

static void devlink_dev_release(struct device *dev)
{
	struct device_link *link = to_devlink(dev);

	call_srcu(&device_links_srcu, &link->rcu_head, __device_link_free_srcu);
}
#else
static void devlink_dev_release(struct device *dev)
{
	device_link_free(to_devlink(dev));
	INIT_WORK(&link->rm_work, device_link_release_fn);
	/*
	 * It may take a while to complete this work because of the SRCU
	 * synchronization in device_link_release_fn() and if the consumer or
	 * supplier devices get deleted when it runs, so put it into the "long"
	 * workqueue.
	 */
	queue_work(system_long_wq, &link->rm_work);
}
#endif

static struct class devlink_class = {
	.name = "devlink",
@@ -846,7 +867,6 @@ struct device_link *device_link_add(struct device *consumer,
}
EXPORT_SYMBOL_GPL(device_link_add);

#ifdef CONFIG_SRCU
static void __device_link_del(struct kref *kref)
{
	struct device_link *link = container_of(kref, struct device_link, kref);
@@ -856,25 +876,9 @@ static void __device_link_del(struct kref *kref)

	pm_runtime_drop_link(link);

	list_del_rcu(&link->s_node);
	list_del_rcu(&link->c_node);
	device_link_remove_from_lists(link);
	device_unregister(&link->link_dev);
}
#else /* !CONFIG_SRCU */
static void __device_link_del(struct kref *kref)
{
	struct device_link *link = container_of(kref, struct device_link, kref);

	dev_info(link->consumer, "Dropping the link to %s\n",
		 dev_name(link->supplier));

	pm_runtime_drop_link(link);

	list_del(&link->s_node);
	list_del(&link->c_node);
	device_unregister(&link->link_dev);
}
#endif /* !CONFIG_SRCU */

static void device_link_put_kref(struct device_link *link)
{
+6 −3
Original line number Diff line number Diff line
@@ -45,10 +45,13 @@ static unsigned int debugfs_allow __ro_after_init = DEFAULT_DEBUGFS_ALLOW_BITS;
static int debugfs_setattr(struct user_namespace *mnt_userns,
			   struct dentry *dentry, struct iattr *ia)
{
	int ret = security_locked_down(LOCKDOWN_DEBUGFS);
	int ret;

	if (ret && (ia->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID)))
	if (ia->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID)) {
		ret = security_locked_down(LOCKDOWN_DEBUGFS);
		if (ret)
			return ret;
	}
	return simple_setattr(&init_user_ns, dentry, ia);
}

+2 −4
Original line number Diff line number Diff line
@@ -570,7 +570,7 @@ struct device {
 * @flags: Link flags.
 * @rpm_active: Whether or not the consumer device is runtime-PM-active.
 * @kref: Count repeated addition of the same link.
 * @rcu_head: An RCU head to use for deferred execution of SRCU callbacks.
 * @rm_work: Work structure used for removing the link.
 * @supplier_preactivated: Supplier has been made active before consumer probe.
 */
struct device_link {
@@ -583,9 +583,7 @@ struct device_link {
	u32 flags;
	refcount_t rpm_active;
	struct kref kref;
#ifdef CONFIG_SRCU
	struct rcu_head rcu_head;
#endif
	struct work_struct rm_work;
	bool supplier_preactivated; /* Owned by consumer probe. */
};