netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v1 net-next 00/12] ipv4: Convert RTM_{NEW,DEL}ADDR and more to per-netns RTNL.
@ 2024-10-21 18:32 Kuniyuki Iwashima
  2024-10-21 18:32 ` [PATCH v1 net-next 01/12] rtnetlink: Make per-netns RTNL dereference helpers to macro Kuniyuki Iwashima
                   ` (12 more replies)
  0 siblings, 13 replies; 15+ messages in thread
From: Kuniyuki Iwashima @ 2024-10-21 18:32 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	David Ahern
  Cc: Kuniyuki Iwashima, Kuniyuki Iwashima, netdev

The IPv4 address hash table and GC are already namespacified.

This series converts RTM_NEWADDR/RTM_DELADDR and some more
RTNL users to per-netns RTNL.


Changes:
  v2:
    * Add patch 1 to address sparse warning for CONFIG_DEBUG_NET_SMALL_RTNL=n
    * Add Eric's tags to patch 2-12

  v1: https://lore.kernel.org/netdev/20241018012225.90409-1-kuniyu@amazon.com/


Kuniyuki Iwashima (12):
  rtnetlink: Make per-netns RTNL dereference helpers to macro.
  rtnetlink: Define RTNL_FLAG_DOIT_PERNET for per-netns RTNL doit().
  ipv4: Factorise RTM_NEWADDR validation to inet_validate_rtm().
  ipv4: Don't allocate ifa for 0.0.0.0 in inet_rtm_newaddr().
  ipv4: Convert RTM_NEWADDR to per-netns RTNL.
  ipv4: Use per-netns RTNL helpers in inet_rtm_newaddr().
  ipv4: Convert RTM_DELADDR to per-netns RTNL.
  ipv4: Convert check_lifetime() to per-netns RTNL.
  rtnetlink: Define rtnl_net_trylock().
  ipv4: Convert devinet_sysctl_forward() to per-netns RTNL.
  ipv4: Convert devinet_ioctl() to per-netns RTNL except for
    SIOCSIFFLAGS.
  ipv4: Convert devinet_ioctl to per-netns RTNL.

 include/linux/inetdevice.h |   9 ++
 include/linux/rtnetlink.h  |  25 +++--
 include/net/rtnetlink.h    |   1 +
 net/core/dev_ioctl.c       |   6 +-
 net/core/rtnetlink.c       |  11 +++
 net/ipv4/devinet.c         | 190 +++++++++++++++++++++----------------
 6 files changed, 143 insertions(+), 99 deletions(-)

-- 
2.39.5 (Apple Git-154)


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v1 net-next 01/12] rtnetlink: Make per-netns RTNL dereference helpers to macro.
  2024-10-21 18:32 [PATCH v1 net-next 00/12] ipv4: Convert RTM_{NEW,DEL}ADDR and more to per-netns RTNL Kuniyuki Iwashima
@ 2024-10-21 18:32 ` Kuniyuki Iwashima
  2024-10-23 18:58   ` Simon Horman
  2024-10-21 18:32 ` [PATCH v1 net-next 02/12] rtnetlink: Define RTNL_FLAG_DOIT_PERNET for per-netns RTNL doit() Kuniyuki Iwashima
                   ` (11 subsequent siblings)
  12 siblings, 1 reply; 15+ messages in thread
From: Kuniyuki Iwashima @ 2024-10-21 18:32 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	David Ahern
  Cc: Kuniyuki Iwashima, Kuniyuki Iwashima, netdev, kernel test robot

When CONFIG_DEBUG_NET_SMALL_RTNL is off, rtnl_net_dereference() is the
static inline wrapper of rtnl_dereference() returning a plain (void *)
pointer to make sure net is always evaluated as requested in [0].

But, it makes sparse complain [1] when the pointer has __rcu annotation:

  net/ipv4/devinet.c:674:47: sparse: warning: incorrect type in argument 2 (different address spaces)
  net/ipv4/devinet.c:674:47: sparse:    expected void *p
  net/ipv4/devinet.c:674:47: sparse:    got struct in_ifaddr [noderef] __rcu *

Also, if we evaluate net as (void *) in a macro, then the compiler
in turn fails to build due to -Werror=unused-value.

  #define rtnl_net_dereference(net, p)                  \
        ({                                              \
                (void *)net;                            \
                rtnl_dereference(p);                    \
        })

  net/ipv4/devinet.c: In function ‘inet_rtm_deladdr’:
  ./include/linux/rtnetlink.h:154:17: error: statement with no effect [-Werror=unused-value]
    154 |                 (void *)net;                            \
  net/ipv4/devinet.c:674:21: note: in expansion of macro ‘rtnl_net_dereference’
    674 |              (ifa = rtnl_net_dereference(net, *ifap)) != NULL;
        |                     ^~~~~~~~~~~~~~~~~~~~

Let's go back to the original simplest macro.

Note that checkpatch complains about this approach, but it's one-shot and
less noisy than the other two.

  WARNING: Argument 'net' is not used in function-like macro
  #76: FILE: include/linux/rtnetlink.h:142:
  +#define rtnl_net_dereference(net, p)			\
  +	rtnl_dereference(p)

Fixes: 844e5e7e656d ("rtnetlink: Add assertion helpers for per-netns RTNL.")
Link: https://lore.kernel.org/netdev/20241004132145.7fd208e9@kernel.org/ [0]
Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202410200325.SaEJmyZS-lkp@intel.com/ [1]
Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
---
 include/linux/rtnetlink.h | 21 ++++++---------------
 1 file changed, 6 insertions(+), 15 deletions(-)

diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index 8468a4ce8510..0e62918de63b 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -137,21 +137,12 @@ static inline void ASSERT_RTNL_NET(struct net *net)
 	ASSERT_RTNL();
 }
 
-static inline void *rcu_dereference_rtnl_net(struct net *net, void *p)
-{
-	return rcu_dereference_rtnl(p);
-}
-
-static inline void *rtnl_net_dereference(struct net *net, void *p)
-{
-	return rtnl_dereference(p);
-}
-
-static inline void *rcu_replace_pointer_rtnl_net(struct net *net,
-						 void *rp, void *p)
-{
-	return rcu_replace_pointer_rtnl(rp, p);
-}
+#define rcu_dereference_rtnl_net(net, p)		\
+	rcu_dereference_rtnl(p)
+#define rtnl_net_dereference(net, p)			\
+	rtnl_dereference(p)
+#define rcu_replace_pointer_rtnl_net(net, rp, p)	\
+	rcu_replace_pointer_rtnl(rp, p)
 #endif
 
 static inline struct netdev_queue *dev_ingress_queue(struct net_device *dev)
-- 
2.39.5 (Apple Git-154)


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v1 net-next 02/12] rtnetlink: Define RTNL_FLAG_DOIT_PERNET for per-netns RTNL doit().
  2024-10-21 18:32 [PATCH v1 net-next 00/12] ipv4: Convert RTM_{NEW,DEL}ADDR and more to per-netns RTNL Kuniyuki Iwashima
  2024-10-21 18:32 ` [PATCH v1 net-next 01/12] rtnetlink: Make per-netns RTNL dereference helpers to macro Kuniyuki Iwashima
@ 2024-10-21 18:32 ` Kuniyuki Iwashima
  2024-10-21 18:32 ` [PATCH v1 net-next 03/12] ipv4: Factorise RTM_NEWADDR validation to inet_validate_rtm() Kuniyuki Iwashima
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: Kuniyuki Iwashima @ 2024-10-21 18:32 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	David Ahern
  Cc: Kuniyuki Iwashima, Kuniyuki Iwashima, netdev

We will push RTNL down to each doit() as rtnl_net_lock().

We can use RTNL_FLAG_DOIT_UNLOCKED to call doit() without RTNL, but doit()
will still hold RTNL.

Let's define RTNL_FLAG_DOIT_PERNET as an alias of RTNL_FLAG_DOIT_UNLOCKED.

Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
---
 include/net/rtnetlink.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h
index bb49c5708ce7..3fa9da93364b 100644
--- a/include/net/rtnetlink.h
+++ b/include/net/rtnetlink.h
@@ -11,6 +11,7 @@ typedef int (*rtnl_dumpit_func)(struct sk_buff *, struct netlink_callback *);
 
 enum rtnl_link_flags {
 	RTNL_FLAG_DOIT_UNLOCKED		= BIT(0),
+#define RTNL_FLAG_DOIT_PERNET		RTNL_FLAG_DOIT_UNLOCKED
 	RTNL_FLAG_BULK_DEL_SUPPORTED	= BIT(1),
 	RTNL_FLAG_DUMP_UNLOCKED		= BIT(2),
 	RTNL_FLAG_DUMP_SPLIT_NLM_DONE	= BIT(3),	/* legacy behavior */
-- 
2.39.5 (Apple Git-154)


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v1 net-next 03/12] ipv4: Factorise RTM_NEWADDR validation to inet_validate_rtm().
  2024-10-21 18:32 [PATCH v1 net-next 00/12] ipv4: Convert RTM_{NEW,DEL}ADDR and more to per-netns RTNL Kuniyuki Iwashima
  2024-10-21 18:32 ` [PATCH v1 net-next 01/12] rtnetlink: Make per-netns RTNL dereference helpers to macro Kuniyuki Iwashima
  2024-10-21 18:32 ` [PATCH v1 net-next 02/12] rtnetlink: Define RTNL_FLAG_DOIT_PERNET for per-netns RTNL doit() Kuniyuki Iwashima
@ 2024-10-21 18:32 ` Kuniyuki Iwashima
  2024-10-21 18:32 ` [PATCH v1 net-next 04/12] ipv4: Don't allocate ifa for 0.0.0.0 in inet_rtm_newaddr() Kuniyuki Iwashima
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: Kuniyuki Iwashima @ 2024-10-21 18:32 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	David Ahern
  Cc: Kuniyuki Iwashima, Kuniyuki Iwashima, netdev

rtm_to_ifaddr() validates some attributes, looks up a netdev,
allocates struct in_ifaddr, and validates IFA_CACHEINFO.

There is no reason to delay IFA_CACHEINFO validation.

We will push RTNL down to inet_rtm_newaddr(), and then we want
to complete rtnetlink validation before rtnl_net_lock().

Let's factorise the validation parts.

Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
---
 net/ipv4/devinet.c | 79 ++++++++++++++++++++++++++--------------------
 1 file changed, 44 insertions(+), 35 deletions(-)

diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index ec29ead83e74..24af01fcb414 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -846,35 +846,54 @@ static void set_ifa_lifetime(struct in_ifaddr *ifa, __u32 valid_lft,
 		WRITE_ONCE(ifa->ifa_cstamp, ifa->ifa_tstamp);
 }
 
-static struct in_ifaddr *rtm_to_ifaddr(struct net *net, struct nlmsghdr *nlh,
-				       __u32 *pvalid_lft, __u32 *pprefered_lft,
-				       struct netlink_ext_ack *extack)
+static int inet_validate_rtm(struct nlmsghdr *nlh, struct nlattr **tb,
+			     struct netlink_ext_ack *extack,
+			     __u32 *valid_lft, __u32 *prefered_lft)
 {
-	struct nlattr *tb[IFA_MAX+1];
-	struct in_ifaddr *ifa;
-	struct ifaddrmsg *ifm;
-	struct net_device *dev;
-	struct in_device *in_dev;
+	struct ifaddrmsg *ifm = nlmsg_data(nlh);
 	int err;
 
 	err = nlmsg_parse_deprecated(nlh, sizeof(*ifm), tb, IFA_MAX,
 				     ifa_ipv4_policy, extack);
 	if (err < 0)
-		goto errout;
-
-	ifm = nlmsg_data(nlh);
-	err = -EINVAL;
+		return err;
 
 	if (ifm->ifa_prefixlen > 32) {
 		NL_SET_ERR_MSG(extack, "ipv4: Invalid prefix length");
-		goto errout;
+		return -EINVAL;
 	}
 
 	if (!tb[IFA_LOCAL]) {
 		NL_SET_ERR_MSG(extack, "ipv4: Local address is not supplied");
-		goto errout;
+		return -EINVAL;
 	}
 
+	if (tb[IFA_CACHEINFO]) {
+		struct ifa_cacheinfo *ci;
+
+		ci = nla_data(tb[IFA_CACHEINFO]);
+		if (!ci->ifa_valid || ci->ifa_prefered > ci->ifa_valid) {
+			NL_SET_ERR_MSG(extack, "ipv4: address lifetime invalid");
+			return -EINVAL;
+		}
+
+		*valid_lft = ci->ifa_valid;
+		*prefered_lft = ci->ifa_prefered;
+	}
+
+	return 0;
+}
+
+static struct in_ifaddr *inet_rtm_to_ifa(struct net *net, struct nlmsghdr *nlh,
+					 struct nlattr **tb,
+					 struct netlink_ext_ack *extack)
+{
+	struct ifaddrmsg *ifm = nlmsg_data(nlh);
+	struct in_device *in_dev;
+	struct net_device *dev;
+	struct in_ifaddr *ifa;
+	int err;
+
 	dev = __dev_get_by_index(net, ifm->ifa_index);
 	err = -ENODEV;
 	if (!dev) {
@@ -923,23 +942,8 @@ static struct in_ifaddr *rtm_to_ifaddr(struct net *net, struct nlmsghdr *nlh,
 	if (tb[IFA_PROTO])
 		ifa->ifa_proto = nla_get_u8(tb[IFA_PROTO]);
 
-	if (tb[IFA_CACHEINFO]) {
-		struct ifa_cacheinfo *ci;
-
-		ci = nla_data(tb[IFA_CACHEINFO]);
-		if (!ci->ifa_valid || ci->ifa_prefered > ci->ifa_valid) {
-			NL_SET_ERR_MSG(extack, "ipv4: address lifetime invalid");
-			err = -EINVAL;
-			goto errout_free;
-		}
-		*pvalid_lft = ci->ifa_valid;
-		*pprefered_lft = ci->ifa_prefered;
-	}
-
 	return ifa;
 
-errout_free:
-	inet_free_ifa(ifa);
 errout:
 	return ERR_PTR(err);
 }
@@ -964,15 +968,21 @@ static struct in_ifaddr *find_matching_ifa(struct in_ifaddr *ifa)
 static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh,
 			    struct netlink_ext_ack *extack)
 {
+	__u32 prefered_lft = INFINITY_LIFE_TIME;
+	__u32 valid_lft = INFINITY_LIFE_TIME;
 	struct net *net = sock_net(skb->sk);
-	struct in_ifaddr *ifa;
 	struct in_ifaddr *ifa_existing;
-	__u32 valid_lft = INFINITY_LIFE_TIME;
-	__u32 prefered_lft = INFINITY_LIFE_TIME;
+	struct nlattr *tb[IFA_MAX + 1];
+	struct in_ifaddr *ifa;
+	int ret;
 
 	ASSERT_RTNL();
 
-	ifa = rtm_to_ifaddr(net, nlh, &valid_lft, &prefered_lft, extack);
+	ret = inet_validate_rtm(nlh, tb, extack, &valid_lft, &prefered_lft);
+	if (ret < 0)
+		return ret;
+
+	ifa = inet_rtm_to_ifa(net, nlh, tb, extack);
 	if (IS_ERR(ifa))
 		return PTR_ERR(ifa);
 
@@ -983,8 +993,7 @@ static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh,
 		 */
 		set_ifa_lifetime(ifa, valid_lft, prefered_lft);
 		if (ifa->ifa_flags & IFA_F_MCAUTOJOIN) {
-			int ret = ip_mc_autojoin_config(net, true, ifa);
-
+			ret = ip_mc_autojoin_config(net, true, ifa);
 			if (ret < 0) {
 				NL_SET_ERR_MSG(extack, "ipv4: Multicast auto join failed");
 				inet_free_ifa(ifa);
-- 
2.39.5 (Apple Git-154)


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v1 net-next 04/12] ipv4: Don't allocate ifa for 0.0.0.0 in inet_rtm_newaddr().
  2024-10-21 18:32 [PATCH v1 net-next 00/12] ipv4: Convert RTM_{NEW,DEL}ADDR and more to per-netns RTNL Kuniyuki Iwashima
                   ` (2 preceding siblings ...)
  2024-10-21 18:32 ` [PATCH v1 net-next 03/12] ipv4: Factorise RTM_NEWADDR validation to inet_validate_rtm() Kuniyuki Iwashima
@ 2024-10-21 18:32 ` Kuniyuki Iwashima
  2024-10-21 18:32 ` [PATCH v1 net-next 05/12] ipv4: Convert RTM_NEWADDR to per-netns RTNL Kuniyuki Iwashima
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: Kuniyuki Iwashima @ 2024-10-21 18:32 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	David Ahern
  Cc: Kuniyuki Iwashima, Kuniyuki Iwashima, netdev

When we pass 0.0.0.0 to __inet_insert_ifa(), it frees ifa and returns 0.

We can do this check much earlier for RTM_NEWADDR even before allocating
struct in_ifaddr.

Let's move the validation to

  1. inet_insert_ifa() for ioctl()
  2. inet_rtm_newaddr() for RTM_NEWADDR

Now, we can remove the same check in find_matching_ifa().

Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
---
 net/ipv4/devinet.c | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 24af01fcb414..5e43f9f68e4a 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -508,11 +508,6 @@ static int __inet_insert_ifa(struct in_ifaddr *ifa, struct nlmsghdr *nlh,
 
 	ASSERT_RTNL();
 
-	if (!ifa->ifa_local) {
-		inet_free_ifa(ifa);
-		return 0;
-	}
-
 	ifa->ifa_flags &= ~IFA_F_SECONDARY;
 	last_primary = &in_dev->ifa_list;
 
@@ -584,6 +579,11 @@ static int __inet_insert_ifa(struct in_ifaddr *ifa, struct nlmsghdr *nlh,
 
 static int inet_insert_ifa(struct in_ifaddr *ifa)
 {
+	if (!ifa->ifa_local) {
+		inet_free_ifa(ifa);
+		return 0;
+	}
+
 	return __inet_insert_ifa(ifa, NULL, 0, NULL);
 }
 
@@ -953,15 +953,13 @@ static struct in_ifaddr *find_matching_ifa(struct in_ifaddr *ifa)
 	struct in_device *in_dev = ifa->ifa_dev;
 	struct in_ifaddr *ifa1;
 
-	if (!ifa->ifa_local)
-		return NULL;
-
 	in_dev_for_each_ifa_rtnl(ifa1, in_dev) {
 		if (ifa1->ifa_mask == ifa->ifa_mask &&
 		    inet_ifa_match(ifa1->ifa_address, ifa) &&
 		    ifa1->ifa_local == ifa->ifa_local)
 			return ifa1;
 	}
+
 	return NULL;
 }
 
@@ -982,6 +980,9 @@ static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh,
 	if (ret < 0)
 		return ret;
 
+	if (!nla_get_in_addr(tb[IFA_LOCAL]))
+		return 0;
+
 	ifa = inet_rtm_to_ifa(net, nlh, tb, extack);
 	if (IS_ERR(ifa))
 		return PTR_ERR(ifa);
-- 
2.39.5 (Apple Git-154)


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v1 net-next 05/12] ipv4: Convert RTM_NEWADDR to per-netns RTNL.
  2024-10-21 18:32 [PATCH v1 net-next 00/12] ipv4: Convert RTM_{NEW,DEL}ADDR and more to per-netns RTNL Kuniyuki Iwashima
                   ` (3 preceding siblings ...)
  2024-10-21 18:32 ` [PATCH v1 net-next 04/12] ipv4: Don't allocate ifa for 0.0.0.0 in inet_rtm_newaddr() Kuniyuki Iwashima
@ 2024-10-21 18:32 ` Kuniyuki Iwashima
  2024-10-21 18:32 ` [PATCH v1 net-next 06/12] ipv4: Use per-netns RTNL helpers in inet_rtm_newaddr() Kuniyuki Iwashima
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: Kuniyuki Iwashima @ 2024-10-21 18:32 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	David Ahern
  Cc: Kuniyuki Iwashima, Kuniyuki Iwashima, netdev

The address hash table and GC are already namespacified.

Let's push down RTNL into inet_rtm_newaddr() as rtnl_net_lock().

Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
---
 net/ipv4/devinet.c | 28 ++++++++++++++++++----------
 1 file changed, 18 insertions(+), 10 deletions(-)

diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 5e43f9f68e4a..d5050c1bf157 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -974,8 +974,6 @@ static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh,
 	struct in_ifaddr *ifa;
 	int ret;
 
-	ASSERT_RTNL();
-
 	ret = inet_validate_rtm(nlh, tb, extack, &valid_lft, &prefered_lft);
 	if (ret < 0)
 		return ret;
@@ -983,9 +981,13 @@ static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh,
 	if (!nla_get_in_addr(tb[IFA_LOCAL]))
 		return 0;
 
+	rtnl_net_lock(net);
+
 	ifa = inet_rtm_to_ifa(net, nlh, tb, extack);
-	if (IS_ERR(ifa))
-		return PTR_ERR(ifa);
+	if (IS_ERR(ifa)) {
+		ret = PTR_ERR(ifa);
+		goto unlock;
+	}
 
 	ifa_existing = find_matching_ifa(ifa);
 	if (!ifa_existing) {
@@ -998,11 +1000,11 @@ static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh,
 			if (ret < 0) {
 				NL_SET_ERR_MSG(extack, "ipv4: Multicast auto join failed");
 				inet_free_ifa(ifa);
-				return ret;
+				goto unlock;
 			}
 		}
-		return __inet_insert_ifa(ifa, nlh, NETLINK_CB(skb).portid,
-					 extack);
+
+		ret = __inet_insert_ifa(ifa, nlh, NETLINK_CB(skb).portid, extack);
 	} else {
 		u32 new_metric = ifa->ifa_rt_priority;
 		u8 new_proto = ifa->ifa_proto;
@@ -1012,7 +1014,8 @@ static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh,
 		if (nlh->nlmsg_flags & NLM_F_EXCL ||
 		    !(nlh->nlmsg_flags & NLM_F_REPLACE)) {
 			NL_SET_ERR_MSG(extack, "ipv4: Address already assigned");
-			return -EEXIST;
+			ret = -EEXIST;
+			goto unlock;
 		}
 		ifa = ifa_existing;
 
@@ -1029,7 +1032,11 @@ static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh,
 				   &net->ipv4.addr_chk_work, 0);
 		rtmsg_ifa(RTM_NEWADDR, ifa, nlh, NETLINK_CB(skb).portid);
 	}
-	return 0;
+
+unlock:
+	rtnl_net_unlock(net);
+
+	return ret;
 }
 
 /*
@@ -2823,7 +2830,8 @@ static struct rtnl_af_ops inet_af_ops __read_mostly = {
 };
 
 static const struct rtnl_msg_handler devinet_rtnl_msg_handlers[] __initconst = {
-	{.protocol = PF_INET, .msgtype = RTM_NEWADDR, .doit = inet_rtm_newaddr},
+	{.protocol = PF_INET, .msgtype = RTM_NEWADDR, .doit = inet_rtm_newaddr,
+	 .flags = RTNL_FLAG_DOIT_PERNET},
 	{.protocol = PF_INET, .msgtype = RTM_DELADDR, .doit = inet_rtm_deladdr},
 	{.protocol = PF_INET, .msgtype = RTM_GETADDR, .dumpit = inet_dump_ifaddr,
 	 .flags = RTNL_FLAG_DUMP_UNLOCKED | RTNL_FLAG_DUMP_SPLIT_NLM_DONE},
-- 
2.39.5 (Apple Git-154)


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v1 net-next 06/12] ipv4: Use per-netns RTNL helpers in inet_rtm_newaddr().
  2024-10-21 18:32 [PATCH v1 net-next 00/12] ipv4: Convert RTM_{NEW,DEL}ADDR and more to per-netns RTNL Kuniyuki Iwashima
                   ` (4 preceding siblings ...)
  2024-10-21 18:32 ` [PATCH v1 net-next 05/12] ipv4: Convert RTM_NEWADDR to per-netns RTNL Kuniyuki Iwashima
@ 2024-10-21 18:32 ` Kuniyuki Iwashima
  2024-10-21 18:32 ` [PATCH v1 net-next 07/12] ipv4: Convert RTM_DELADDR to per-netns RTNL Kuniyuki Iwashima
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: Kuniyuki Iwashima @ 2024-10-21 18:32 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	David Ahern
  Cc: Kuniyuki Iwashima, Kuniyuki Iwashima, netdev

inet_rtm_to_ifa() and find_matching_ifa() are called
under rtnl_net_lock().

__in_dev_get_rtnl() and in_dev_for_each_ifa_rtnl() there
can use per-netns RTNL helpers.

Let's define and use __in_dev_get_rtnl_net() and
in_dev_for_each_ifa_rtnl_net().

Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
---
 include/linux/inetdevice.h | 9 +++++++++
 net/ipv4/devinet.c         | 8 ++++----
 2 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/include/linux/inetdevice.h b/include/linux/inetdevice.h
index d9c690c8c80b..5730ba6b1cfa 100644
--- a/include/linux/inetdevice.h
+++ b/include/linux/inetdevice.h
@@ -226,6 +226,10 @@ static __inline__ bool bad_mask(__be32 mask, __be32 addr)
 	for (ifa = rtnl_dereference((in_dev)->ifa_list); ifa;	\
 	     ifa = rtnl_dereference(ifa->ifa_next))
 
+#define in_dev_for_each_ifa_rtnl_net(net, ifa, in_dev)			\
+	for (ifa = rtnl_net_dereference(net, (in_dev)->ifa_list); ifa;	\
+	     ifa = rtnl_net_dereference(net, ifa->ifa_next))
+
 #define in_dev_for_each_ifa_rcu(ifa, in_dev)			\
 	for (ifa = rcu_dereference((in_dev)->ifa_list); ifa;	\
 	     ifa = rcu_dereference(ifa->ifa_next))
@@ -252,6 +256,11 @@ static inline struct in_device *__in_dev_get_rtnl(const struct net_device *dev)
 	return rtnl_dereference(dev->ip_ptr);
 }
 
+static inline struct in_device *__in_dev_get_rtnl_net(const struct net_device *dev)
+{
+	return rtnl_net_dereference(dev_net(dev), dev->ip_ptr);
+}
+
 /* called with rcu_read_lock or rtnl held */
 static inline bool ip_ignore_linkdown(const struct net_device *dev)
 {
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index d5050c1bf157..96f6592740c6 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -901,7 +901,7 @@ static struct in_ifaddr *inet_rtm_to_ifa(struct net *net, struct nlmsghdr *nlh,
 		goto errout;
 	}
 
-	in_dev = __in_dev_get_rtnl(dev);
+	in_dev = __in_dev_get_rtnl_net(dev);
 	err = -ENOBUFS;
 	if (!in_dev)
 		goto errout;
@@ -948,12 +948,12 @@ static struct in_ifaddr *inet_rtm_to_ifa(struct net *net, struct nlmsghdr *nlh,
 	return ERR_PTR(err);
 }
 
-static struct in_ifaddr *find_matching_ifa(struct in_ifaddr *ifa)
+static struct in_ifaddr *find_matching_ifa(struct net *net, struct in_ifaddr *ifa)
 {
 	struct in_device *in_dev = ifa->ifa_dev;
 	struct in_ifaddr *ifa1;
 
-	in_dev_for_each_ifa_rtnl(ifa1, in_dev) {
+	in_dev_for_each_ifa_rtnl_net(net, ifa1, in_dev) {
 		if (ifa1->ifa_mask == ifa->ifa_mask &&
 		    inet_ifa_match(ifa1->ifa_address, ifa) &&
 		    ifa1->ifa_local == ifa->ifa_local)
@@ -989,7 +989,7 @@ static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh,
 		goto unlock;
 	}
 
-	ifa_existing = find_matching_ifa(ifa);
+	ifa_existing = find_matching_ifa(net, ifa);
 	if (!ifa_existing) {
 		/* It would be best to check for !NLM_F_CREATE here but
 		 * userspace already relies on not having to provide this.
-- 
2.39.5 (Apple Git-154)


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v1 net-next 07/12] ipv4: Convert RTM_DELADDR to per-netns RTNL.
  2024-10-21 18:32 [PATCH v1 net-next 00/12] ipv4: Convert RTM_{NEW,DEL}ADDR and more to per-netns RTNL Kuniyuki Iwashima
                   ` (5 preceding siblings ...)
  2024-10-21 18:32 ` [PATCH v1 net-next 06/12] ipv4: Use per-netns RTNL helpers in inet_rtm_newaddr() Kuniyuki Iwashima
@ 2024-10-21 18:32 ` Kuniyuki Iwashima
  2024-10-21 18:32 ` [PATCH v1 net-next 08/12] ipv4: Convert check_lifetime() " Kuniyuki Iwashima
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: Kuniyuki Iwashima @ 2024-10-21 18:32 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	David Ahern
  Cc: Kuniyuki Iwashima, Kuniyuki Iwashima, netdev

Let's push down RTNL into inet_rtm_deladdr() as rtnl_net_lock().

Now, ip_mc_autojoin_config() is always called under per-netns RTNL,
so ASSERT_RTNL() can be replaced with ASSERT_RTNL_NET().

Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
---
 net/ipv4/devinet.c | 24 +++++++++++++++---------
 1 file changed, 15 insertions(+), 9 deletions(-)

diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 96f6592740c6..db56c1e16f65 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -645,7 +645,7 @@ static int ip_mc_autojoin_config(struct net *net, bool join,
 	struct sock *sk = net->ipv4.mc_autojoin_sk;
 	int ret;
 
-	ASSERT_RTNL();
+	ASSERT_RTNL_NET(net);
 
 	lock_sock(sk);
 	if (join)
@@ -671,22 +671,24 @@ static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh,
 	struct in_ifaddr *ifa;
 	int err;
 
-	ASSERT_RTNL();
-
 	err = nlmsg_parse_deprecated(nlh, sizeof(*ifm), tb, IFA_MAX,
 				     ifa_ipv4_policy, extack);
 	if (err < 0)
-		goto errout;
+		goto out;
 
 	ifm = nlmsg_data(nlh);
+
+	rtnl_net_lock(net);
+
 	in_dev = inetdev_by_index(net, ifm->ifa_index);
 	if (!in_dev) {
 		NL_SET_ERR_MSG(extack, "ipv4: Device not found");
 		err = -ENODEV;
-		goto errout;
+		goto unlock;
 	}
 
-	for (ifap = &in_dev->ifa_list; (ifa = rtnl_dereference(*ifap)) != NULL;
+	for (ifap = &in_dev->ifa_list;
+	     (ifa = rtnl_net_dereference(net, *ifap)) != NULL;
 	     ifap = &ifa->ifa_next) {
 		if (tb[IFA_LOCAL] &&
 		    ifa->ifa_local != nla_get_in_addr(tb[IFA_LOCAL]))
@@ -702,13 +704,16 @@ static int inet_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh,
 
 		if (ipv4_is_multicast(ifa->ifa_address))
 			ip_mc_autojoin_config(net, false, ifa);
+
 		__inet_del_ifa(in_dev, ifap, 1, nlh, NETLINK_CB(skb).portid);
-		return 0;
+		goto unlock;
 	}
 
 	NL_SET_ERR_MSG(extack, "ipv4: Address not found");
 	err = -EADDRNOTAVAIL;
-errout:
+unlock:
+	rtnl_net_unlock(net);
+out:
 	return err;
 }
 
@@ -2832,7 +2837,8 @@ static struct rtnl_af_ops inet_af_ops __read_mostly = {
 static const struct rtnl_msg_handler devinet_rtnl_msg_handlers[] __initconst = {
 	{.protocol = PF_INET, .msgtype = RTM_NEWADDR, .doit = inet_rtm_newaddr,
 	 .flags = RTNL_FLAG_DOIT_PERNET},
-	{.protocol = PF_INET, .msgtype = RTM_DELADDR, .doit = inet_rtm_deladdr},
+	{.protocol = PF_INET, .msgtype = RTM_DELADDR, .doit = inet_rtm_deladdr,
+	 .flags = RTNL_FLAG_DOIT_PERNET},
 	{.protocol = PF_INET, .msgtype = RTM_GETADDR, .dumpit = inet_dump_ifaddr,
 	 .flags = RTNL_FLAG_DUMP_UNLOCKED | RTNL_FLAG_DUMP_SPLIT_NLM_DONE},
 	{.protocol = PF_INET, .msgtype = RTM_GETNETCONF,
-- 
2.39.5 (Apple Git-154)


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v1 net-next 08/12] ipv4: Convert check_lifetime() to per-netns RTNL.
  2024-10-21 18:32 [PATCH v1 net-next 00/12] ipv4: Convert RTM_{NEW,DEL}ADDR and more to per-netns RTNL Kuniyuki Iwashima
                   ` (6 preceding siblings ...)
  2024-10-21 18:32 ` [PATCH v1 net-next 07/12] ipv4: Convert RTM_DELADDR to per-netns RTNL Kuniyuki Iwashima
@ 2024-10-21 18:32 ` Kuniyuki Iwashima
  2024-10-21 18:32 ` [PATCH v1 net-next 09/12] rtnetlink: Define rtnl_net_trylock() Kuniyuki Iwashima
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: Kuniyuki Iwashima @ 2024-10-21 18:32 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	David Ahern
  Cc: Kuniyuki Iwashima, Kuniyuki Iwashima, netdev

Since commit 1675f385213e ("ipv4: Namespacify IPv4 address GC."),
check_lifetime() works on a per-netns basis.

Let's use rtnl_net_lock() and rtnl_net_dereference().

Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
---
 net/ipv4/devinet.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index db56c1e16f65..260df53ff342 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -771,7 +771,8 @@ static void check_lifetime(struct work_struct *work)
 		rcu_read_unlock();
 		if (!change_needed)
 			continue;
-		rtnl_lock();
+
+		rtnl_net_lock(net);
 		hlist_for_each_entry_safe(ifa, n, head, addr_lst) {
 			unsigned long age;
 
@@ -788,7 +789,7 @@ static void check_lifetime(struct work_struct *work)
 				struct in_ifaddr *tmp;
 
 				ifap = &ifa->ifa_dev->ifa_list;
-				tmp = rtnl_dereference(*ifap);
+				tmp = rtnl_net_dereference(net, *ifap);
 				while (tmp) {
 					if (tmp == ifa) {
 						inet_del_ifa(ifa->ifa_dev,
@@ -796,7 +797,7 @@ static void check_lifetime(struct work_struct *work)
 						break;
 					}
 					ifap = &tmp->ifa_next;
-					tmp = rtnl_dereference(*ifap);
+					tmp = rtnl_net_dereference(net, *ifap);
 				}
 			} else if (ifa->ifa_preferred_lft !=
 				   INFINITY_LIFE_TIME &&
@@ -806,7 +807,7 @@ static void check_lifetime(struct work_struct *work)
 				rtmsg_ifa(RTM_NEWADDR, ifa, NULL, 0);
 			}
 		}
-		rtnl_unlock();
+		rtnl_net_unlock(net);
 	}
 
 	next_sec = round_jiffies_up(next);
-- 
2.39.5 (Apple Git-154)


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v1 net-next 09/12] rtnetlink: Define rtnl_net_trylock().
  2024-10-21 18:32 [PATCH v1 net-next 00/12] ipv4: Convert RTM_{NEW,DEL}ADDR and more to per-netns RTNL Kuniyuki Iwashima
                   ` (7 preceding siblings ...)
  2024-10-21 18:32 ` [PATCH v1 net-next 08/12] ipv4: Convert check_lifetime() " Kuniyuki Iwashima
@ 2024-10-21 18:32 ` Kuniyuki Iwashima
  2024-10-21 18:32 ` [PATCH v1 net-next 10/12] ipv4: Convert devinet_sysctl_forward() to per-netns RTNL Kuniyuki Iwashima
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: Kuniyuki Iwashima @ 2024-10-21 18:32 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	David Ahern
  Cc: Kuniyuki Iwashima, Kuniyuki Iwashima, netdev

We will need the per-netns version of rtnl_trylock().

rtnl_net_trylock() calls __rtnl_net_lock() only when rtnl_trylock()
successfully holds RTNL.

When RTNL is removed, we will use mutex_trylock() for per-netns RTNL.

Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
---
 include/linux/rtnetlink.h |  6 ++++++
 net/core/rtnetlink.c      | 11 +++++++++++
 2 files changed, 17 insertions(+)

diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index 0e62918de63b..14b88f551920 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -101,6 +101,7 @@ void __rtnl_net_lock(struct net *net);
 void __rtnl_net_unlock(struct net *net);
 void rtnl_net_lock(struct net *net);
 void rtnl_net_unlock(struct net *net);
+int rtnl_net_trylock(struct net *net);
 int rtnl_net_lock_cmp_fn(const struct lockdep_map *a, const struct lockdep_map *b);
 
 bool rtnl_net_is_locked(struct net *net);
@@ -132,6 +133,11 @@ static inline void rtnl_net_unlock(struct net *net)
 	rtnl_unlock();
 }
 
+static inline int rtnl_net_trylock(struct net *net)
+{
+	return rtnl_trylock();
+}
+
 static inline void ASSERT_RTNL_NET(struct net *net)
 {
 	ASSERT_RTNL();
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index a9c92392fb1d..bb4927da0275 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -210,6 +210,17 @@ void rtnl_net_unlock(struct net *net)
 }
 EXPORT_SYMBOL(rtnl_net_unlock);
 
+int rtnl_net_trylock(struct net *net)
+{
+	int ret = rtnl_trylock();
+
+	if (ret)
+		__rtnl_net_lock(net);
+
+	return ret;
+}
+EXPORT_SYMBOL(rtnl_net_trylock);
+
 static int rtnl_net_cmp_locks(const struct net *net_a, const struct net *net_b)
 {
 	if (net_eq(net_a, net_b))
-- 
2.39.5 (Apple Git-154)


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v1 net-next 10/12] ipv4: Convert devinet_sysctl_forward() to per-netns RTNL.
  2024-10-21 18:32 [PATCH v1 net-next 00/12] ipv4: Convert RTM_{NEW,DEL}ADDR and more to per-netns RTNL Kuniyuki Iwashima
                   ` (8 preceding siblings ...)
  2024-10-21 18:32 ` [PATCH v1 net-next 09/12] rtnetlink: Define rtnl_net_trylock() Kuniyuki Iwashima
@ 2024-10-21 18:32 ` Kuniyuki Iwashima
  2024-10-21 18:32 ` [PATCH v1 net-next 11/12] ipv4: Convert devinet_ioctl() to per-netns RTNL except for SIOCSIFFLAGS Kuniyuki Iwashima
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 15+ messages in thread
From: Kuniyuki Iwashima @ 2024-10-21 18:32 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	David Ahern
  Cc: Kuniyuki Iwashima, Kuniyuki Iwashima, netdev

devinet_sysctl_forward() touches only a single netns.

Let's use rtnl_trylock() and __in_dev_get_rtnl_net().

Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
---
 net/ipv4/devinet.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 260df53ff342..dcfc060694fa 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -2395,7 +2395,7 @@ static void inet_forward_change(struct net *net)
 		if (on)
 			dev_disable_lro(dev);
 
-		in_dev = __in_dev_get_rtnl(dev);
+		in_dev = __in_dev_get_rtnl_net(dev);
 		if (in_dev) {
 			IN_DEV_CONF_SET(in_dev, FORWARDING, on);
 			inet_netconf_notify_devconf(net, RTM_NEWNETCONF,
@@ -2486,7 +2486,7 @@ static int devinet_sysctl_forward(const struct ctl_table *ctl, int write,
 
 	if (write && *valp != val) {
 		if (valp != &IPV4_DEVCONF_DFLT(net, FORWARDING)) {
-			if (!rtnl_trylock()) {
+			if (!rtnl_net_trylock(net)) {
 				/* Restore the original values before restarting */
 				*valp = val;
 				*ppos = pos;
@@ -2505,7 +2505,7 @@ static int devinet_sysctl_forward(const struct ctl_table *ctl, int write,
 							    idev->dev->ifindex,
 							    cnf);
 			}
-			rtnl_unlock();
+			rtnl_net_unlock(net);
 			rt_cache_flush(net);
 		} else
 			inet_netconf_notify_devconf(net, RTM_NEWNETCONF,
-- 
2.39.5 (Apple Git-154)


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v1 net-next 11/12] ipv4: Convert devinet_ioctl() to per-netns RTNL except for SIOCSIFFLAGS.
  2024-10-21 18:32 [PATCH v1 net-next 00/12] ipv4: Convert RTM_{NEW,DEL}ADDR and more to per-netns RTNL Kuniyuki Iwashima
                   ` (9 preceding siblings ...)
  2024-10-21 18:32 ` [PATCH v1 net-next 10/12] ipv4: Convert devinet_sysctl_forward() to per-netns RTNL Kuniyuki Iwashima
@ 2024-10-21 18:32 ` Kuniyuki Iwashima
  2024-10-21 18:32 ` [PATCH v1 net-next 12/12] ipv4: Convert devinet_ioctl to per-netns RTNL Kuniyuki Iwashima
  2024-10-29 11:20 ` [PATCH v1 net-next 00/12] ipv4: Convert RTM_{NEW,DEL}ADDR and more " patchwork-bot+netdevbpf
  12 siblings, 0 replies; 15+ messages in thread
From: Kuniyuki Iwashima @ 2024-10-21 18:32 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	David Ahern
  Cc: Kuniyuki Iwashima, Kuniyuki Iwashima, netdev

Basically, devinet_ioctl() operates on a single netns.

However, ioctl(SIOCSIFFLAGS) will trigger the netdev notifier
that could touch another netdev in different netns.

Let's use per-netns RTNL helper in devinet_ioctl() and place
ASSERT_RTNL() for SIOCSIFFLAGS.

We will remove ASSERT_RTNL() once RTM_SETLINK and RTM_DELLINK
are converted.

Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
---
 net/ipv4/devinet.c | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index dcfc060694fa..fb6320f144c5 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -589,9 +589,7 @@ static int inet_insert_ifa(struct in_ifaddr *ifa)
 
 static int inet_set_ifa(struct net_device *dev, struct in_ifaddr *ifa)
 {
-	struct in_device *in_dev = __in_dev_get_rtnl(dev);
-
-	ASSERT_RTNL();
+	struct in_device *in_dev = __in_dev_get_rtnl_net(dev);
 
 	ipv4_devconf_setall(in_dev);
 	neigh_parms_data_state_setall(in_dev->arp_parms);
@@ -1129,7 +1127,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr)
 		goto out;
 	}
 
-	rtnl_lock();
+	rtnl_net_lock(net);
 
 	ret = -ENODEV;
 	dev = __dev_get_by_name(net, ifr->ifr_name);
@@ -1139,7 +1137,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr)
 	if (colon)
 		*colon = ':';
 
-	in_dev = __in_dev_get_rtnl(dev);
+	in_dev = __in_dev_get_rtnl_net(dev);
 	if (in_dev) {
 		if (tryaddrmatch) {
 			/* Matthias Andree */
@@ -1149,7 +1147,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr)
 			   This is checked above. */
 
 			for (ifap = &in_dev->ifa_list;
-			     (ifa = rtnl_dereference(*ifap)) != NULL;
+			     (ifa = rtnl_net_dereference(net, *ifap)) != NULL;
 			     ifap = &ifa->ifa_next) {
 				if (!strcmp(ifr->ifr_name, ifa->ifa_label) &&
 				    sin_orig.sin_addr.s_addr ==
@@ -1163,7 +1161,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr)
 		   comparing just the label */
 		if (!ifa) {
 			for (ifap = &in_dev->ifa_list;
-			     (ifa = rtnl_dereference(*ifap)) != NULL;
+			     (ifa = rtnl_net_dereference(net, *ifap)) != NULL;
 			     ifap = &ifa->ifa_next)
 				if (!strcmp(ifr->ifr_name, ifa->ifa_label))
 					break;
@@ -1205,6 +1203,9 @@ int devinet_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr)
 				inet_del_ifa(in_dev, ifap, 1);
 			break;
 		}
+
+		/* NETDEV_UP/DOWN/CHANGE could touch a peer dev */
+		ASSERT_RTNL();
 		ret = dev_change_flags(dev, ifr->ifr_flags, NULL);
 		break;
 
@@ -1306,7 +1307,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr)
 		break;
 	}
 done:
-	rtnl_unlock();
+	rtnl_net_unlock(net);
 out:
 	return ret;
 }
-- 
2.39.5 (Apple Git-154)


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v1 net-next 12/12] ipv4: Convert devinet_ioctl to per-netns RTNL.
  2024-10-21 18:32 [PATCH v1 net-next 00/12] ipv4: Convert RTM_{NEW,DEL}ADDR and more to per-netns RTNL Kuniyuki Iwashima
                   ` (10 preceding siblings ...)
  2024-10-21 18:32 ` [PATCH v1 net-next 11/12] ipv4: Convert devinet_ioctl() to per-netns RTNL except for SIOCSIFFLAGS Kuniyuki Iwashima
@ 2024-10-21 18:32 ` Kuniyuki Iwashima
  2024-10-29 11:20 ` [PATCH v1 net-next 00/12] ipv4: Convert RTM_{NEW,DEL}ADDR and more " patchwork-bot+netdevbpf
  12 siblings, 0 replies; 15+ messages in thread
From: Kuniyuki Iwashima @ 2024-10-21 18:32 UTC (permalink / raw)
  To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	David Ahern
  Cc: Kuniyuki Iwashima, Kuniyuki Iwashima, netdev

ioctl(SIOCGIFCONF) calls dev_ifconf() that operates on the current netns.

Let's use per-netns RTNL helpers in dev_ifconf() and inet_gifconf().

Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
---
 net/core/dev_ioctl.c | 6 +++---
 net/ipv4/devinet.c   | 4 ++--
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/net/core/dev_ioctl.c b/net/core/dev_ioctl.c
index 473c437b6b53..46d43b950471 100644
--- a/net/core/dev_ioctl.c
+++ b/net/core/dev_ioctl.c
@@ -64,7 +64,7 @@ int dev_ifconf(struct net *net, struct ifconf __user *uifc)
 	}
 
 	/* Loop over the interfaces, and write an info block for each. */
-	rtnl_lock();
+	rtnl_net_lock(net);
 	for_each_netdev(net, dev) {
 		if (!pos)
 			done = inet_gifconf(dev, NULL, 0, size);
@@ -72,12 +72,12 @@ int dev_ifconf(struct net *net, struct ifconf __user *uifc)
 			done = inet_gifconf(dev, pos + total,
 					    len - total, size);
 		if (done < 0) {
-			rtnl_unlock();
+			rtnl_net_unlock(net);
 			return -EFAULT;
 		}
 		total += done;
 	}
-	rtnl_unlock();
+	rtnl_net_unlock(net);
 
 	return put_user(total, &uifc->ifc_len);
 }
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index fb6320f144c5..75549ce631ee 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1314,7 +1314,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr)
 
 int inet_gifconf(struct net_device *dev, char __user *buf, int len, int size)
 {
-	struct in_device *in_dev = __in_dev_get_rtnl(dev);
+	struct in_device *in_dev = __in_dev_get_rtnl_net(dev);
 	const struct in_ifaddr *ifa;
 	struct ifreq ifr;
 	int done = 0;
@@ -1325,7 +1325,7 @@ int inet_gifconf(struct net_device *dev, char __user *buf, int len, int size)
 	if (!in_dev)
 		goto out;
 
-	in_dev_for_each_ifa_rtnl(ifa, in_dev) {
+	in_dev_for_each_ifa_rtnl_net(dev_net(dev), ifa, in_dev) {
 		if (!buf) {
 			done += size;
 			continue;
-- 
2.39.5 (Apple Git-154)


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH v1 net-next 01/12] rtnetlink: Make per-netns RTNL dereference helpers to macro.
  2024-10-21 18:32 ` [PATCH v1 net-next 01/12] rtnetlink: Make per-netns RTNL dereference helpers to macro Kuniyuki Iwashima
@ 2024-10-23 18:58   ` Simon Horman
  0 siblings, 0 replies; 15+ messages in thread
From: Simon Horman @ 2024-10-23 18:58 UTC (permalink / raw)
  To: Kuniyuki Iwashima
  Cc: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	David Ahern, Kuniyuki Iwashima, netdev, kernel test robot

On Mon, Oct 21, 2024 at 11:32:28AM -0700, Kuniyuki Iwashima wrote:
> When CONFIG_DEBUG_NET_SMALL_RTNL is off, rtnl_net_dereference() is the
> static inline wrapper of rtnl_dereference() returning a plain (void *)
> pointer to make sure net is always evaluated as requested in [0].
> 
> But, it makes sparse complain [1] when the pointer has __rcu annotation:
> 
>   net/ipv4/devinet.c:674:47: sparse: warning: incorrect type in argument 2 (different address spaces)
>   net/ipv4/devinet.c:674:47: sparse:    expected void *p
>   net/ipv4/devinet.c:674:47: sparse:    got struct in_ifaddr [noderef] __rcu *
> 
> Also, if we evaluate net as (void *) in a macro, then the compiler
> in turn fails to build due to -Werror=unused-value.
> 
>   #define rtnl_net_dereference(net, p)                  \
>         ({                                              \
>                 (void *)net;                            \
>                 rtnl_dereference(p);                    \
>         })
> 
>   net/ipv4/devinet.c: In function ‘inet_rtm_deladdr’:
>   ./include/linux/rtnetlink.h:154:17: error: statement with no effect [-Werror=unused-value]
>     154 |                 (void *)net;                            \
>   net/ipv4/devinet.c:674:21: note: in expansion of macro ‘rtnl_net_dereference’
>     674 |              (ifa = rtnl_net_dereference(net, *ifap)) != NULL;
>         |                     ^~~~~~~~~~~~~~~~~~~~
> 
> Let's go back to the original simplest macro.
> 
> Note that checkpatch complains about this approach, but it's one-shot and
> less noisy than the other two.
> 
>   WARNING: Argument 'net' is not used in function-like macro
>   #76: FILE: include/linux/rtnetlink.h:142:
>   +#define rtnl_net_dereference(net, p)			\
>   +	rtnl_dereference(p)
> 
> Fixes: 844e5e7e656d ("rtnetlink: Add assertion helpers for per-netns RTNL.")
> Link: https://lore.kernel.org/netdev/20241004132145.7fd208e9@kernel.org/ [0]
> Reported-by: kernel test robot <lkp@intel.com>
> Closes: https://lore.kernel.org/oe-kbuild-all/202410200325.SaEJmyZS-lkp@intel.com/ [1]
> Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>

Thanks,

I was able to reproduce the build problem as described.

Reviewed-by: Simon Horman <horms@kernel.org>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v1 net-next 00/12] ipv4: Convert RTM_{NEW,DEL}ADDR and more to per-netns RTNL.
  2024-10-21 18:32 [PATCH v1 net-next 00/12] ipv4: Convert RTM_{NEW,DEL}ADDR and more to per-netns RTNL Kuniyuki Iwashima
                   ` (11 preceding siblings ...)
  2024-10-21 18:32 ` [PATCH v1 net-next 12/12] ipv4: Convert devinet_ioctl to per-netns RTNL Kuniyuki Iwashima
@ 2024-10-29 11:20 ` patchwork-bot+netdevbpf
  12 siblings, 0 replies; 15+ messages in thread
From: patchwork-bot+netdevbpf @ 2024-10-29 11:20 UTC (permalink / raw)
  To: Kuniyuki Iwashima
  Cc: davem, edumazet, kuba, pabeni, dsahern, kuni1840, netdev

Hello:

This series was applied to netdev/net-next.git (main)
by Paolo Abeni <pabeni@redhat.com>:

On Mon, 21 Oct 2024 11:32:27 -0700 you wrote:
> The IPv4 address hash table and GC are already namespacified.
> 
> This series converts RTM_NEWADDR/RTM_DELADDR and some more
> RTNL users to per-netns RTNL.
> 
> 
> Changes:
>   v2:
>     * Add patch 1 to address sparse warning for CONFIG_DEBUG_NET_SMALL_RTNL=n
>     * Add Eric's tags to patch 2-12
> 
> [...]

Here is the summary with links:
  - [v1,net-next,01/12] rtnetlink: Make per-netns RTNL dereference helpers to macro.
    https://git.kernel.org/netdev/net-next/c/9cb7e40d388d
  - [v1,net-next,02/12] rtnetlink: Define RTNL_FLAG_DOIT_PERNET for per-netns RTNL doit().
    https://git.kernel.org/netdev/net-next/c/26d8db55eeac
  - [v1,net-next,03/12] ipv4: Factorise RTM_NEWADDR validation to inet_validate_rtm().
    https://git.kernel.org/netdev/net-next/c/2d34429d14f9
  - [v1,net-next,04/12] ipv4: Don't allocate ifa for 0.0.0.0 in inet_rtm_newaddr().
    https://git.kernel.org/netdev/net-next/c/abd0deff03d8
  - [v1,net-next,05/12] ipv4: Convert RTM_NEWADDR to per-netns RTNL.
    https://git.kernel.org/netdev/net-next/c/487257786b71
  - [v1,net-next,06/12] ipv4: Use per-netns RTNL helpers in inet_rtm_newaddr().
    https://git.kernel.org/netdev/net-next/c/d4b483208b26
  - [v1,net-next,07/12] ipv4: Convert RTM_DELADDR to per-netns RTNL.
    https://git.kernel.org/netdev/net-next/c/4df5066f079c
  - [v1,net-next,08/12] ipv4: Convert check_lifetime() to per-netns RTNL.
    https://git.kernel.org/netdev/net-next/c/c350c4761e7f
  - [v1,net-next,09/12] rtnetlink: Define rtnl_net_trylock().
    https://git.kernel.org/netdev/net-next/c/d1c81818aa22
  - [v1,net-next,10/12] ipv4: Convert devinet_sysctl_forward() to per-netns RTNL.
    https://git.kernel.org/netdev/net-next/c/77453d428d4c
  - [v1,net-next,11/12] ipv4: Convert devinet_ioctl() to per-netns RTNL except for SIOCSIFFLAGS.
    https://git.kernel.org/netdev/net-next/c/88d1f8770690
  - [v1,net-next,12/12] ipv4: Convert devinet_ioctl to per-netns RTNL.
    https://git.kernel.org/netdev/net-next/c/7ed8da17bfb2

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2024-10-29 11:20 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-10-21 18:32 [PATCH v1 net-next 00/12] ipv4: Convert RTM_{NEW,DEL}ADDR and more to per-netns RTNL Kuniyuki Iwashima
2024-10-21 18:32 ` [PATCH v1 net-next 01/12] rtnetlink: Make per-netns RTNL dereference helpers to macro Kuniyuki Iwashima
2024-10-23 18:58   ` Simon Horman
2024-10-21 18:32 ` [PATCH v1 net-next 02/12] rtnetlink: Define RTNL_FLAG_DOIT_PERNET for per-netns RTNL doit() Kuniyuki Iwashima
2024-10-21 18:32 ` [PATCH v1 net-next 03/12] ipv4: Factorise RTM_NEWADDR validation to inet_validate_rtm() Kuniyuki Iwashima
2024-10-21 18:32 ` [PATCH v1 net-next 04/12] ipv4: Don't allocate ifa for 0.0.0.0 in inet_rtm_newaddr() Kuniyuki Iwashima
2024-10-21 18:32 ` [PATCH v1 net-next 05/12] ipv4: Convert RTM_NEWADDR to per-netns RTNL Kuniyuki Iwashima
2024-10-21 18:32 ` [PATCH v1 net-next 06/12] ipv4: Use per-netns RTNL helpers in inet_rtm_newaddr() Kuniyuki Iwashima
2024-10-21 18:32 ` [PATCH v1 net-next 07/12] ipv4: Convert RTM_DELADDR to per-netns RTNL Kuniyuki Iwashima
2024-10-21 18:32 ` [PATCH v1 net-next 08/12] ipv4: Convert check_lifetime() " Kuniyuki Iwashima
2024-10-21 18:32 ` [PATCH v1 net-next 09/12] rtnetlink: Define rtnl_net_trylock() Kuniyuki Iwashima
2024-10-21 18:32 ` [PATCH v1 net-next 10/12] ipv4: Convert devinet_sysctl_forward() to per-netns RTNL Kuniyuki Iwashima
2024-10-21 18:32 ` [PATCH v1 net-next 11/12] ipv4: Convert devinet_ioctl() to per-netns RTNL except for SIOCSIFFLAGS Kuniyuki Iwashima
2024-10-21 18:32 ` [PATCH v1 net-next 12/12] ipv4: Convert devinet_ioctl to per-netns RTNL Kuniyuki Iwashima
2024-10-29 11:20 ` [PATCH v1 net-next 00/12] ipv4: Convert RTM_{NEW,DEL}ADDR and more " patchwork-bot+netdevbpf

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).