From patchwork Mon Feb 17 16:14:27 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Brauner X-Patchwork-Id: 1239366 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=ubuntu.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 48LpxK4Hygz9sRG for ; Tue, 18 Feb 2020 03:15:33 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728696AbgBQQOq (ORCPT ); Mon, 17 Feb 2020 11:14:46 -0500 Received: from youngberry.canonical.com ([91.189.89.112]:49196 "EHLO youngberry.canonical.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726646AbgBQQOp (ORCPT ); Mon, 17 Feb 2020 11:14:45 -0500 Received: from ip5f5bf7ec.dynamic.kabel-deutschland.de ([95.91.247.236] helo=wittgenstein.fritz.box) by youngberry.canonical.com with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1j3j2g-0003Cp-3h; Mon, 17 Feb 2020 16:14:42 +0000 From: Christian Brauner To: "David S. Miller" , Greg Kroah-Hartman , linux-kernel@vger.kernel.org, netdev@vger.kernel.org Cc: "Rafael J. Wysocki" , Pavel Machek , Jakub Kicinski , Eric Dumazet , Stephen Hemminger , linux-pm@vger.kernel.org, Christian Brauner Subject: [PATCH net-next v2 01/10] sysfs: add sysfs_file_change_owner{_by_name}() Date: Mon, 17 Feb 2020 17:14:27 +0100 Message-Id: <20200217161436.1748598-2-christian.brauner@ubuntu.com> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20200217161436.1748598-1-christian.brauner@ubuntu.com> References: <20200217161436.1748598-1-christian.brauner@ubuntu.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Add helpers to change owner of a sysfs files. The ownership of a sysfs object is determined based on the ownership of the corresponding kobject, i.e. only if the ownership of a kobject is changed will this function change the ownership of the corresponding sysfs entry. This function will be used to correctly account for kobject ownership changes, e.g. when moving network devices between network namespaces. Signed-off-by: Christian Brauner --- /* v2 */ - Greg Kroah-Hartman : - Better naming for sysfs_file_change_owner() to reflect the fact that it can be used to change the owner of the kobject itself by passing NULL as argument. - Christian Brauner : - Split sysfs_file_change_owner() into two helpers sysfs_change_owner() and sysfs_change_owner_by_name(). The former changes the owner of the kobject itself, the latter the owner of the kobject looked up via the name argument. --- fs/sysfs/file.c | 82 +++++++++++++++++++++++++++++++++++++++++++ include/linux/sysfs.h | 14 ++++++++ 2 files changed, 96 insertions(+) diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 130fc6fbcc03..8f2607de2456 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -558,3 +558,85 @@ 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, struct kobject *kobj) +{ + kuid_t uid; + kgid_t gid; + struct iattr newattrs = { + .ia_valid = ATTR_UID | ATTR_GID, + }; + + kobject_get_ownership(kobj, &uid, &gid); + newattrs.ia_uid = uid; + newattrs.ia_gid = gid; + + return kernfs_setattr(kn, &newattrs); +} + +/** + * sysfs_file_change_owner_by_name - change owner of a file. + * @kobj: object. + * @name: name of the file to change. + * + * To change the ownership of a sysfs object, the caller must first change the + * uid/gid of the kobject and then call this function. Usually this will be + * taken care of by the relevant subsystem, e.g. moving a network device + * between network namespaces owned by different user namespaces will change + * the uid/gid of the kobject to the uid/gid of the root user in the user + * namespace. Calling this function afterwards will cause the sysfs object to + * reflect the new uid/gid. + */ +int sysfs_file_change_owner_by_name(struct kobject *kobj, const char *name) +{ + 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, kobj); + + kernfs_put(kn); + + return error; +} +EXPORT_SYMBOL_GPL(sysfs_file_change_owner_by_name); + +/** + * sysfs_file_change_owner - change owner of a file. + * @kobj: object. + * + * To change the ownership of a sysfs object, the caller must first change the + * uid/gid of the kobject and then call this function. Usually this will be + * taken care of by the relevant subsystem, e.g. moving a network device + * between network namespaces owned by different user namespaces will change + * the uid/gid of the kobject to the uid/gid of the root user in the user + * namespace. Calling this function afterwards will cause the sysfs object to + * reflect the new uid/gid. + */ +int sysfs_file_change_owner(struct kobject *kobj) +{ + struct kernfs_node *kn; + int error; + + if (!kobj->state_in_sysfs) + return -EINVAL; + + kernfs_get(kobj->sd); + + kn = kobj->sd; + error = internal_change_owner(kn, kobj); + + kernfs_put(kn); + + return error; +} +EXPORT_SYMBOL_GPL(sysfs_file_change_owner); diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index fa7ee503fb76..4b3c3b76ff80 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -310,6 +310,9 @@ static inline void sysfs_enable_ns(struct kernfs_node *kn) return kernfs_enable_ns(kn); } +int sysfs_file_change_owner(struct kobject *kobj); +int sysfs_file_change_owner_by_name(struct kobject *kobj, const char *name); + #else /* CONFIG_SYSFS */ static inline int sysfs_create_dir_ns(struct kobject *kobj, const void *ns) @@ -522,6 +525,17 @@ static inline void sysfs_enable_ns(struct kernfs_node *kn) { } +static inline int int sysfs_file_change_owner(struct kobject *kobj) +{ + return 0; +} + +static inline int sysfs_file_change_owner_by_name(struct kobject *kobj, + const char *name) +{ + return 0; +} + #endif /* CONFIG_SYSFS */ static inline int __must_check sysfs_create_file(struct kobject *kobj, From patchwork Mon Feb 17 16:14:28 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Brauner X-Patchwork-Id: 1239368 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=ubuntu.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 48LpxW3416z9sRR for ; Tue, 18 Feb 2020 03:15:43 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728626AbgBQQOq (ORCPT ); Mon, 17 Feb 2020 11:14:46 -0500 Received: from youngberry.canonical.com ([91.189.89.112]:49200 "EHLO youngberry.canonical.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726760AbgBQQOp (ORCPT ); Mon, 17 Feb 2020 11:14:45 -0500 Received: from ip5f5bf7ec.dynamic.kabel-deutschland.de ([95.91.247.236] helo=wittgenstein.fritz.box) by youngberry.canonical.com with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1j3j2g-0003Cp-N3; Mon, 17 Feb 2020 16:14:42 +0000 From: Christian Brauner To: "David S. Miller" , Greg Kroah-Hartman , linux-kernel@vger.kernel.org, netdev@vger.kernel.org Cc: "Rafael J. Wysocki" , Pavel Machek , Jakub Kicinski , Eric Dumazet , Stephen Hemminger , linux-pm@vger.kernel.org, Christian Brauner Subject: [PATCH net-next v2 02/10] sysfs: add sysfs_link_change_owner() Date: Mon, 17 Feb 2020 17:14:28 +0100 Message-Id: <20200217161436.1748598-3-christian.brauner@ubuntu.com> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20200217161436.1748598-1-christian.brauner@ubuntu.com> References: <20200217161436.1748598-1-christian.brauner@ubuntu.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Add a helper to change the owner of a sysfs link. The ownership of a sysfs object is determined based on the ownership of the corresponding kobject, i.e. only if the ownership of a kobject is changed will this function change the ownership of the corresponding sysfs entry. This function will be used to correctly account for kobject ownership changes, e.g. when moving network devices between network namespaces. Signed-off-by: Christian Brauner --- /* v2 */ - Greg Kroah-Hartman : - Add comment how ownership of sysfs object is changed. --- fs/sysfs/file.c | 46 +++++++++++++++++++++++++++++++++++++++++++ include/linux/sysfs.h | 9 +++++++++ 2 files changed, 55 insertions(+) diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 8f2607de2456..8b20245f359c 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -574,6 +574,52 @@ static int internal_change_owner(struct kernfs_node *kn, struct kobject *kobj) return kernfs_setattr(kn, &newattrs); } +/** + * sysfs_link_change_owner - change owner of a link. + * @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. + * + * To change the ownership of a sysfs object, the caller must first change the + * uid/gid of the kobject and then call this function. Usually this will be + * taken care of by the relevant subsystem, e.g. moving a network device + * between network namespaces owned by different user namespaces will change + * the uid/gid of the kobject to the uid/gid of the root user in the user + * namespace. Calling this function afterwards will cause the sysfs object to + * reflect the new uid/gid. + */ +int sysfs_link_change_owner(struct kobject *kobj, struct kobject *targ, + const char *name) +{ + struct kernfs_node *parent, *kn = NULL; + int error; + + if (!kobj) + parent = sysfs_root_kn; + else + parent = kobj->sd; + + if (!targ->state_in_sysfs) + return -EINVAL; + + error = -ENOENT; + kn = kernfs_find_and_get_ns(parent, 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, targ); + +out: + kernfs_put(kn); + return error; +} + /** * sysfs_file_change_owner_by_name - change owner of a file. * @kobj: object. diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 4b3c3b76ff80..238f3d7b1fa0 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -312,6 +312,8 @@ static inline void sysfs_enable_ns(struct kernfs_node *kn) int sysfs_file_change_owner(struct kobject *kobj); int sysfs_file_change_owner_by_name(struct kobject *kobj, const char *name); +int sysfs_link_change_owner(struct kobject *kobj, struct kobject *targ, + const char *name); #else /* CONFIG_SYSFS */ @@ -536,6 +538,13 @@ static inline int sysfs_file_change_owner_by_name(struct kobject *kobj, return 0; } +static inline int sysfs_link_change_owner(struct kobject *kobj, + struct kobject *targ, + const char *name) +{ + return 0; +} + #endif /* CONFIG_SYSFS */ static inline int __must_check sysfs_create_file(struct kobject *kobj, From patchwork Mon Feb 17 16:14:29 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Brauner X-Patchwork-Id: 1239359 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=ubuntu.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 48LpwS2GtYz9sRN for ; Tue, 18 Feb 2020 03:14:48 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728928AbgBQQOq (ORCPT ); Mon, 17 Feb 2020 11:14:46 -0500 Received: from youngberry.canonical.com ([91.189.89.112]:49203 "EHLO youngberry.canonical.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727108AbgBQQOq (ORCPT ); Mon, 17 Feb 2020 11:14:46 -0500 Received: from ip5f5bf7ec.dynamic.kabel-deutschland.de ([95.91.247.236] helo=wittgenstein.fritz.box) by youngberry.canonical.com with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1j3j2h-0003Cp-AT; Mon, 17 Feb 2020 16:14:43 +0000 From: Christian Brauner To: "David S. Miller" , Greg Kroah-Hartman , linux-kernel@vger.kernel.org, netdev@vger.kernel.org Cc: "Rafael J. Wysocki" , Pavel Machek , Jakub Kicinski , Eric Dumazet , Stephen Hemminger , linux-pm@vger.kernel.org, Christian Brauner Subject: [PATCH net-next v2 03/10] sysfs: add sysfs_group_change_owner() Date: Mon, 17 Feb 2020 17:14:29 +0100 Message-Id: <20200217161436.1748598-4-christian.brauner@ubuntu.com> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20200217161436.1748598-1-christian.brauner@ubuntu.com> References: <20200217161436.1748598-1-christian.brauner@ubuntu.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Add a helper to change the owner of a sysfs group. The ownership of a sysfs object is determined based on the ownership of the corresponding kobject, i.e. only if the ownership of a kobject is changed will this function change the ownership of the corresponding sysfs entry. This function will be used to correctly account for kobject ownership changes, e.g. when moving network devices between network namespaces. Signed-off-by: Christian Brauner --- /* v2 */ - Greg Kroah-Hartman : - Add comment how ownership of sysfs object is changed. --- fs/sysfs/group.c | 93 +++++++++++++++++++++++++++++++++++++++++++ include/linux/sysfs.h | 8 ++++ 2 files changed, 101 insertions(+) diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c index c4ab045926b7..7d158d59d097 100644 --- a/fs/sysfs/group.c +++ b/fs/sysfs/group.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "sysfs.h" @@ -457,3 +458,95 @@ int __compat_only_sysfs_link_entry_to_kobj(struct kobject *kobj, return PTR_ERR_OR_ZERO(link); } EXPORT_SYMBOL_GPL(__compat_only_sysfs_link_entry_to_kobj); + +static int sysfs_group_attrs_change_owner(struct kernfs_node *grp_kn, + const struct attribute_group *grp, + struct iattr *newattrs) +{ + struct kernfs_node *kn; + int error; + + if (grp->attrs) { + struct attribute *const *attr; + + for (attr = grp->attrs; *attr; attr++) { + kn = kernfs_find_and_get(grp_kn, (*attr)->name); + if (!kn) + return -ENOENT; + + error = kernfs_setattr(kn, newattrs); + kernfs_put(kn); + if (error) + return error; + } + } + + if (grp->bin_attrs) { + struct bin_attribute *const *bin_attr; + + for (bin_attr = grp->bin_attrs; *bin_attr; bin_attr++) { + kn = kernfs_find_and_get(grp_kn, (*bin_attr)->attr.name); + if (!kn) + return -ENOENT; + + error = kernfs_setattr(kn, newattrs); + kernfs_put(kn); + if (error) + return error; + } + } + + return 0; +} + +/** + * sysfs_group_change_owner - change owner of an attribute group. + * @kobj: The kobject containing the group. + * @grp: The attribute group. + * + * To change the ownership of a sysfs object, the caller must first change the + * uid/gid of the kobject and then call this function. Usually this will be + * taken care of by the relevant subsystem, e.g. moving a network device + * between network namespaces owned by different user namespaces will change + * the uid/gid of the kobject to the uid/gid of the root user in the user + * namespace. Calling this function afterwards will cause the sysfs object to + * reflect the new uid/gid. + * + * Returns 0 on success or error code on failure. + */ +int sysfs_group_change_owner(struct kobject *kobj, + const struct attribute_group *grp) +{ + struct kernfs_node *grp_kn; + kuid_t uid; + kgid_t gid; + int error; + struct iattr newattrs = { + .ia_valid = ATTR_UID | ATTR_GID, + }; + + if (!kobj->state_in_sysfs) + return -EINVAL; + + if (grp->name) { + grp_kn = kernfs_find_and_get(kobj->sd, grp->name); + } else { + kernfs_get(kobj->sd); + grp_kn = kobj->sd; + } + if (!grp_kn) + return -ENOENT; + + kobject_get_ownership(kobj, &uid, &gid); + newattrs.ia_uid = uid; + newattrs.ia_gid = gid; + + error = kernfs_setattr(grp_kn, &newattrs); + if (!error) + error = sysfs_group_attrs_change_owner(grp_kn, grp, &newattrs); + + kernfs_put(grp_kn); + + return error; +} +EXPORT_SYMBOL_GPL(sysfs_group_change_owner); diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 238f3d7b1fa0..dd211f0a654b 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -314,6 +314,8 @@ int sysfs_file_change_owner(struct kobject *kobj); int sysfs_file_change_owner_by_name(struct kobject *kobj, const char *name); int sysfs_link_change_owner(struct kobject *kobj, struct kobject *targ, const char *name); +int sysfs_group_change_owner(struct kobject *kobj, + const struct attribute_group *groups); #else /* CONFIG_SYSFS */ @@ -545,6 +547,12 @@ static inline int sysfs_link_change_owner(struct kobject *kobj, return 0; } +static inline int sysfs_group_change_owner(struct kobject *kobj, + const struct attribute_group **groups) +{ + return 0; +} + #endif /* CONFIG_SYSFS */ static inline int __must_check sysfs_create_file(struct kobject *kobj, From patchwork Mon Feb 17 16:14:30 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Brauner X-Patchwork-Id: 1239367 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=ubuntu.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 48LpxM5MX0z9sRN for ; Tue, 18 Feb 2020 03:15:35 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729397AbgBQQPc (ORCPT ); Mon, 17 Feb 2020 11:15:32 -0500 Received: from youngberry.canonical.com ([91.189.89.112]:49206 "EHLO youngberry.canonical.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727217AbgBQQOq (ORCPT ); Mon, 17 Feb 2020 11:14:46 -0500 Received: from ip5f5bf7ec.dynamic.kabel-deutschland.de ([95.91.247.236] helo=wittgenstein.fritz.box) by youngberry.canonical.com with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1j3j2h-0003Cp-Tm; Mon, 17 Feb 2020 16:14:44 +0000 From: Christian Brauner To: "David S. Miller" , Greg Kroah-Hartman , linux-kernel@vger.kernel.org, netdev@vger.kernel.org Cc: "Rafael J. Wysocki" , Pavel Machek , Jakub Kicinski , Eric Dumazet , Stephen Hemminger , linux-pm@vger.kernel.org, Christian Brauner Subject: [PATCH net-next v2 04/10] sysfs: add sysfs_groups_change_owner() Date: Mon, 17 Feb 2020 17:14:30 +0100 Message-Id: <20200217161436.1748598-5-christian.brauner@ubuntu.com> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20200217161436.1748598-1-christian.brauner@ubuntu.com> References: <20200217161436.1748598-1-christian.brauner@ubuntu.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Add a helper to change the owner of a set of sysfs groups file. The ownership of a sysfs object is determined based on the ownership of the corresponding kobject, i.e. only if the ownership of a kobject is changed will this function change the ownership of the corresponding sysfs entry. This function will be used to correctly account for kobject ownership changes, e.g. when moving network devices between network namespaces. Signed-off-by: Christian Brauner --- /* v2 */ - Greg Kroah-Hartman : - Add comment how ownership of sysfs object is changed. --- fs/sysfs/group.c | 36 ++++++++++++++++++++++++++++++++++++ include/linux/sysfs.h | 8 ++++++++ 2 files changed, 44 insertions(+) diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c index 7d158d59d097..0fc7b119a5dd 100644 --- a/fs/sysfs/group.c +++ b/fs/sysfs/group.c @@ -550,3 +550,39 @@ int sysfs_group_change_owner(struct kobject *kobj, return error; } EXPORT_SYMBOL_GPL(sysfs_group_change_owner); + +/** + * sysfs_groups_change_owner - change owner of a set of attribute groups. + * @kobj: The kobject containing the groups. + * @groups: The attribute groups. + * + * To change the ownership of a sysfs object, the caller must first change the + * uid/gid of the kobject and then call this function. Usually this will be + * taken care of by the relevant subsystem, e.g. moving a network device + * between network namespaces owned by different user namespaces will change + * the uid/gid of the kobject to the uid/gid of the root user in the user + * namespace. Calling this function afterwards will cause the sysfs object to + * reflect the new uid/gid. + * + * Returns 0 on success or error code on failure. + */ +int sysfs_groups_change_owner(struct kobject *kobj, + const struct attribute_group **groups) +{ + int error = 0, i; + + if (!kobj->state_in_sysfs) + return -EINVAL; + + if (!groups) + return 0; + + for (i = 0; groups[i]; i++) { + error = sysfs_group_change_owner(kobj, groups[i]); + if (error) + break; + } + + return error; +} +EXPORT_SYMBOL_GPL(sysfs_groups_change_owner); diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index dd211f0a654b..d13c6cc8e487 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -314,6 +314,8 @@ int sysfs_file_change_owner(struct kobject *kobj); int sysfs_file_change_owner_by_name(struct kobject *kobj, const char *name); int sysfs_link_change_owner(struct kobject *kobj, struct kobject *targ, const char *name); +int sysfs_groups_change_owner(struct kobject *kobj, + const struct attribute_group **groups); int sysfs_group_change_owner(struct kobject *kobj, const struct attribute_group *groups); @@ -547,6 +549,12 @@ static inline int sysfs_link_change_owner(struct kobject *kobj, return 0; } +static inline int sysfs_groups_change_owner(struct kobject *kobj, + const struct attribute_group **groups) +{ + return 0; +} + static inline int sysfs_group_change_owner(struct kobject *kobj, const struct attribute_group **groups) { From patchwork Mon Feb 17 16:14:31 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Brauner X-Patchwork-Id: 1239363 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=ubuntu.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 48Lpww6W1Yz9sRG for ; Tue, 18 Feb 2020 03:15:12 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729317AbgBQQOt (ORCPT ); Mon, 17 Feb 2020 11:14:49 -0500 Received: from youngberry.canonical.com ([91.189.89.112]:49212 "EHLO youngberry.canonical.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727926AbgBQQOr (ORCPT ); Mon, 17 Feb 2020 11:14:47 -0500 Received: from ip5f5bf7ec.dynamic.kabel-deutschland.de ([95.91.247.236] helo=wittgenstein.fritz.box) by youngberry.canonical.com with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1j3j2i-0003Cp-Fz; Mon, 17 Feb 2020 16:14:44 +0000 From: Christian Brauner To: "David S. Miller" , Greg Kroah-Hartman , linux-kernel@vger.kernel.org, netdev@vger.kernel.org Cc: "Rafael J. Wysocki" , Pavel Machek , Jakub Kicinski , Eric Dumazet , Stephen Hemminger , linux-pm@vger.kernel.org, Christian Brauner Subject: [PATCH net-next v2 05/10] sysfs: add sysfs_change_owner() Date: Mon, 17 Feb 2020 17:14:31 +0100 Message-Id: <20200217161436.1748598-6-christian.brauner@ubuntu.com> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20200217161436.1748598-1-christian.brauner@ubuntu.com> References: <20200217161436.1748598-1-christian.brauner@ubuntu.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Add a helper to change the owner of sysfs objects. The ownership of a sysfs object is determined based on the ownership of the corresponding kobject, i.e. only if the ownership of a kobject is changed will this function change the ownership of the corresponding sysfs entry. This function will be used to correctly account for kobject ownership changes, e.g. when moving network devices between network namespaces. Signed-off-by: Christian Brauner --- /* v2 */ - Greg Kroah-Hartman : - Add comment how ownership of sysfs object is changed. --- fs/sysfs/file.c | 43 +++++++++++++++++++++++++++++++++++++++++++ include/linux/sysfs.h | 6 ++++++ 2 files changed, 49 insertions(+) diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index 8b20245f359c..f88b8bf2fcc3 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -686,3 +686,46 @@ int sysfs_file_change_owner(struct kobject *kobj) return error; } EXPORT_SYMBOL_GPL(sysfs_file_change_owner); + +/** + * sysfs_change_owner - change owner of the given object. + * @kobj: object. + * + * To change the ownership of a sysfs object, the caller must first change the + * uid/gid of the kobject and then call this function. Usually this will be + * taken care of by the relevant subsystem, e.g. moving a network device + * between network namespaces owned by different user namespaces will change + * the uid/gid of the kobject to the uid/gid of the root user in the user + * namespace. Calling this function afterwards will cause the sysfs object to + * reflect the new uid/gid. + */ +int sysfs_change_owner(struct kobject *kobj) +{ + int error; + const struct kobj_type *ktype; + + if (!kobj->state_in_sysfs) + return -EINVAL; + + error = sysfs_file_change_owner(kobj); + if (error) + return error; + + ktype = get_ktype(kobj); + if (ktype) { + struct attribute **kattr; + + for (kattr = ktype->default_attrs; kattr && *kattr; kattr++) { + error = sysfs_file_change_owner_by_name(kobj, (*kattr)->name); + if (error) + return error; + } + + error = sysfs_groups_change_owner(kobj, ktype->default_groups); + if (error) + return error; + } + + return 0; +} +EXPORT_SYMBOL_GPL(sysfs_change_owner); diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index d13c6cc8e487..ce5165a111bc 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -312,6 +312,7 @@ static inline void sysfs_enable_ns(struct kernfs_node *kn) int sysfs_file_change_owner(struct kobject *kobj); int sysfs_file_change_owner_by_name(struct kobject *kobj, const char *name); +int sysfs_change_owner(struct kobject *kobj); int sysfs_link_change_owner(struct kobject *kobj, struct kobject *targ, const char *name); int sysfs_groups_change_owner(struct kobject *kobj, @@ -549,6 +550,11 @@ static inline int sysfs_link_change_owner(struct kobject *kobj, return 0; } +static inline int sysfs_change_owner(struct kobject *kobj) +{ + return 0; +} + static inline int sysfs_groups_change_owner(struct kobject *kobj, const struct attribute_group **groups) { From patchwork Mon Feb 17 16:14:32 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Brauner X-Patchwork-Id: 1239365 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=ubuntu.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 48Lpx86l8lz9sRY for ; Tue, 18 Feb 2020 03:15:24 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729300AbgBQQPV (ORCPT ); Mon, 17 Feb 2020 11:15:21 -0500 Received: from youngberry.canonical.com ([91.189.89.112]:49218 "EHLO youngberry.canonical.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728778AbgBQQOr (ORCPT ); Mon, 17 Feb 2020 11:14:47 -0500 Received: from ip5f5bf7ec.dynamic.kabel-deutschland.de ([95.91.247.236] helo=wittgenstein.fritz.box) by youngberry.canonical.com with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1j3j2j-0003Cp-F4; Mon, 17 Feb 2020 16:14:45 +0000 From: Christian Brauner To: "David S. Miller" , Greg Kroah-Hartman , linux-kernel@vger.kernel.org, netdev@vger.kernel.org Cc: "Rafael J. Wysocki" , Pavel Machek , Jakub Kicinski , Eric Dumazet , Stephen Hemminger , linux-pm@vger.kernel.org, Christian Brauner Subject: [PATCH net-next v2 06/10] device: add device_change_owner() Date: Mon, 17 Feb 2020 17:14:32 +0100 Message-Id: <20200217161436.1748598-7-christian.brauner@ubuntu.com> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20200217161436.1748598-1-christian.brauner@ubuntu.com> References: <20200217161436.1748598-1-christian.brauner@ubuntu.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Add a helper to change the owner of a device's sysfs entries. This needs to happen when the ownership of a device is changed, e.g. when moving network devices between network namespaces. The ownership of a device is determined based on the ownership of the corresponding kobject, i.e. only if the ownership of a kobject is changed will this function change the ownership of the corresponding device's sysfs entries. This function will be used to correctly account for ownership changes, e.g. when moving network devices between network namespaces. Signed-off-by: Christian Brauner --- /* v2 */ unchanged --- drivers/base/core.c | 73 ++++++++++++++++++++++++++++++++++++++++++ include/linux/device.h | 1 + 2 files changed, 74 insertions(+) diff --git a/drivers/base/core.c b/drivers/base/core.c index 42a672456432..915766c20a47 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -3458,6 +3458,79 @@ int device_move(struct device *dev, struct device *new_parent, } EXPORT_SYMBOL_GPL(device_move); +static int device_attrs_change_owner(struct device *dev) +{ + struct kobject *kobj = &dev->kobj; + struct class *class = dev->class; + const struct device_type *type = dev->type; + int error; + + if (class) { + error = sysfs_groups_change_owner(kobj, class->dev_groups); + if (error) + return error; + } + + if (type) { + error = sysfs_groups_change_owner(kobj, type->groups); + if (error) + return error; + } + + error = sysfs_groups_change_owner(kobj, dev->groups); + if (error) + return error; + + if (device_supports_offline(dev) && !dev->offline_disabled) { + error = sysfs_file_change_owner_by_name(kobj, dev_attr_online.attr.name); + if (error) + return error; + } + + return 0; +} + +/** + * device_change_owner - change the owner of an existing device. + * @dev: device. + */ +int device_change_owner(struct device *dev) +{ + int error; + struct kobject *kobj = &dev->kobj; + + dev = get_device(dev); + if (!dev) + return -EINVAL; + + error = sysfs_change_owner(kobj); + if (error) + goto out; + + error = sysfs_file_change_owner_by_name(kobj, dev_attr_uevent.attr.name); + if (error) + goto out; + + error = device_attrs_change_owner(dev); + if (error) + goto out; + +#ifdef CONFIG_BLOCK + if (sysfs_deprecated && dev->class == &block_class) + goto out; +#endif + + error = sysfs_link_change_owner(&dev->class->p->subsys.kobj, &dev->kobj, + dev_name(dev)); + if (error) + goto out; + +out: + put_device(dev); + return error; +} +EXPORT_SYMBOL_GPL(device_change_owner); + /** * device_shutdown - call ->shutdown() on each device to shutdown. */ diff --git a/include/linux/device.h b/include/linux/device.h index 0cd7c647c16c..63ebd9e3f6b0 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -817,6 +817,7 @@ extern struct device *device_find_child_by_name(struct device *parent, extern int device_rename(struct device *dev, const char *new_name); extern int device_move(struct device *dev, struct device *new_parent, enum dpm_order dpm_order); +extern int device_change_owner(struct device *dev); extern const char *device_get_devnode(struct device *dev, umode_t *mode, kuid_t *uid, kgid_t *gid, const char **tmp); From patchwork Mon Feb 17 16:14:33 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Brauner X-Patchwork-Id: 1239360 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=ubuntu.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 48LpwX2C8Dz9sRN for ; Tue, 18 Feb 2020 03:14:52 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729439AbgBQQOu (ORCPT ); Mon, 17 Feb 2020 11:14:50 -0500 Received: from youngberry.canonical.com ([91.189.89.112]:49224 "EHLO youngberry.canonical.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729015AbgBQQOs (ORCPT ); Mon, 17 Feb 2020 11:14:48 -0500 Received: from ip5f5bf7ec.dynamic.kabel-deutschland.de ([95.91.247.236] helo=wittgenstein.fritz.box) by youngberry.canonical.com with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1j3j2k-0003Cp-33; Mon, 17 Feb 2020 16:14:46 +0000 From: Christian Brauner To: "David S. Miller" , Greg Kroah-Hartman , linux-kernel@vger.kernel.org, netdev@vger.kernel.org Cc: "Rafael J. Wysocki" , Pavel Machek , Jakub Kicinski , Eric Dumazet , Stephen Hemminger , linux-pm@vger.kernel.org, Christian Brauner Subject: [PATCH net-next v2 07/10] drivers/base/power: add dpm_sysfs_change_owner() Date: Mon, 17 Feb 2020 17:14:33 +0100 Message-Id: <20200217161436.1748598-8-christian.brauner@ubuntu.com> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20200217161436.1748598-1-christian.brauner@ubuntu.com> References: <20200217161436.1748598-1-christian.brauner@ubuntu.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Add a helper to change the owner of a device's power entries. This needs to happen when the ownership of a device is changed, e.g. when moving network devices between network namespaces. The ownership of a device's power entries is determined based on the ownership of the corresponding kobject, i.e. only if the ownership of a kobject is changed will this function change the ownership of the corresponding sysfs entries. This function will be used to correctly account for ownership changes, e.g. when moving network devices between network namespaces. Signed-off-by: Christian Brauner --- /* v2 */ - "Rafael J. Wysocki" : - Fold if (dev->power.wakeup && dev->power.wakeup->dev) check into if (device_can_wakeup(dev)) check since the former can never be true if the latter is false. - Christian Brauner : - Place (dev->power.wakeup && dev->power.wakeup->dev) check under CONFIG_PM_SLEEP ifdefine since it will wakeup_source will only be available when this config option is set. --- drivers/base/core.c | 4 ++++ drivers/base/power/power.h | 2 ++ drivers/base/power/sysfs.c | 40 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 46 insertions(+) diff --git a/drivers/base/core.c b/drivers/base/core.c index 915766c20a47..74ca07f9eb2b 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -3515,6 +3515,10 @@ int device_change_owner(struct device *dev) if (error) goto out; + error = dpm_sysfs_change_owner(dev); + if (error) + goto out; + #ifdef CONFIG_BLOCK if (sysfs_deprecated && dev->class == &block_class) goto out; diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h index 444f5c169a0b..f68490d0811b 100644 --- a/drivers/base/power/power.h +++ b/drivers/base/power/power.h @@ -74,6 +74,7 @@ extern int pm_qos_sysfs_add_flags(struct device *dev); extern void pm_qos_sysfs_remove_flags(struct device *dev); extern int pm_qos_sysfs_add_latency_tolerance(struct device *dev); extern void pm_qos_sysfs_remove_latency_tolerance(struct device *dev); +extern int dpm_sysfs_change_owner(struct device *dev); #else /* CONFIG_PM */ @@ -88,6 +89,7 @@ static inline void pm_runtime_remove(struct device *dev) {} static inline int dpm_sysfs_add(struct device *dev) { return 0; } static inline void dpm_sysfs_remove(struct device *dev) {} +static inline int dpm_sysfs_change_owner(struct device *dev) { return 0; } #endif diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c index d7d82db2e4bc..a18ceafd921e 100644 --- a/drivers/base/power/sysfs.c +++ b/drivers/base/power/sysfs.c @@ -684,6 +684,46 @@ int dpm_sysfs_add(struct device *dev) return rc; } +int dpm_sysfs_change_owner(struct device *dev) +{ + int rc; + + if (device_pm_not_required(dev)) + return 0; + + rc = sysfs_group_change_owner(&dev->kobj, &pm_attr_group); + if (rc) + return rc; + + if (pm_runtime_callbacks_present(dev)) { + rc = sysfs_group_change_owner(&dev->kobj, + &pm_runtime_attr_group); + if (rc) + return rc; + } + if (device_can_wakeup(dev)) { + rc = sysfs_group_change_owner(&dev->kobj, + &pm_wakeup_attr_group); + if (rc) + return rc; + +#ifdef CONFIG_PM_SLEEP + if (dev->power.wakeup && dev->power.wakeup->dev) { + rc = device_change_owner(dev->power.wakeup->dev); + if (rc) + return rc; + } +#endif + } + if (dev->power.set_latency_tolerance) { + rc = sysfs_group_change_owner(&dev->kobj, + &pm_qos_latency_tolerance_attr_group); + if (rc) + return rc; + } + return 0; +} + int wakeup_sysfs_add(struct device *dev) { return sysfs_merge_group(&dev->kobj, &pm_wakeup_attr_group); From patchwork Mon Feb 17 16:14:34 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Brauner X-Patchwork-Id: 1239364 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=ubuntu.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 48Lpx30p8tz9sRY for ; Tue, 18 Feb 2020 03:15:19 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729256AbgBQQPP (ORCPT ); Mon, 17 Feb 2020 11:15:15 -0500 Received: from youngberry.canonical.com ([91.189.89.112]:49234 "EHLO youngberry.canonical.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727108AbgBQQOt (ORCPT ); Mon, 17 Feb 2020 11:14:49 -0500 Received: from ip5f5bf7ec.dynamic.kabel-deutschland.de ([95.91.247.236] helo=wittgenstein.fritz.box) by youngberry.canonical.com with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1j3j2k-0003Cp-MN; Mon, 17 Feb 2020 16:14:46 +0000 From: Christian Brauner To: "David S. Miller" , Greg Kroah-Hartman , linux-kernel@vger.kernel.org, netdev@vger.kernel.org Cc: "Rafael J. Wysocki" , Pavel Machek , Jakub Kicinski , Eric Dumazet , Stephen Hemminger , linux-pm@vger.kernel.org, Christian Brauner Subject: [PATCH net-next v2 08/10] net-sysfs: add netdev_change_owner() Date: Mon, 17 Feb 2020 17:14:34 +0100 Message-Id: <20200217161436.1748598-9-christian.brauner@ubuntu.com> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20200217161436.1748598-1-christian.brauner@ubuntu.com> References: <20200217161436.1748598-1-christian.brauner@ubuntu.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Add a function to change the owner of a network device when it is moved between network namespaces. Currently, when moving network devices between network namespaces the ownership of the corresponding sysfs entries is not changed. This leads to problems when tools try to operate on the corresponding sysfs files. This leads to a bug whereby a network device that is created in a network namespaces owned by a user namespace will have its corresponding sysfs entry owned by the root user of the corresponding user namespace. If such a network device has to be moved back to the host network namespace the permissions will still be set to the user namespaces. This means unprivileged users can e.g. trigger uevents for such incorrectly owned devices. They can also modify the settings of the device itself. Both of these things are unwanted. For example, workloads will create network devices in the host network namespace. Other tools will then proceed to move such devices between network namespaces owner by other user namespaces. While the ownership of the device itself is updated in net/core/net-sysfs.c:dev_change_net_namespace() the corresponding sysfs entry for the device is not: drwxr-xr-x 5 nobody nobody 0 Jan 25 18:08 . drwxr-xr-x 9 nobody nobody 0 Jan 25 18:08 .. -r--r--r-- 1 nobody nobody 4096 Jan 25 18:09 addr_assign_type -r--r--r-- 1 nobody nobody 4096 Jan 25 18:09 addr_len -r--r--r-- 1 nobody nobody 4096 Jan 25 18:09 address -r--r--r-- 1 nobody nobody 4096 Jan 25 18:09 broadcast -rw-r--r-- 1 nobody nobody 4096 Jan 25 18:09 carrier -r--r--r-- 1 nobody nobody 4096 Jan 25 18:09 carrier_changes -r--r--r-- 1 nobody nobody 4096 Jan 25 18:09 carrier_down_count -r--r--r-- 1 nobody nobody 4096 Jan 25 18:09 carrier_up_count -r--r--r-- 1 nobody nobody 4096 Jan 25 18:09 dev_id -r--r--r-- 1 nobody nobody 4096 Jan 25 18:09 dev_port -r--r--r-- 1 nobody nobody 4096 Jan 25 18:09 dormant -r--r--r-- 1 nobody nobody 4096 Jan 25 18:09 duplex -rw-r--r-- 1 nobody nobody 4096 Jan 25 18:09 flags -rw-r--r-- 1 nobody nobody 4096 Jan 25 18:09 gro_flush_timeout -rw-r--r-- 1 nobody nobody 4096 Jan 25 18:09 ifalias -r--r--r-- 1 nobody nobody 4096 Jan 25 18:09 ifindex -r--r--r-- 1 nobody nobody 4096 Jan 25 18:09 iflink -r--r--r-- 1 nobody nobody 4096 Jan 25 18:09 link_mode -rw-r--r-- 1 nobody nobody 4096 Jan 25 18:09 mtu -r--r--r-- 1 nobody nobody 4096 Jan 25 18:09 name_assign_type -rw-r--r-- 1 nobody nobody 4096 Jan 25 18:09 netdev_group -r--r--r-- 1 nobody nobody 4096 Jan 25 18:09 operstate -r--r--r-- 1 nobody nobody 4096 Jan 25 18:09 phys_port_id -r--r--r-- 1 nobody nobody 4096 Jan 25 18:09 phys_port_name -r--r--r-- 1 nobody nobody 4096 Jan 25 18:09 phys_switch_id drwxr-xr-x 2 nobody nobody 0 Jan 25 18:09 power -rw-r--r-- 1 nobody nobody 4096 Jan 25 18:09 proto_down drwxr-xr-x 4 nobody nobody 0 Jan 25 18:09 queues -r--r--r-- 1 nobody nobody 4096 Jan 25 18:09 speed drwxr-xr-x 2 nobody nobody 0 Jan 25 18:09 statistics lrwxrwxrwx 1 nobody nobody 0 Jan 25 18:08 subsystem -> ../../../../class/net -rw-r--r-- 1 nobody nobody 4096 Jan 25 18:09 tx_queue_len -r--r--r-- 1 nobody nobody 4096 Jan 25 18:09 type -rw-r--r-- 1 nobody nobody 4096 Jan 25 18:08 uevent However, if a device is created directly in the network namespace then the device's sysfs permissions will be correctly updated: drwxr-xr-x 5 root root 0 Jan 25 18:12 . drwxr-xr-x 9 nobody nobody 0 Jan 25 18:08 .. -r--r--r-- 1 root root 4096 Jan 25 18:12 addr_assign_type -r--r--r-- 1 root root 4096 Jan 25 18:12 addr_len -r--r--r-- 1 root root 4096 Jan 25 18:12 address -r--r--r-- 1 root root 4096 Jan 25 18:12 broadcast -rw-r--r-- 1 root root 4096 Jan 25 18:12 carrier -r--r--r-- 1 root root 4096 Jan 25 18:12 carrier_changes -r--r--r-- 1 root root 4096 Jan 25 18:12 carrier_down_count -r--r--r-- 1 root root 4096 Jan 25 18:12 carrier_up_count -r--r--r-- 1 root root 4096 Jan 25 18:12 dev_id -r--r--r-- 1 root root 4096 Jan 25 18:12 dev_port -r--r--r-- 1 root root 4096 Jan 25 18:12 dormant -r--r--r-- 1 root root 4096 Jan 25 18:12 duplex -rw-r--r-- 1 root root 4096 Jan 25 18:12 flags -rw-r--r-- 1 root root 4096 Jan 25 18:12 gro_flush_timeout -rw-r--r-- 1 root root 4096 Jan 25 18:12 ifalias -r--r--r-- 1 root root 4096 Jan 25 18:12 ifindex -r--r--r-- 1 root root 4096 Jan 25 18:12 iflink -r--r--r-- 1 root root 4096 Jan 25 18:12 link_mode -rw-r--r-- 1 root root 4096 Jan 25 18:12 mtu -r--r--r-- 1 root root 4096 Jan 25 18:12 name_assign_type -rw-r--r-- 1 root root 4096 Jan 25 18:12 netdev_group -r--r--r-- 1 root root 4096 Jan 25 18:12 operstate -r--r--r-- 1 root root 4096 Jan 25 18:12 phys_port_id -r--r--r-- 1 root root 4096 Jan 25 18:12 phys_port_name -r--r--r-- 1 root root 4096 Jan 25 18:12 phys_switch_id drwxr-xr-x 2 root root 0 Jan 25 18:12 power -rw-r--r-- 1 root root 4096 Jan 25 18:12 proto_down drwxr-xr-x 4 root root 0 Jan 25 18:12 queues -r--r--r-- 1 root root 4096 Jan 25 18:12 speed drwxr-xr-x 2 root root 0 Jan 25 18:12 statistics lrwxrwxrwx 1 nobody nobody 0 Jan 25 18:12 subsystem -> ../../../../class/net -rw-r--r-- 1 root root 4096 Jan 25 18:12 tx_queue_len -r--r--r-- 1 root root 4096 Jan 25 18:12 type -rw-r--r-- 1 root root 4096 Jan 25 18:12 uevent Now, when creating a network device in a network namespace owned by a user namespace and moving it to the host the permissions will be set to the id that the user namespace root user has been mapped to on the host leading to all sorts of permission issues: 458752 drwxr-xr-x 5 458752 458752 0 Jan 25 18:12 . drwxr-xr-x 9 root root 0 Jan 25 18:08 .. -r--r--r-- 1 458752 458752 4096 Jan 25 18:12 addr_assign_type -r--r--r-- 1 458752 458752 4096 Jan 25 18:12 addr_len -r--r--r-- 1 458752 458752 4096 Jan 25 18:12 address -r--r--r-- 1 458752 458752 4096 Jan 25 18:12 broadcast -rw-r--r-- 1 458752 458752 4096 Jan 25 18:12 carrier -r--r--r-- 1 458752 458752 4096 Jan 25 18:12 carrier_changes -r--r--r-- 1 458752 458752 4096 Jan 25 18:12 carrier_down_count -r--r--r-- 1 458752 458752 4096 Jan 25 18:12 carrier_up_count -r--r--r-- 1 458752 458752 4096 Jan 25 18:12 dev_id -r--r--r-- 1 458752 458752 4096 Jan 25 18:12 dev_port -r--r--r-- 1 458752 458752 4096 Jan 25 18:12 dormant -r--r--r-- 1 458752 458752 4096 Jan 25 18:12 duplex -rw-r--r-- 1 458752 458752 4096 Jan 25 18:12 flags -rw-r--r-- 1 458752 458752 4096 Jan 25 18:12 gro_flush_timeout -rw-r--r-- 1 458752 458752 4096 Jan 25 18:12 ifalias -r--r--r-- 1 458752 458752 4096 Jan 25 18:12 ifindex -r--r--r-- 1 458752 458752 4096 Jan 25 18:12 iflink -r--r--r-- 1 458752 458752 4096 Jan 25 18:12 link_mode -rw-r--r-- 1 458752 458752 4096 Jan 25 18:12 mtu -r--r--r-- 1 458752 458752 4096 Jan 25 18:12 name_assign_type -rw-r--r-- 1 458752 458752 4096 Jan 25 18:12 netdev_group -r--r--r-- 1 458752 458752 4096 Jan 25 18:12 operstate -r--r--r-- 1 458752 458752 4096 Jan 25 18:12 phys_port_id -r--r--r-- 1 458752 458752 4096 Jan 25 18:12 phys_port_name -r--r--r-- 1 458752 458752 4096 Jan 25 18:12 phys_switch_id drwxr-xr-x 2 458752 458752 0 Jan 25 18:12 power -rw-r--r-- 1 458752 458752 4096 Jan 25 18:12 proto_down drwxr-xr-x 4 458752 458752 0 Jan 25 18:12 queues -r--r--r-- 1 458752 458752 4096 Jan 25 18:12 speed drwxr-xr-x 2 458752 458752 0 Jan 25 18:12 statistics lrwxrwxrwx 1 root root 0 Jan 25 18:12 subsystem -> ../../../../class/net -rw-r--r-- 1 458752 458752 4096 Jan 25 18:12 tx_queue_len -r--r--r-- 1 458752 458752 4096 Jan 25 18:12 type -rw-r--r-- 1 458752 458752 4096 Jan 25 18:12 uevent Signed-off-by: Christian Brauner --- /* v2 */ unchanged --- net/core/net-sysfs.c | 27 +++++++++++++++++++++++++++ net/core/net-sysfs.h | 2 ++ 2 files changed, 29 insertions(+) diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 4c826b8bf9b1..4fda021edf6d 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -1767,6 +1767,33 @@ int netdev_register_kobject(struct net_device *ndev) return error; } +/* Change owner for sysfs entries when moving network devices across network + * namespaces owned by different user namespaces. + */ +int netdev_change_owner(struct net_device *ndev, const struct net *net_old, + const struct net *net_new) +{ + struct device *dev = &ndev->dev; + kuid_t old_uid, new_uid; + kgid_t old_gid, new_gid; + int error; + + net_ns_get_ownership(net_old, &old_uid, &old_gid); + net_ns_get_ownership(net_new, &new_uid, &new_gid); + + /* The network namespace was changed but the owning user namespace is + * identical so there's no need to change the owner of sysfs entries. + */ + if (uid_eq(old_uid, new_uid) && gid_eq(old_gid, new_gid)) + return 0; + + error = device_change_owner(dev); + if (error) + return error; + + return 0; +} + int netdev_class_create_file_ns(const struct class_attribute *class_attr, const void *ns) { diff --git a/net/core/net-sysfs.h b/net/core/net-sysfs.h index 006876c7b78d..8a5b04c2699a 100644 --- a/net/core/net-sysfs.h +++ b/net/core/net-sysfs.h @@ -8,5 +8,7 @@ void netdev_unregister_kobject(struct net_device *); int net_rx_queue_update_kobjects(struct net_device *, int old_num, int new_num); int netdev_queue_update_kobjects(struct net_device *net, int old_num, int new_num); +int netdev_change_owner(struct net_device *, const struct net *net_old, + const struct net *net_new); #endif From patchwork Mon Feb 17 16:14:35 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Brauner X-Patchwork-Id: 1239362 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=ubuntu.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 48Lpwn3xDzz9sRf for ; Tue, 18 Feb 2020 03:15:05 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729521AbgBQQOv (ORCPT ); Mon, 17 Feb 2020 11:14:51 -0500 Received: from youngberry.canonical.com ([91.189.89.112]:49250 "EHLO youngberry.canonical.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729056AbgBQQOt (ORCPT ); Mon, 17 Feb 2020 11:14:49 -0500 Received: from ip5f5bf7ec.dynamic.kabel-deutschland.de ([95.91.247.236] helo=wittgenstein.fritz.box) by youngberry.canonical.com with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1j3j2l-0003Cp-Ac; Mon, 17 Feb 2020 16:14:47 +0000 From: Christian Brauner To: "David S. Miller" , Greg Kroah-Hartman , linux-kernel@vger.kernel.org, netdev@vger.kernel.org Cc: "Rafael J. Wysocki" , Pavel Machek , Jakub Kicinski , Eric Dumazet , Stephen Hemminger , linux-pm@vger.kernel.org, Christian Brauner Subject: [PATCH net-next v2 09/10] net-sysfs: add queue_change_owner() Date: Mon, 17 Feb 2020 17:14:35 +0100 Message-Id: <20200217161436.1748598-10-christian.brauner@ubuntu.com> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20200217161436.1748598-1-christian.brauner@ubuntu.com> References: <20200217161436.1748598-1-christian.brauner@ubuntu.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Add a function to change the owner of the queue entries for a network device when it is moved between network namespaces. Currently, when moving network devices between network namespaces the ownership of the corresponding queue sysfs entries are not changed. This leads to problems when tools try to operate on the corresponding sysfs files. Fix this. Signed-off-by: Christian Brauner --- /* v2 */ - kbuild test robot via sparse: - Make net_rx_queue_change_owner() static since it's not exported. --- net/core/net-sysfs.c | 101 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 4fda021edf6d..3f93f996c7a3 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -944,6 +944,22 @@ static int rx_queue_add_kobject(struct net_device *dev, int index) kobject_put(kobj); return error; } + +static int rx_queue_change_owner(struct net_device *dev, int index) +{ + struct netdev_rx_queue *queue = dev->_rx + index; + struct kobject *kobj = &queue->kobj; + int error; + + error = sysfs_change_owner(kobj); + if (error) + return error; + + if (dev->sysfs_rx_queue_group) + error = sysfs_group_change_owner(kobj, dev->sysfs_rx_queue_group); + + return error; +} #endif /* CONFIG_SYSFS */ int @@ -981,6 +997,28 @@ net_rx_queue_update_kobjects(struct net_device *dev, int old_num, int new_num) #endif } +static int net_rx_queue_change_owner(struct net_device *dev, int num) +{ +#ifdef CONFIG_SYSFS + int error = 0; + int i; + +#ifndef CONFIG_RPS + if (!dev->sysfs_rx_queue_group) + return 0; +#endif + for (i = 0; i < num; i++) { + error = rx_queue_change_owner(dev, i); + if (error) + break; + } + + return error; +#else + return 0; +#endif +} + #ifdef CONFIG_SYSFS /* * netdev_queue sysfs structures and functions. @@ -1486,6 +1524,22 @@ static int netdev_queue_add_kobject(struct net_device *dev, int index) kobject_put(kobj); return error; } + +static int tx_queue_change_owner(struct net_device *ndev, int index) +{ + struct netdev_queue *queue = ndev->_tx + index; + struct kobject *kobj = &queue->kobj; + int error; + + error = sysfs_change_owner(kobj); + if (error) + return error; + +#ifdef CONFIG_BQL + error = sysfs_group_change_owner(kobj, &dql_group); +#endif + return error; +} #endif /* CONFIG_SYSFS */ int @@ -1520,6 +1574,24 @@ netdev_queue_update_kobjects(struct net_device *dev, int old_num, int new_num) #endif /* CONFIG_SYSFS */ } +static int net_tx_queue_change_owner(struct net_device *dev, int num) +{ +#ifdef CONFIG_SYSFS + int error = 0; + int i; + + for (i = 0; i < num; i++) { + error = tx_queue_change_owner(dev, i); + if (error) + break; + } + + return error; +#else + return 0; +#endif /* CONFIG_SYSFS */ +} + static int register_queue_kobjects(struct net_device *dev) { int error = 0, txq = 0, rxq = 0, real_rx = 0, real_tx = 0; @@ -1554,6 +1626,31 @@ static int register_queue_kobjects(struct net_device *dev) return error; } +static int queue_change_owner(struct net_device *ndev) +{ + int error = 0, real_rx = 0, real_tx = 0; + +#ifdef CONFIG_SYSFS + if (ndev->queues_kset) { + error = sysfs_change_owner(&ndev->queues_kset->kobj); + if (error) + return error; + } + real_rx = ndev->real_num_rx_queues; +#endif + real_tx = ndev->real_num_tx_queues; + + error = net_rx_queue_change_owner(ndev, real_rx); + if (error) + return error; + + error = net_tx_queue_change_owner(ndev, real_tx); + if (error) + return error; + + return 0; +} + static void remove_queue_kobjects(struct net_device *dev) { int real_rx = 0, real_tx = 0; @@ -1791,6 +1888,10 @@ int netdev_change_owner(struct net_device *ndev, const struct net *net_old, if (error) return error; + error = queue_change_owner(ndev); + if (error) + return error; + return 0; } From patchwork Mon Feb 17 16:14:36 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christian Brauner X-Patchwork-Id: 1239361 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=ubuntu.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 48LpwY2Qp9z9sRf for ; Tue, 18 Feb 2020 03:14:53 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729015AbgBQQOw (ORCPT ); Mon, 17 Feb 2020 11:14:52 -0500 Received: from youngberry.canonical.com ([91.189.89.112]:49255 "EHLO youngberry.canonical.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729271AbgBQQOu (ORCPT ); Mon, 17 Feb 2020 11:14:50 -0500 Received: from ip5f5bf7ec.dynamic.kabel-deutschland.de ([95.91.247.236] helo=wittgenstein.fritz.box) by youngberry.canonical.com with esmtpsa (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1j3j2l-0003Cp-U3; Mon, 17 Feb 2020 16:14:48 +0000 From: Christian Brauner To: "David S. Miller" , Greg Kroah-Hartman , linux-kernel@vger.kernel.org, netdev@vger.kernel.org Cc: "Rafael J. Wysocki" , Pavel Machek , Jakub Kicinski , Eric Dumazet , Stephen Hemminger , linux-pm@vger.kernel.org, Christian Brauner Subject: [PATCH net-next v2 10/10] net: fix sysfs permssions when device changes network namespace Date: Mon, 17 Feb 2020 17:14:36 +0100 Message-Id: <20200217161436.1748598-11-christian.brauner@ubuntu.com> X-Mailer: git-send-email 2.25.0 In-Reply-To: <20200217161436.1748598-1-christian.brauner@ubuntu.com> References: <20200217161436.1748598-1-christian.brauner@ubuntu.com> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Now that we moved all the helpers in place and make use netdev_change_owner() to fixup the permissions when moving network devices between network namespaces. Signed-off-by: Christian Brauner --- /* v2 */ unchanged --- net/core/dev.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/net/core/dev.c b/net/core/dev.c index a69e8bd7ed74..0f9c4684fcbd 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -10016,6 +10016,7 @@ EXPORT_SYMBOL(unregister_netdev); int dev_change_net_namespace(struct net_device *dev, struct net *net, const char *pat) { + struct net *net_old = dev_net(dev); int err, new_nsid, new_ifindex; ASSERT_RTNL(); @@ -10031,7 +10032,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char /* Get out if there is nothing todo */ err = 0; - if (net_eq(dev_net(dev), net)) + if (net_eq(net_old, net)) goto out; /* Pick the destination device name, and ensure @@ -10107,6 +10108,12 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char err = device_rename(&dev->dev, dev->name); WARN_ON(err); + /* Adapt owner in case owning user namespace of target network + * namespace is different from the original one. + */ + err = netdev_change_owner(dev, net_old, net); + WARN_ON(err); + /* Add the device back in the hashes */ list_netdevice(dev);