* [PATCH net-next v2 04/12] net: sched: cls_u32: get rid of unused argument of u32_destroy_key()
From: Jamal Hadi Salim @ 2018-10-08 10:22 UTC (permalink / raw)
To: davem; +Cc: xiyou.wangcong, jiri, netdev, viro, Jamal Hadi Salim
In-Reply-To: <20181008102244.22212-1-jhs@emojatatu.com>
From: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
---
net/sched/cls_u32.c | 13 ++++++-------
1 file changed, 6 insertions(+), 7 deletions(-)
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index ce55eea448a0..ef0f2e6ec422 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -405,8 +405,7 @@ static int u32_init(struct tcf_proto *tp)
return 0;
}
-static int u32_destroy_key(struct tcf_proto *tp, struct tc_u_knode *n,
- bool free_pf)
+static int u32_destroy_key(struct tc_u_knode *n, bool free_pf)
{
struct tc_u_hnode *ht = rtnl_dereference(n->ht_down);
@@ -440,7 +439,7 @@ static void u32_delete_key_work(struct work_struct *work)
struct tc_u_knode,
rwork);
rtnl_lock();
- u32_destroy_key(key->tp, key, false);
+ u32_destroy_key(key, false);
rtnl_unlock();
}
@@ -457,7 +456,7 @@ static void u32_delete_key_freepf_work(struct work_struct *work)
struct tc_u_knode,
rwork);
rtnl_lock();
- u32_destroy_key(key->tp, key, true);
+ u32_destroy_key(key, true);
rtnl_unlock();
}
@@ -600,7 +599,7 @@ static void u32_clear_hnode(struct tcf_proto *tp, struct tc_u_hnode *ht,
if (tcf_exts_get_net(&n->exts))
tcf_queue_work(&n->rwork, u32_delete_key_freepf_work);
else
- u32_destroy_key(n->tp, n, true);
+ u32_destroy_key(n, true);
}
}
}
@@ -971,13 +970,13 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
tca[TCA_RATE], ovr, extack);
if (err) {
- u32_destroy_key(tp, new, false);
+ u32_destroy_key(new, false);
return err;
}
err = u32_replace_hw_knode(tp, new, flags, extack);
if (err) {
- u32_destroy_key(tp, new, false);
+ u32_destroy_key(new, false);
return err;
}
--
2.11.0
^ permalink raw reply related
* [PATCH net-next v2 03/12] net: sched: cls_u32: make sure that divisor is a power of 2
From: Jamal Hadi Salim @ 2018-10-08 10:22 UTC (permalink / raw)
To: davem; +Cc: xiyou.wangcong, jiri, netdev, viro, Jamal Hadi Salim
In-Reply-To: <20181008102244.22212-1-jhs@emojatatu.com>
From: Al Viro <viro@zeniv.linux.org.uk>
Tested by modifying iproute2 to allow sending a divisor > 255
Tested-by: Jamal Hadi Salim <jhs@mojatatu.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
---
net/sched/cls_u32.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index 3357331a80a2..ce55eea448a0 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -994,7 +994,11 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
if (tb[TCA_U32_DIVISOR]) {
unsigned int divisor = nla_get_u32(tb[TCA_U32_DIVISOR]);
- if (--divisor > 0x100) {
+ if (!is_power_of_2(divisor)) {
+ NL_SET_ERR_MSG_MOD(extack, "Divisor is not a power of 2");
+ return -EINVAL;
+ }
+ if (divisor-- > 0x100) {
NL_SET_ERR_MSG_MOD(extack, "Exceeded maximum 256 hash buckets");
return -EINVAL;
}
--
2.11.0
^ permalink raw reply related
* [PATCH net-next v2 02/12] net: sched: cls_u32: disallow linking to root hnode
From: Jamal Hadi Salim @ 2018-10-08 10:22 UTC (permalink / raw)
To: davem; +Cc: xiyou.wangcong, jiri, netdev, viro, Jamal Hadi Salim
In-Reply-To: <20181008102244.22212-1-jhs@emojatatu.com>
From: Al Viro <viro@zeniv.linux.org.uk>
Operation makes no sense. Nothing will actually break if we do so
(depth limit in u32_classify() will prevent infinite loops), but
according to maintainers it's best prohibited outright.
NOTE: doing so guarantees that u32_destroy() will trigger the call
of u32_destroy_hnode(); we might want to make that unconditional.
Test:
tc qdisc add dev eth0 ingress
tc filter add dev eth0 parent ffff: protocol ip prio 100 u32 \
link 800: offset at 0 mask 0f00 shift 6 plus 0 eat match ip protocol 6 ff
should fail with
Error: cls_u32: Not linking to root node
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
---
net/sched/cls_u32.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index 622f4657da94..3357331a80a2 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -797,6 +797,10 @@ static int u32_set_parms(struct net *net, struct tcf_proto *tp,
NL_SET_ERR_MSG_MOD(extack, "Link hash table not found");
return -EINVAL;
}
+ if (ht_down->is_root) {
+ NL_SET_ERR_MSG_MOD(extack, "Not linking to root node");
+ return -EINVAL;
+ }
ht_down->refcnt++;
}
--
2.11.0
^ permalink raw reply related
* [PATCH net-next v2 01/12] net: sched: cls_u32: mark root hnode explicitly
From: Jamal Hadi Salim @ 2018-10-08 10:22 UTC (permalink / raw)
To: davem; +Cc: xiyou.wangcong, jiri, netdev, viro, Jamal Hadi Salim
In-Reply-To: <20181008102244.22212-1-jhs@emojatatu.com>
From: Al Viro <viro@zeniv.linux.org.uk>
... and produce consistent error on attempt to delete such.
Existing check in u32_delete() is inconsistent - after
tc qdisc add dev eth0 ingress
tc filter add dev eth0 parent ffff: protocol ip prio 100 handle 1: u32 \
divisor 1
tc filter add dev eth0 parent ffff: protocol ip prio 200 handle 2: u32 \
divisor 1
both
tc filter delete dev eth0 parent ffff: protocol ip prio 100 handle 801: u32
and
tc filter delete dev eth0 parent ffff: protocol ip prio 100 handle 800: u32
will fail (at least with refcounting fixes), but the former will complain
about an attempt to remove a busy table, while the latter will recognize
it as root and yield "Not allowed to delete root node" instead.
The problem with the existing check is that several tcf_proto instances
might share the same tp->data and handle-to-hnode lookup will be the same
for all of them. So comparing an hnode to be deleted with tp->root won't
catch the case when one tp is used to try deleting the root of another.
Solution is trivial - mark the root hnodes explicitly upon allocation and
check for that.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Jamal Hadi Salim <jhs@mojatatu.com>
---
net/sched/cls_u32.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c
index f218ccf1e2d9..622f4657da94 100644
--- a/net/sched/cls_u32.c
+++ b/net/sched/cls_u32.c
@@ -84,6 +84,7 @@ struct tc_u_hnode {
int refcnt;
unsigned int divisor;
struct idr handle_idr;
+ bool is_root;
struct rcu_head rcu;
u32 flags;
/* The 'ht' field MUST be the last field in structure to allow for
@@ -377,6 +378,7 @@ static int u32_init(struct tcf_proto *tp)
root_ht->refcnt++;
root_ht->handle = tp_c ? gen_new_htid(tp_c, root_ht) : 0x80000000;
root_ht->prio = tp->prio;
+ root_ht->is_root = true;
idr_init(&root_ht->handle_idr);
if (tp_c == NULL) {
@@ -692,7 +694,7 @@ static int u32_delete(struct tcf_proto *tp, void *arg, bool *last,
goto out;
}
- if (root_ht == ht) {
+ if (ht->is_root) {
NL_SET_ERR_MSG_MOD(extack, "Not allowed to delete root node");
return -EINVAL;
}
--
2.11.0
^ permalink raw reply related
* [PATCH net-next v2 00/12] net: sched: cls_u32 Various improvements
From: Jamal Hadi Salim @ 2018-10-08 10:22 UTC (permalink / raw)
To: davem; +Cc: xiyou.wangcong, jiri, netdev, viro, Jamal Hadi Salim
From: Jamal Hadi Salim <hadi@mojatatu.com>
Various improvements from Al.
Changes from version 1: Add missing commit
Al Viro (11):
net: sched: cls_u32: mark root hnode explicitly
net: sched: cls_u32: disallow linking to root hnode
net: sched: cls_u32: make sure that divisor is a power of 2
net: sched: cls_u32: get rid of unused argument of u32_destroy_key()
net: sched: cls_u32: get rid of tc_u_knode ->tp
net: sched: cls_u32: get rid of tc_u_common ->rcu
net: sched: cls_u32: clean tc_u_common hashtable
net: sched: cls_u32: pass tc_u_common to u32_set_parms() instead of
tc_u_hnode
net: sched: cls_u32: the tp_c argument of u32_set_parms() is always
tp->data
net: sched: cls_u32: get rid of tp_c
net: sched: cls_u32: keep track of knodes count in tc_u_common
net: sched: cls_u32: simplify the hell out u32_delete() emptiness
check
net/sched/cls_u32.c | 121 +++++++++++++++++-----------------------------------
1 file changed, 38 insertions(+), 83 deletions(-)
--
2.11.0
^ permalink raw reply
* Re: [RESEND PATCH v2 0/5] net: phy: mscc: add support for VSC8584 and VSC8574 Microsemi quad-port PHYs
From: David Miller @ 2018-10-08 17:31 UTC (permalink / raw)
To: quentin.schulz
Cc: alexandre.belloni, ralf, paul.burton, jhogan, robh+dt,
mark.rutland, andrew, f.fainelli, allan.nielsen, linux-mips,
devicetree, linux-kernel, netdev, thomas.petazzoni,
antoine.tenart
In-Reply-To: <20181008101445.25946-1-quentin.schulz@bootlin.com>
From: Quentin Schulz <quentin.schulz@bootlin.com>
Date: Mon, 8 Oct 2018 12:14:40 +0200
> RESEND: rebased on top of latest net-next and on top of latest version of
> "net: phy: mscc: various improvements to Microsemi PHY driver" patch
> series.
Patches 1-3 applied to net-next, thanks.
^ permalink raw reply
* Re: [PATCH v2 net-next 12/23] rtnetlink: Update inet6_dump_ifinfo for strict data checking
From: Christian Brauner @ 2018-10-08 10:18 UTC (permalink / raw)
To: David Ahern; +Cc: netdev, davem, jbenc, stephen, David Ahern
In-Reply-To: <20181008031644.15989-13-dsahern@kernel.org>
On Sun, Oct 07, 2018 at 08:16:33PM -0700, David Ahern wrote:
> From: David Ahern <dsahern@gmail.com>
>
> Update inet6_dump_ifinfo for strict data checking. If the flag is
> set, the dump request is expected to have an ifinfomsg struct as
> the header. All elements of the struct are expected to be 0 and no
> attributes can be appended.
>
> Signed-off-by: David Ahern <dsahern@gmail.com>
Acked-by: Christian Brauner <christian@brauner.io>
> ---
> net/ipv6/addrconf.c | 35 +++++++++++++++++++++++++++++++++++
> 1 file changed, 35 insertions(+)
>
> diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
> index 095d3f56f0a9..ce071d85ad00 100644
> --- a/net/ipv6/addrconf.c
> +++ b/net/ipv6/addrconf.c
> @@ -5644,6 +5644,31 @@ static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev,
> return -EMSGSIZE;
> }
>
> +static int inet6_valid_dump_ifinfo(const struct nlmsghdr *nlh,
> + struct netlink_ext_ack *extack)
> +{
> + struct ifinfomsg *ifm;
> +
> + if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ifm))) {
> + NL_SET_ERR_MSG_MOD(extack, "Invalid header for link dump request");
> + return -EINVAL;
> + }
> +
> + if (nlmsg_attrlen(nlh, sizeof(*ifm))) {
> + NL_SET_ERR_MSG_MOD(extack, "Invalid data after header");
> + return -EINVAL;
> + }
> +
> + ifm = nlmsg_data(nlh);
> + if (ifm->__ifi_pad || ifm->ifi_type || ifm->ifi_flags ||
> + ifm->ifi_change || ifm->ifi_index) {
> + NL_SET_ERR_MSG_MOD(extack, "Invalid values in header for dump request");
> + return -EINVAL;
> + }
> +
> + return 0;
> +}
> +
> static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
> {
> struct net *net = sock_net(skb->sk);
> @@ -5653,6 +5678,16 @@ static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
> struct inet6_dev *idev;
> struct hlist_head *head;
>
> + /* only requests using strict checking can pass data to
> + * influence the dump
> + */
> + if (cb->strict_check) {
> + int err = inet6_valid_dump_ifinfo(cb->nlh, cb->extack);
> +
> + if (err < 0)
> + return err;
> + }
> +
> s_h = cb->args[0];
> s_idx = cb->args[1];
>
> --
> 2.11.0
>
^ permalink raw reply
* Re: [PATCH net-next v3 0/6] net: phy: mscc: various improvements to Microsemi PHY driver
From: David Miller @ 2018-10-08 17:29 UTC (permalink / raw)
To: quentin.schulz
Cc: andrew, f.fainelli, allan.nielsen, linux-kernel, netdev,
thomas.petazzoni, alexandre.belloni
In-Reply-To: <20181008100728.24959-1-quentin.schulz@bootlin.com>
From: Quentin Schulz <quentin.schulz@bootlin.com>
Date: Mon, 8 Oct 2018 12:07:22 +0200
> The Microsemi PHYs have multiple banks of registers (called pages).
> Registers can only be accessed from one page, if we need a register from
> another page, we need to switch the page and the registers of all other
> pages are not accessible anymore.
>
> Basically, to read register 5 from page 0, 1, 2, etc., you do the same
> phy_read(phydev, 5); but you need to set the desired page beforehand.
>
> In order to guarantee that two concurrent functions do not change the
> page, we need to do some locking per page. This can be achieved with the
> use of phy_select_page and phy_restore_page functions but phy_write/read
> calls in-between those two functions shall be replaced by their
> lock-free alternative __phy_write/read.
>
> The Microsemi PHYs have several counters so let's make them available as PHY
> statistics.
>
> The VSC 8530/31/40/41 also need to update their EEE init sequence in order to
> avoid packet losses and improve performance.
>
> This patch series also makes some minor cosmetic changes to the driver.
Series applied, thank you.
^ permalink raw reply
* [PATCH net-next] netdev: remove useless codes of tun_automq_select_queue
From: Wang Li @ 2018-10-08 10:17 UTC (permalink / raw)
To: netdev
Because the function __skb_get_hash_symmetric always returns non-zero.
Signed-off-by: Zhang Yu <zhangyu31@baidu.com>
Signed-off-by: Wang Li <wangli39@baidu.com>
---
drivers/net/tun.c | 35 +++++++++++++----------------------
1 file changed, 13 insertions(+), 22 deletions(-)
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index e2648b5a3861..9647da2c5651 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -562,12 +562,11 @@ static inline void tun_flow_save_rps_rxhash(struct tun_flow_entry *e, u32 hash)
e->rps_rxhash = hash;
}
-/* We try to identify a flow through its rxhash first. The reason that
+/* We try to identify a flow through its rxhash. The reason that
* we do not check rxq no. is because some cards(e.g 82599), chooses
* the rxq based on the txq where the last packet of the flow comes. As
* the userspace application move between processors, we may get a
- * different rxq no. here. If we could not get rxhash, then we would
- * hope the rxq no. may help here.
+ * different rxq no. here.
*/
static u16 tun_automq_select_queue(struct tun_struct *tun, struct sk_buff *skb)
{
@@ -578,18 +577,13 @@ static u16 tun_automq_select_queue(struct tun_struct *tun, struct sk_buff *skb)
numqueues = READ_ONCE(tun->numqueues);
txq = __skb_get_hash_symmetric(skb);
- if (txq) {
- e = tun_flow_find(&tun->flows[tun_hashfn(txq)], txq);
- if (e) {
- tun_flow_save_rps_rxhash(e, txq);
- txq = e->queue_index;
- } else
- /* use multiply and shift instead of expensive divide */
- txq = ((u64)txq * numqueues) >> 32;
- } else if (likely(skb_rx_queue_recorded(skb))) {
- txq = skb_get_rx_queue(skb);
- while (unlikely(txq >= numqueues))
- txq -= numqueues;
+ e = tun_flow_find(&tun->flows[tun_hashfn(txq)], txq);
+ if (e) {
+ tun_flow_save_rps_rxhash(e, txq);
+ txq = e->queue_index;
+ } else {
+ /* use multiply and shift instead of expensive divide */
+ txq = ((u64)txq * numqueues) >> 32;
}
return txq;
@@ -1045,15 +1039,12 @@ static void tun_automq_xmit(struct tun_struct *tun, struct sk_buff *skb)
* RPS hash and save it into the flow_table here.
*/
__u32 rxhash;
+ struct tun_flow_entry *e;
rxhash = __skb_get_hash_symmetric(skb);
- if (rxhash) {
- struct tun_flow_entry *e;
- e = tun_flow_find(&tun->flows[tun_hashfn(rxhash)],
- rxhash);
- if (e)
- tun_flow_save_rps_rxhash(e, rxhash);
- }
+ e = tun_flow_find(&tun->flows[tun_hashfn(rxhash)], rxhash);
+ if (e)
+ tun_flow_save_rps_rxhash(e, rxhash);
}
#endif
}
--
2.15.2 (Apple Git-101.1)
^ permalink raw reply related
* Re: [PATCH v2 net-next 11/23] rtnetlink: Update rtnl_stats_dump for strict data checking
From: Christian Brauner @ 2018-10-08 10:17 UTC (permalink / raw)
To: David Ahern; +Cc: netdev, davem, jbenc, stephen, David Ahern
In-Reply-To: <20181008031644.15989-12-dsahern@kernel.org>
On Sun, Oct 07, 2018 at 08:16:32PM -0700, David Ahern wrote:
> From: David Ahern <dsahern@gmail.com>
>
> Update rtnl_stats_dump for strict data checking. If the flag is set,
> the dump request is expected to have an if_stats_msg struct as the header.
> All elements of the struct are expected to be 0 except filter_mask which
> must be non-0 (legacy behavior). No attributes are supported.
>
> Signed-off-by: David Ahern <dsahern@gmail.com>
> ---
> net/core/rtnetlink.c | 24 ++++++++++++++++++++++--
> 1 file changed, 22 insertions(+), 2 deletions(-)
>
> diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
> index e38e1f178611..f6d2609cfa9f 100644
> --- a/net/core/rtnetlink.c
> +++ b/net/core/rtnetlink.c
> @@ -4680,6 +4680,7 @@ static int rtnl_stats_get(struct sk_buff *skb, struct nlmsghdr *nlh,
>
> static int rtnl_stats_dump(struct sk_buff *skb, struct netlink_callback *cb)
> {
> + struct netlink_ext_ack *extack = cb->extack;
> int h, s_h, err, s_idx, s_idxattr, s_prividx;
> struct net *net = sock_net(skb->sk);
> unsigned int flags = NLM_F_MULTI;
> @@ -4696,13 +4697,32 @@ static int rtnl_stats_dump(struct sk_buff *skb, struct netlink_callback *cb)
>
> cb->seq = net->dev_base_seq;
>
> - if (nlmsg_len(cb->nlh) < sizeof(*ifsm))
> + if (nlmsg_len(cb->nlh) < sizeof(*ifsm)) {
> + NL_SET_ERR_MSG(extack, "Invalid header for stats dump");
> return -EINVAL;
> + }
>
> ifsm = nlmsg_data(cb->nlh);
> +
> + /* only requests using NLM_F_DUMP_PROPER_HDR can pass data to
That looks like an accidental leftover before we changed this to a
socket option. :)
> + * influence the dump. The legacy exception is filter_mask.
> + */
> + if (cb->strict_check) {
> + if (ifsm->pad1 || ifsm->pad2 || ifsm->ifindex) {
> + NL_SET_ERR_MSG(extack, "Invalid values in header for stats dump request");
> + return -EINVAL;
> + }
> + if (nlmsg_attrlen(cb->nlh, sizeof(*ifsm))) {
> + NL_SET_ERR_MSG(extack, "Invalid attributes after stats header");
> + return -EINVAL;
> + }
> + }
> +
> filter_mask = ifsm->filter_mask;
> - if (!filter_mask)
> + if (!filter_mask) {
> + NL_SET_ERR_MSG(extack, "Filter mask must be set for stats dump");
> return -EINVAL;
> + }
>
> for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
> idx = 0;
> --
> 2.11.0
>
^ permalink raw reply
* Re: [PATCH v2 net-next 10/23] rtnetlink: Update rtnl_bridge_getlink for strict data checking
From: Christian Brauner @ 2018-10-08 10:15 UTC (permalink / raw)
To: David Ahern; +Cc: netdev, davem, jbenc, stephen, David Ahern
In-Reply-To: <20181008031644.15989-11-dsahern@kernel.org>
On Sun, Oct 07, 2018 at 08:16:31PM -0700, David Ahern wrote:
> From: David Ahern <dsahern@gmail.com>
>
> Update rtnl_bridge_getlink for strict data checking. If the flag is set,
> the dump request is expected to have an ifinfomsg struct as the header
> potentially followed by one or more attributes. Any data passed in the
> header or as an attribute is taken as a request to influence the data
> returned. Only values supported by the dump handler are allowed to be
> non-0 or set in the request. At the moment only the IFLA_EXT_MASK
> attribute is supported.
>
> Signed-off-by: David Ahern <dsahern@gmail.com>
Acked-by: Christian Brauner <christian@brauner.io>
> ---
> net/core/rtnetlink.c | 70 ++++++++++++++++++++++++++++++++++++++++++----------
> 1 file changed, 57 insertions(+), 13 deletions(-)
>
> diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
> index 12fd52105005..e38e1f178611 100644
> --- a/net/core/rtnetlink.c
> +++ b/net/core/rtnetlink.c
> @@ -4021,28 +4021,72 @@ int ndo_dflt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq,
> }
> EXPORT_SYMBOL_GPL(ndo_dflt_bridge_getlink);
>
> +static int valid_bridge_getlink_req(const struct nlmsghdr *nlh,
> + bool strict_check, u32 *filter_mask,
> + struct netlink_ext_ack *extack)
> +{
> + struct nlattr *tb[IFLA_MAX+1];
> + int err, i;
> +
> + if (strict_check) {
> + struct ifinfomsg *ifm;
> +
> + if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ifm))) {
> + NL_SET_ERR_MSG(extack, "Invalid header for bridge link dump");
> + return -EINVAL;
> + }
> +
> + ifm = nlmsg_data(nlh);
> + if (ifm->__ifi_pad || ifm->ifi_type || ifm->ifi_flags ||
> + ifm->ifi_change || ifm->ifi_index) {
> + NL_SET_ERR_MSG(extack, "Invalid values in header for bridge link dump request");
> + return -EINVAL;
> + }
> +
> + err = nlmsg_parse_strict(nlh, sizeof(struct ifinfomsg), tb,
> + IFLA_MAX, ifla_policy, extack);
> + } else {
> + err = nlmsg_parse(nlh, sizeof(struct ifinfomsg), tb,
> + IFLA_MAX, ifla_policy, extack);
> + }
> + if (err < 0)
> + return err;
> +
> + /* new attributes should only be added with strict checking */
> + for (i = 0; i <= IFLA_MAX; ++i) {
> + if (!tb[i])
> + continue;
> +
> + switch (i) {
> + case IFLA_EXT_MASK:
> + *filter_mask = nla_get_u32(tb[i]);
> + break;
> + default:
> + if (strict_check) {
> + NL_SET_ERR_MSG(extack, "Unsupported attribute in bridge link dump request");
> + return -EINVAL;
> + }
> + }
> + }
> +
> + return 0;
> +}
> +
> static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb)
> {
> + const struct nlmsghdr *nlh = cb->nlh;
> struct net *net = sock_net(skb->sk);
> struct net_device *dev;
> int idx = 0;
> u32 portid = NETLINK_CB(cb->skb).portid;
> - u32 seq = cb->nlh->nlmsg_seq;
> + u32 seq = nlh->nlmsg_seq;
> u32 filter_mask = 0;
> int err;
>
> - if (nlmsg_len(cb->nlh) > sizeof(struct ifinfomsg)) {
> - struct nlattr *extfilt;
> -
> - extfilt = nlmsg_find_attr(cb->nlh, sizeof(struct ifinfomsg),
> - IFLA_EXT_MASK);
> - if (extfilt) {
> - if (nla_len(extfilt) < sizeof(filter_mask))
> - return -EINVAL;
> -
> - filter_mask = nla_get_u32(extfilt);
> - }
> - }
> + err = valid_bridge_getlink_req(nlh, cb->strict_check, &filter_mask,
> + cb->extack);
> + if (err < 0 && cb->strict_check)
> + return err;
>
> rcu_read_lock();
> for_each_netdev_rcu(net, dev) {
> --
> 2.11.0
>
^ permalink raw reply
* [RESEND PATCH v2 4/5] MIPS: mscc: add DT for Ocelot PCB120
From: Quentin Schulz @ 2018-10-08 10:14 UTC (permalink / raw)
To: alexandre.belloni, ralf, paul.burton, jhogan, robh+dt,
mark.rutland, davem, andrew, f.fainelli
Cc: allan.nielsen, linux-mips, devicetree, linux-kernel, netdev,
thomas.petazzoni, antoine.tenart, Quentin Schulz
In-Reply-To: <20181008101445.25946-1-quentin.schulz@bootlin.com>
The Ocelot PCB120 evaluation board is different from the PCB123 in that
it has 4 external VSC8584 (or VSC8574) PHYs.
It uses the SoC's second MDIO bus for external PHYs which have a
reversed address on the bus (i.e. PHY4 is on address 3, PHY5 is on
address 2, PHY6 on 1 and PHY7 on 0).
Here is how the PHYs are connected to the switch ports:
port 0: phy0 (internal)
port 1: phy1 (internal)
port 2: phy2 (internal)
port 3: phy3 (internal)
port 4: phy7
port 5: phy4
port 6: phy6
port 9: phy5
Reviewed-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Signed-off-by: Quentin Schulz <quentin.schulz@bootlin.com>
---
arch/mips/boot/dts/mscc/Makefile | 2 +-
arch/mips/boot/dts/mscc/ocelot_pcb120.dts | 107 ++++++++++++++++++++++
2 files changed, 108 insertions(+), 1 deletion(-)
create mode 100644 arch/mips/boot/dts/mscc/ocelot_pcb120.dts
diff --git a/arch/mips/boot/dts/mscc/Makefile b/arch/mips/boot/dts/mscc/Makefile
index 9a9bb7ea0503..ec6f5b2bf093 100644
--- a/arch/mips/boot/dts/mscc/Makefile
+++ b/arch/mips/boot/dts/mscc/Makefile
@@ -1,3 +1,3 @@
-dtb-$(CONFIG_MSCC_OCELOT) += ocelot_pcb123.dtb
+dtb-$(CONFIG_MSCC_OCELOT) += ocelot_pcb123.dtb ocelot_pcb120.dtb
obj-$(CONFIG_BUILTIN_DTB) += $(addsuffix .o, $(dtb-y))
diff --git a/arch/mips/boot/dts/mscc/ocelot_pcb120.dts b/arch/mips/boot/dts/mscc/ocelot_pcb120.dts
new file mode 100644
index 000000000000..33991fd209f5
--- /dev/null
+++ b/arch/mips/boot/dts/mscc/ocelot_pcb120.dts
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/* Copyright (c) 2017 Microsemi Corporation */
+
+/dts-v1/;
+
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/phy/phy-ocelot-serdes.h>
+#include "ocelot.dtsi"
+
+/ {
+ compatible = "mscc,ocelot-pcb120", "mscc,ocelot";
+
+ chosen {
+ stdout-path = "serial0:115200n8";
+ };
+
+ memory@0 {
+ device_type = "memory";
+ reg = <0x0 0x0e000000>;
+ };
+};
+
+&gpio {
+ phy_int_pins: phy_int_pins {
+ pins = "GPIO_4";
+ function = "gpio";
+ };
+};
+
+&mdio0 {
+ status = "okay";
+};
+
+&mdio1 {
+ status = "okay";
+ pinctrl-names = "default";
+ pinctrl-0 = <&miim1>, <&phy_int_pins>;
+
+ phy7: ethernet-phy@0 {
+ reg = <0>;
+ interrupts = <4 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-parent = <&gpio>;
+ };
+ phy6: ethernet-phy@1 {
+ reg = <1>;
+ interrupts = <4 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-parent = <&gpio>;
+ };
+ phy5: ethernet-phy@2 {
+ reg = <2>;
+ interrupts = <4 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-parent = <&gpio>;
+ };
+ phy4: ethernet-phy@3 {
+ reg = <3>;
+ interrupts = <4 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-parent = <&gpio>;
+ };
+};
+
+&port0 {
+ phy-handle = <&phy0>;
+};
+
+&port1 {
+ phy-handle = <&phy1>;
+};
+
+&port2 {
+ phy-handle = <&phy2>;
+};
+
+&port3 {
+ phy-handle = <&phy3>;
+};
+
+&port4 {
+ phy-handle = <&phy7>;
+ phy-mode = "sgmii";
+ phys = <&serdes 4 SERDES1G(2)>;
+};
+
+&port5 {
+ phy-handle = <&phy4>;
+ phy-mode = "sgmii";
+ phys = <&serdes 5 SERDES1G(5)>;
+};
+
+&port6 {
+ phy-handle = <&phy6>;
+ phy-mode = "sgmii";
+ phys = <&serdes 6 SERDES1G(3)>;
+};
+
+&port9 {
+ phy-handle = <&phy5>;
+ phy-mode = "sgmii";
+ phys = <&serdes 9 SERDES1G(4)>;
+};
+
+&uart0 {
+ status = "okay";
+};
+
+&uart2 {
+ status = "okay";
+};
--
2.17.1
^ permalink raw reply related
* [RESEND PATCH v2 0/5] net: phy: mscc: add support for VSC8584 and VSC8574 Microsemi quad-port PHYs
From: Quentin Schulz @ 2018-10-08 10:14 UTC (permalink / raw)
To: alexandre.belloni, ralf, paul.burton, jhogan, robh+dt,
mark.rutland, davem, andrew, f.fainelli
Cc: allan.nielsen, linux-mips, devicetree, linux-kernel, netdev,
thomas.petazzoni, antoine.tenart, Quentin Schulz
RESEND: rebased on top of latest net-next and on top of latest version of
"net: phy: mscc: various improvements to Microsemi PHY driver" patch
series.
Both PHYs are 4-port PHY that are 10/100/1000BASE-T, 100BASE-FX, 1000BASE-X
and triple-speed copper SFP capable, can communicate with the MAC via
SGMII, QSGMII or 1000BASE-X, supports downshifting and can set the blinking
pattern of each of its 4 LEDs, supports SyncE as well as HP Auto-MDIX
detection.
VSC8574 supports WOL and VSC8584 supports hardware offloading of MACsec.
This patch series add support for 10/100/1000BASE-T, SGMII/QSGMII link with
the MAC, downshifting, HP Auto-MDIX detection and blinking pattern for
their 4 LEDs.
They have also an internal Intel 8051 microcontroller whose firmware needs
to be patched when the PHY is reset. If the 8051's firmware has the
expected CRC, its patching can be skipped. The microcontroller can be
accessed from any port of the PHY, though the CRC function can only be done
through the PHY that is the base PHY of the package (internal address 0)
due to a limitation of the firmware.
The GPIO register bank is a set of registers that are common to all PHYs in
the package. So any modification in any register of this bank affects all
PHYs of the package.
If the PHYs haven't been reset before booting the Linux kernel and were
configured to use interrupts for e.g. link status updates, it is required
to clear the interrupts mask register of all PHYs before being able to use
interrupts with any PHY. The first PHY of the package that will be init
will take care of clearing all PHYs interrupts mask registers. Thus, we
need to keep track of the init sequence in the package, if it's already
been done or if it's to be done.
Most of the init sequence of a PHY of the package is common to all PHYs in
the package, thus we use the SMI broadcast feature which enables us to
propagate a write in one register of one PHY to all PHYs in the same
package.
We also introduce a new development board called PCB120 which exists in
variants for VSC8584 and VSC8574 (and that's the only difference to the
best of my knowledge).
I suggest patches 1 to 3 go through net tree and patches 4 and 5 go
through MIPS tree. Patches going through net tree and those going through
MIPS tree do not depend on one another.
This patch series depends on this patch series:
(https://lore.kernel.org/lkml/20181008100728.24959-1-quentin.schulz@bootlin.com/)
Thanks,
Quentin
Quentin Schulz (5):
dt-bindings: net: vsc8531: add two additional LED modes for VSC8584
net: phy: mscc: add support for VSC8584 PHY
net: phy: mscc: add support for VSC8574 PHY
MIPS: mscc: add DT for Ocelot PCB120
MIPS: mscc: add PCB120 to the ocelot fitImage
arch/mips/boot/dts/mscc/Makefile | 2 +-
arch/mips/boot/dts/mscc/ocelot_pcb120.dts | 107 ++
arch/mips/generic/Kconfig | 6 +-
arch/mips/generic/Platform | 2 +-
...ocelot_pcb123.its.S => board-ocelot.its.S} | 17 +
drivers/net/phy/mscc.c | 1065 +++++++++++++++++
include/dt-bindings/net/mscc-phy-vsc8531.h | 2 +
7 files changed, 1196 insertions(+), 5 deletions(-)
create mode 100644 arch/mips/boot/dts/mscc/ocelot_pcb120.dts
rename arch/mips/generic/{board-ocelot_pcb123.its.S => board-ocelot.its.S} (55%)
--
2.17.1
^ permalink raw reply
* Re: [PATCH v2 net-next 09/23] rtnetlink: Update rtnl_dump_ifinfo for strict data checking
From: Christian Brauner @ 2018-10-08 10:14 UTC (permalink / raw)
To: David Ahern; +Cc: netdev, davem, jbenc, stephen, David Ahern
In-Reply-To: <20181008031644.15989-10-dsahern@kernel.org>
On Sun, Oct 07, 2018 at 08:16:30PM -0700, David Ahern wrote:
> From: David Ahern <dsahern@gmail.com>
>
> Update rtnl_dump_ifinfo for strict data checking. If the flag is set,
> the dump request is expected to have an ifinfomsg struct as the header
> potentially followed by one or more attributes. Any data passed in the
> header or as an attribute is taken as a request to influence the data
> returned. Only values supported by the dump handler are allowed to be
> non-0 or set in the request. At the moment only the IFA_TARGET_NETNSID,
> IFLA_EXT_MASK, IFLA_MASTER, and IFLA_LINKINFO attributes are supported.
>
> Existing code does not fail the dump if nlmsg_parse fails. That behavior
> is kept for non-strict checking.
>
> Signed-off-by: David Ahern <dsahern@gmail.com>
Acked-by: Christian Brauner <christian@brauner.io>
> ---
> net/core/rtnetlink.c | 113 +++++++++++++++++++++++++++++++++++++--------------
> 1 file changed, 83 insertions(+), 30 deletions(-)
>
> diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
> index 4486e8b7d9d0..12fd52105005 100644
> --- a/net/core/rtnetlink.c
> +++ b/net/core/rtnetlink.c
> @@ -1878,8 +1878,52 @@ struct net *rtnl_get_net_ns_capable(struct sock *sk, int netnsid)
> }
> EXPORT_SYMBOL_GPL(rtnl_get_net_ns_capable);
>
> +static int rtnl_valid_dump_ifinfo_req(const struct nlmsghdr *nlh,
> + bool strict_check, struct nlattr **tb,
> + struct netlink_ext_ack *extack)
> +{
> + int hdrlen;
> +
> + if (strict_check) {
> + struct ifinfomsg *ifm;
> +
> + if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ifm))) {
> + NL_SET_ERR_MSG(extack, "Invalid header for link dump");
> + return -EINVAL;
> + }
> +
> + ifm = nlmsg_data(nlh);
> + if (ifm->__ifi_pad || ifm->ifi_type || ifm->ifi_flags ||
> + ifm->ifi_change) {
> + NL_SET_ERR_MSG(extack, "Invalid values in header for link dump request");
> + return -EINVAL;
> + }
> + if (ifm->ifi_index) {
> + NL_SET_ERR_MSG(extack, "Filter by device index not supported for link dumps");
> + return -EINVAL;
> + }
> +
> + return nlmsg_parse_strict(nlh, sizeof(*ifm), tb, IFLA_MAX,
> + ifla_policy, extack);
> + }
> +
> + /* A hack to preserve kernel<->userspace interface.
> + * The correct header is ifinfomsg. It is consistent with rtnl_getlink.
> + * However, before Linux v3.9 the code here assumed rtgenmsg and that's
> + * what iproute2 < v3.9.0 used.
> + * We can detect the old iproute2. Even including the IFLA_EXT_MASK
> + * attribute, its netlink message is shorter than struct ifinfomsg.
> + */
> + hdrlen = nlmsg_len(nlh) < sizeof(struct ifinfomsg) ?
> + sizeof(struct rtgenmsg) : sizeof(struct ifinfomsg);
> +
> + return nlmsg_parse(nlh, hdrlen, tb, IFLA_MAX, ifla_policy, extack);
> +}
> +
> static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
> {
> + struct netlink_ext_ack *extack = cb->extack;
> + const struct nlmsghdr *nlh = cb->nlh;
> struct net *net = sock_net(skb->sk);
> struct net *tgt_net = net;
> int h, s_h;
> @@ -1892,44 +1936,54 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
> unsigned int flags = NLM_F_MULTI;
> int master_idx = 0;
> int netnsid = -1;
> - int err;
> - int hdrlen;
> + int err, i;
>
> s_h = cb->args[0];
> s_idx = cb->args[1];
>
> - /* A hack to preserve kernel<->userspace interface.
> - * The correct header is ifinfomsg. It is consistent with rtnl_getlink.
> - * However, before Linux v3.9 the code here assumed rtgenmsg and that's
> - * what iproute2 < v3.9.0 used.
> - * We can detect the old iproute2. Even including the IFLA_EXT_MASK
> - * attribute, its netlink message is shorter than struct ifinfomsg.
> - */
> - hdrlen = nlmsg_len(cb->nlh) < sizeof(struct ifinfomsg) ?
> - sizeof(struct rtgenmsg) : sizeof(struct ifinfomsg);
> + err = rtnl_valid_dump_ifinfo_req(nlh, cb->strict_check, tb, extack);
> + if (err < 0) {
> + if (cb->strict_check)
> + return err;
> +
> + goto walk_entries;
> + }
> +
> + for (i = 0; i <= IFLA_MAX; ++i) {
> + if (!tb[i])
> + continue;
>
> - if (nlmsg_parse(cb->nlh, hdrlen, tb, IFLA_MAX,
> - ifla_policy, cb->extack) >= 0) {
> - if (tb[IFLA_TARGET_NETNSID]) {
> - netnsid = nla_get_s32(tb[IFLA_TARGET_NETNSID]);
> + /* new attributes should only be added with strict checking */
> + switch (i) {
> + case IFLA_TARGET_NETNSID:
> + netnsid = nla_get_s32(tb[i]);
> tgt_net = rtnl_get_net_ns_capable(skb->sk, netnsid);
> - if (IS_ERR(tgt_net))
> + if (IS_ERR(tgt_net)) {
> + NL_SET_ERR_MSG(extack, "Invalid target network namespace id");
> return PTR_ERR(tgt_net);
> + }
> + break;
> + case IFLA_EXT_MASK:
> + ext_filter_mask = nla_get_u32(tb[i]);
> + break;
> + case IFLA_MASTER:
> + master_idx = nla_get_u32(tb[i]);
> + break;
> + case IFLA_LINKINFO:
> + kind_ops = linkinfo_to_kind_ops(tb[i]);
> + break;
> + default:
> + if (cb->strict_check) {
> + NL_SET_ERR_MSG(extack, "Unsupported attribute in link dump request");
> + return -EINVAL;
> + }
> }
> -
> - if (tb[IFLA_EXT_MASK])
> - ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]);
> -
> - if (tb[IFLA_MASTER])
> - master_idx = nla_get_u32(tb[IFLA_MASTER]);
> -
> - if (tb[IFLA_LINKINFO])
> - kind_ops = linkinfo_to_kind_ops(tb[IFLA_LINKINFO]);
> -
> - if (master_idx || kind_ops)
> - flags |= NLM_F_DUMP_FILTERED;
> }
>
> + if (master_idx || kind_ops)
> + flags |= NLM_F_DUMP_FILTERED;
> +
> +walk_entries:
> for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
> idx = 0;
> head = &tgt_net->dev_index_head[h];
> @@ -1941,8 +1995,7 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
> err = rtnl_fill_ifinfo(skb, dev, net,
> RTM_NEWLINK,
> NETLINK_CB(cb->skb).portid,
> - cb->nlh->nlmsg_seq, 0,
> - flags,
> + nlh->nlmsg_seq, 0, flags,
> ext_filter_mask, 0, NULL, 0,
> netnsid);
>
> --
> 2.11.0
>
^ permalink raw reply
* Re: [v3, 6/6] net: dpaa2: fix and improve dpaa2-ptp driver
From: David Miller @ 2018-10-08 17:24 UTC (permalink / raw)
To: yangbo.lu; +Cc: devel, andrew, netdev, richardcochran, linux-kernel, gregkh
In-Reply-To: <20181008074430.34379-6-yangbo.lu@nxp.com>
From: Yangbo Lu <yangbo.lu@nxp.com>
Date: Mon, 8 Oct 2018 15:44:30 +0800
> This patch is to fix and improve dpaa2-ptp driver
> in some places.
>
> - Fixed the return for some functions.
> - Replaced kzalloc with devm_kzalloc.
> - Removed dev_set_drvdata(dev, NULL).
> - Made ptp_dpaa2_caps const.
>
> Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
Applied.
You can make things much easier for me and everyone else if you provide
a proper "[PATCH 0/N] ..." header posting with your patch series.
^ permalink raw reply
* Re: [v3, 5/6] net: dpaa2: remove unused code for dprtc
From: David Miller @ 2018-10-08 17:24 UTC (permalink / raw)
To: yangbo.lu
Cc: linux-kernel, devel, netdev, richardcochran, ruxandra.radulescu,
gregkh, andrew
In-Reply-To: <20181008074430.34379-5-yangbo.lu@nxp.com>
From: Yangbo Lu <yangbo.lu@nxp.com>
Date: Mon, 8 Oct 2018 15:44:29 +0800
> This patch is to removed unused code for dprtc.
> This code will be re-added along with more features
> of dpaa2-ptp added.
>
> Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
Applied.
^ permalink raw reply
* Re: [v3, 4/6] net: dpaa2: rename rtc as ptp in dpaa2-ptp driver
From: David Miller @ 2018-10-08 17:23 UTC (permalink / raw)
To: yangbo.lu; +Cc: devel, andrew, netdev, richardcochran, linux-kernel, gregkh
In-Reply-To: <20181008074430.34379-4-yangbo.lu@nxp.com>
From: Yangbo Lu <yangbo.lu@nxp.com>
Date: Mon, 8 Oct 2018 15:44:28 +0800
> In dpaa2-ptp driver, it's odd to use rtc in names of
> some functions and structures except these dprtc APIs.
> This patch is to use ptp instead of rtc in names.
>
> Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
Applied.
^ permalink raw reply
* Re: [v3, 2/6] MAINTAINERS: update files maintained under DPAA2 PTP/ETHERNET
From: David Miller @ 2018-10-08 17:23 UTC (permalink / raw)
To: yangbo.lu
Cc: linux-kernel, devel, netdev, richardcochran, ruxandra.radulescu,
gregkh, andrew
In-Reply-To: <20181008074430.34379-2-yangbo.lu@nxp.com>
From: Yangbo Lu <yangbo.lu@nxp.com>
Date: Mon, 8 Oct 2018 15:44:26 +0800
> The files maintained under DPAA2 PTP/ETHERNET needs to
> be updated since dpaa2 ptp driver had been moved into
> drivers/net/ethernet/freescale/dpaa2/.
>
> Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
Applied.
^ permalink raw reply
* Re: [v3, 1/6] net: dpaa2: move DPAA2 PTP driver out of staging/
From: David Miller @ 2018-10-08 17:23 UTC (permalink / raw)
To: yangbo.lu
Cc: linux-kernel, devel, netdev, richardcochran, ruxandra.radulescu,
gregkh, andrew
In-Reply-To: <20181008074430.34379-1-yangbo.lu@nxp.com>
From: Yangbo Lu <yangbo.lu@nxp.com>
Date: Mon, 8 Oct 2018 15:44:25 +0800
> This patch is to move DPAA2 PTP driver out of staging/
> since the dpaa2-eth had been moved out.
>
> Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
Applied.
^ permalink raw reply
* Re: [PATCH v2 net-next 08/23] net/ipv6: Update inet6_dump_addr for strict data checking
From: Christian Brauner @ 2018-10-08 10:10 UTC (permalink / raw)
To: David Ahern; +Cc: netdev, davem, jbenc, stephen, David Ahern
In-Reply-To: <20181008031644.15989-9-dsahern@kernel.org>
On Sun, Oct 07, 2018 at 08:16:29PM -0700, David Ahern wrote:
> From: David Ahern <dsahern@gmail.com>
>
> Update inet6_dump_addr for strict data checking. If the flag is set, the
> dump request is expected to have an ifaddrmsg struct as the header
> potentially followed by one or more attributes. Any data passed in the
> header or as an attribute is taken as a request to influence the data
> returned. Only values suppored by the dump handler are allowed to be
> non-0 or set in the request. At the moment only the IFA_TARGET_NETNSID
> attribute is supported. Follow on patches can add support for other fields
> (e.g., honor ifa_index and only return data for the given device index).
>
> Signed-off-by: David Ahern <dsahern@gmail.com>
Same as ipv4, looks way cleaner with the new *_strict() helper! :)
Acked-by: Christian Brauner <christian@brauner.io>
> ---
> net/ipv6/addrconf.c | 69 +++++++++++++++++++++++++++++++++++++++++++++--------
> 1 file changed, 59 insertions(+), 10 deletions(-)
>
> diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
> index afa279170ba5..095d3f56f0a9 100644
> --- a/net/ipv6/addrconf.c
> +++ b/net/ipv6/addrconf.c
> @@ -4998,9 +4998,62 @@ static int in6_dump_addrs(struct inet6_dev *idev, struct sk_buff *skb,
> return err;
> }
>
> +static int inet6_valid_dump_ifaddr_req(const struct nlmsghdr *nlh,
> + struct inet6_fill_args *fillargs,
> + struct net **tgt_net, struct sock *sk,
> + struct netlink_ext_ack *extack)
> +{
> + struct nlattr *tb[IFA_MAX+1];
> + struct ifaddrmsg *ifm;
> + int err, i;
> +
> + if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ifm))) {
> + NL_SET_ERR_MSG_MOD(extack, "Invalid header for address dump request");
> + return -EINVAL;
> + }
> +
> + ifm = nlmsg_data(nlh);
> + if (ifm->ifa_prefixlen || ifm->ifa_flags || ifm->ifa_scope) {
> + NL_SET_ERR_MSG_MOD(extack, "Invalid values in header for address dump request");
> + return -EINVAL;
> + }
> + if (ifm->ifa_index) {
> + NL_SET_ERR_MSG_MOD(extack, "Filter by device index not supported for address dump");
> + return -EINVAL;
> + }
> +
> + err = nlmsg_parse_strict(nlh, sizeof(*ifm), tb, IFA_MAX,
> + ifa_ipv6_policy, extack);
> + if (err < 0)
> + return err;
> +
> + for (i = 0; i <= IFA_MAX; ++i) {
> + if (!tb[i])
> + continue;
> +
> + if (i == IFA_TARGET_NETNSID) {
> + struct net *net;
> +
> + fillargs->netnsid = nla_get_s32(tb[i]);
> + net = rtnl_get_net_ns_capable(sk, fillargs->netnsid);
> + if (IS_ERR(net)) {
> + NL_SET_ERR_MSG_MOD(extack, "Invalid target network namespace id");
> + return PTR_ERR(net);
> + }
> + *tgt_net = net;
> + } else {
> + NL_SET_ERR_MSG_MOD(extack, "Unsupported attribute in dump request");
> + return -EINVAL;
> + }
> + }
> +
> + return 0;
> +}
> +
> static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb,
> enum addr_type_t type)
> {
> + const struct nlmsghdr *nlh = cb->nlh;
> struct inet6_fill_args fillargs = {
> .portid = NETLINK_CB(cb->skb).portid,
> .seq = cb->nlh->nlmsg_seq,
> @@ -5009,7 +5062,6 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb,
> .type = type,
> };
> struct net *net = sock_net(skb->sk);
> - struct nlattr *tb[IFA_MAX+1];
> struct net *tgt_net = net;
> int h, s_h;
> int idx, ip_idx;
> @@ -5022,16 +5074,13 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb,
> s_idx = idx = cb->args[1];
> s_ip_idx = ip_idx = cb->args[2];
>
> - if (nlmsg_parse(cb->nlh, sizeof(struct ifaddrmsg), tb, IFA_MAX,
> - ifa_ipv6_policy, cb->extack) >= 0) {
> - if (tb[IFA_TARGET_NETNSID]) {
> - fillargs.netnsid = nla_get_s32(tb[IFA_TARGET_NETNSID]);
> + if (cb->strict_check) {
> + int err;
>
> - tgt_net = rtnl_get_net_ns_capable(skb->sk,
> - fillargs.netnsid);
> - if (IS_ERR(tgt_net))
> - return PTR_ERR(tgt_net);
> - }
> + err = inet6_valid_dump_ifaddr_req(nlh, &fillargs, &tgt_net,
> + skb->sk, cb->extack);
> + if (err < 0)
> + return err;
> }
>
> rcu_read_lock();
> --
> 2.11.0
>
^ permalink raw reply
* [PATCH net-next v3 6/6] net: phy: mscc: remove unneeded temporary variable
From: Quentin Schulz @ 2018-10-08 10:07 UTC (permalink / raw)
To: davem, andrew, f.fainelli
Cc: allan.nielsen, linux-kernel, netdev, thomas.petazzoni,
alexandre.belloni, Quentin Schulz
In-Reply-To: <20181008100728.24959-1-quentin.schulz@bootlin.com>
Here, the rc variable is either used only for the condition right after
the assignment or right before being used as the return value of the
function it's being used in.
So let's remove this unneeded temporary variable whenever possible.
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Quentin Schulz <quentin.schulz@bootlin.com>
---
drivers/net/phy/mscc.c | 12 ++++--------
1 file changed, 4 insertions(+), 8 deletions(-)
diff --git a/drivers/net/phy/mscc.c b/drivers/net/phy/mscc.c
index 6bfdc168c62b..7ae3e644a18f 100644
--- a/drivers/net/phy/mscc.c
+++ b/drivers/net/phy/mscc.c
@@ -481,7 +481,7 @@ static void vsc85xx_wol_get(struct phy_device *phydev,
static int vsc85xx_edge_rate_magic_get(struct phy_device *phydev)
{
u32 vdd, sd;
- int rc, i, j;
+ int i, j;
struct device *dev = &phydev->mdio.dev;
struct device_node *of_node = dev->of_node;
u8 sd_array_size = ARRAY_SIZE(edge_table[0].slowdown);
@@ -489,12 +489,10 @@ static int vsc85xx_edge_rate_magic_get(struct phy_device *phydev)
if (!of_node)
return -ENODEV;
- rc = of_property_read_u32(of_node, "vsc8531,vddmac", &vdd);
- if (rc != 0)
+ if (of_property_read_u32(of_node, "vsc8531,vddmac", &vdd))
vdd = MSCC_VDDMAC_3300;
- rc = of_property_read_u32(of_node, "vsc8531,edge-slowdown", &sd);
- if (rc != 0)
+ if (of_property_read_u32(of_node, "vsc8531,edge-slowdown", &sd))
sd = 0;
for (i = 0; i < ARRAY_SIZE(edge_table); i++)
@@ -735,9 +733,7 @@ static int vsc85xx_config_init(struct phy_device *phydev)
return rc;
}
- rc = genphy_config_init(phydev);
-
- return rc;
+ return genphy_config_init(phydev);
}
static int vsc85xx_ack_interrupt(struct phy_device *phydev)
--
2.17.1
^ permalink raw reply related
* [PATCH net-next v3 1/6] net: phy: mscc: migrate to phy_select/restore_page functions
From: Quentin Schulz @ 2018-10-08 10:07 UTC (permalink / raw)
To: davem, andrew, f.fainelli
Cc: allan.nielsen, linux-kernel, netdev, thomas.petazzoni,
alexandre.belloni, Quentin Schulz
In-Reply-To: <20181008100728.24959-1-quentin.schulz@bootlin.com>
The Microsemi PHYs have multiple banks of registers (called pages).
Registers can only be accessed from one page, if we need a register from
another page, we need to switch the page and the registers of all other
pages are not accessible anymore.
Basically, to read register 5 from page 0, 1, 2, etc., you do the same
phy_read(phydev, 5); but you need to set the desired page beforehand.
In order to guarantee that two concurrent functions do not change the
page, we need to do some locking per page. This can be achieved with the
use of phy_select_page and phy_restore_page functions but phy_write/read
calls in-between those two functions shall be replaced by their
lock-free alternative __phy_write/read.
Let's migrate this driver to those functions.
Suggested-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Quentin Schulz <quentin.schulz@bootlin.com>
---
drivers/net/phy/mscc.c | 146 +++++++++++++++++------------------------
1 file changed, 62 insertions(+), 84 deletions(-)
diff --git a/drivers/net/phy/mscc.c b/drivers/net/phy/mscc.c
index 7d0384e26c99..52198be46c68 100644
--- a/drivers/net/phy/mscc.c
+++ b/drivers/net/phy/mscc.c
@@ -140,12 +140,14 @@ static const struct vsc8531_edge_rate_table edge_table[] = {
};
#endif /* CONFIG_OF_MDIO */
-static int vsc85xx_phy_page_set(struct phy_device *phydev, u16 page)
+static int vsc85xx_phy_read_page(struct phy_device *phydev)
{
- int rc;
+ return __phy_read(phydev, MSCC_EXT_PAGE_ACCESS);
+}
- rc = phy_write(phydev, MSCC_EXT_PAGE_ACCESS, page);
- return rc;
+static int vsc85xx_phy_write_page(struct phy_device *phydev, int page)
+{
+ return __phy_write(phydev, MSCC_EXT_PAGE_ACCESS, page);
}
static int vsc85xx_led_cntl_set(struct phy_device *phydev,
@@ -197,22 +199,17 @@ static int vsc85xx_mdix_set(struct phy_device *phydev, u8 mdix)
if (rc != 0)
return rc;
- rc = vsc85xx_phy_page_set(phydev, MSCC_PHY_PAGE_EXTENDED);
- if (rc != 0)
- return rc;
+ reg_val = 0;
- reg_val = phy_read(phydev, MSCC_PHY_EXT_MODE_CNTL);
- reg_val &= ~(FORCE_MDI_CROSSOVER_MASK);
if (mdix == ETH_TP_MDI)
- reg_val |= FORCE_MDI_CROSSOVER_MDI;
+ reg_val = FORCE_MDI_CROSSOVER_MDI;
else if (mdix == ETH_TP_MDI_X)
- reg_val |= FORCE_MDI_CROSSOVER_MDIX;
- rc = phy_write(phydev, MSCC_PHY_EXT_MODE_CNTL, reg_val);
- if (rc != 0)
- return rc;
+ reg_val = FORCE_MDI_CROSSOVER_MDIX;
- rc = vsc85xx_phy_page_set(phydev, MSCC_PHY_PAGE_STANDARD);
- if (rc != 0)
+ rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_EXTENDED,
+ MSCC_PHY_EXT_MODE_CNTL, FORCE_MDI_CROSSOVER_MASK,
+ reg_val);
+ if (rc < 0)
return rc;
return genphy_restart_aneg(phydev);
@@ -220,30 +217,24 @@ static int vsc85xx_mdix_set(struct phy_device *phydev, u8 mdix)
static int vsc85xx_downshift_get(struct phy_device *phydev, u8 *count)
{
- int rc;
u16 reg_val;
- rc = vsc85xx_phy_page_set(phydev, MSCC_PHY_PAGE_EXTENDED);
- if (rc != 0)
- goto out;
+ reg_val = phy_read_paged(phydev, MSCC_PHY_PAGE_EXTENDED,
+ MSCC_PHY_ACTIPHY_CNTL);
+ if (reg_val < 0)
+ return reg_val;
- reg_val = phy_read(phydev, MSCC_PHY_ACTIPHY_CNTL);
reg_val &= DOWNSHIFT_CNTL_MASK;
if (!(reg_val & DOWNSHIFT_EN))
*count = DOWNSHIFT_DEV_DISABLE;
else
*count = ((reg_val & ~DOWNSHIFT_EN) >> DOWNSHIFT_CNTL_POS) + 2;
- rc = vsc85xx_phy_page_set(phydev, MSCC_PHY_PAGE_STANDARD);
-out:
- return rc;
+ return 0;
}
static int vsc85xx_downshift_set(struct phy_device *phydev, u8 count)
{
- int rc;
- u16 reg_val;
-
if (count == DOWNSHIFT_DEV_DEFAULT_COUNT) {
/* Default downshift count 3 (i.e. Bit3:2 = 0b01) */
count = ((1 << DOWNSHIFT_CNTL_POS) | DOWNSHIFT_EN);
@@ -255,21 +246,9 @@ static int vsc85xx_downshift_set(struct phy_device *phydev, u8 count)
count = (((count - 2) << DOWNSHIFT_CNTL_POS) | DOWNSHIFT_EN);
}
- rc = vsc85xx_phy_page_set(phydev, MSCC_PHY_PAGE_EXTENDED);
- if (rc != 0)
- goto out;
-
- reg_val = phy_read(phydev, MSCC_PHY_ACTIPHY_CNTL);
- reg_val &= ~(DOWNSHIFT_CNTL_MASK);
- reg_val |= count;
- rc = phy_write(phydev, MSCC_PHY_ACTIPHY_CNTL, reg_val);
- if (rc != 0)
- goto out;
-
- rc = vsc85xx_phy_page_set(phydev, MSCC_PHY_PAGE_STANDARD);
-
-out:
- return rc;
+ return phy_modify_paged(phydev, MSCC_PHY_PAGE_EXTENDED,
+ MSCC_PHY_ACTIPHY_CNTL, DOWNSHIFT_CNTL_MASK,
+ count);
}
static int vsc85xx_wol_set(struct phy_device *phydev,
@@ -283,46 +262,48 @@ static int vsc85xx_wol_set(struct phy_device *phydev,
u8 *mac_addr = phydev->attached_dev->dev_addr;
mutex_lock(&phydev->lock);
- rc = vsc85xx_phy_page_set(phydev, MSCC_PHY_PAGE_EXTENDED_2);
- if (rc != 0)
+ rc = phy_select_page(phydev, MSCC_PHY_PAGE_EXTENDED_2);
+ if (rc < 0) {
+ rc = phy_restore_page(phydev, rc, rc);
goto out_unlock;
+ }
if (wol->wolopts & WAKE_MAGIC) {
/* Store the device address for the magic packet */
for (i = 0; i < ARRAY_SIZE(pwd); i++)
pwd[i] = mac_addr[5 - (i * 2 + 1)] << 8 |
mac_addr[5 - i * 2];
- phy_write(phydev, MSCC_PHY_WOL_LOWER_MAC_ADDR, pwd[0]);
- phy_write(phydev, MSCC_PHY_WOL_MID_MAC_ADDR, pwd[1]);
- phy_write(phydev, MSCC_PHY_WOL_UPPER_MAC_ADDR, pwd[2]);
+ __phy_write(phydev, MSCC_PHY_WOL_LOWER_MAC_ADDR, pwd[0]);
+ __phy_write(phydev, MSCC_PHY_WOL_MID_MAC_ADDR, pwd[1]);
+ __phy_write(phydev, MSCC_PHY_WOL_UPPER_MAC_ADDR, pwd[2]);
} else {
- phy_write(phydev, MSCC_PHY_WOL_LOWER_MAC_ADDR, 0);
- phy_write(phydev, MSCC_PHY_WOL_MID_MAC_ADDR, 0);
- phy_write(phydev, MSCC_PHY_WOL_UPPER_MAC_ADDR, 0);
+ __phy_write(phydev, MSCC_PHY_WOL_LOWER_MAC_ADDR, 0);
+ __phy_write(phydev, MSCC_PHY_WOL_MID_MAC_ADDR, 0);
+ __phy_write(phydev, MSCC_PHY_WOL_UPPER_MAC_ADDR, 0);
}
if (wol_conf->wolopts & WAKE_MAGICSECURE) {
for (i = 0; i < ARRAY_SIZE(pwd); i++)
pwd[i] = wol_conf->sopass[5 - (i * 2 + 1)] << 8 |
wol_conf->sopass[5 - i * 2];
- phy_write(phydev, MSCC_PHY_WOL_LOWER_PASSWD, pwd[0]);
- phy_write(phydev, MSCC_PHY_WOL_MID_PASSWD, pwd[1]);
- phy_write(phydev, MSCC_PHY_WOL_UPPER_PASSWD, pwd[2]);
+ __phy_write(phydev, MSCC_PHY_WOL_LOWER_PASSWD, pwd[0]);
+ __phy_write(phydev, MSCC_PHY_WOL_MID_PASSWD, pwd[1]);
+ __phy_write(phydev, MSCC_PHY_WOL_UPPER_PASSWD, pwd[2]);
} else {
- phy_write(phydev, MSCC_PHY_WOL_LOWER_PASSWD, 0);
- phy_write(phydev, MSCC_PHY_WOL_MID_PASSWD, 0);
- phy_write(phydev, MSCC_PHY_WOL_UPPER_PASSWD, 0);
+ __phy_write(phydev, MSCC_PHY_WOL_LOWER_PASSWD, 0);
+ __phy_write(phydev, MSCC_PHY_WOL_MID_PASSWD, 0);
+ __phy_write(phydev, MSCC_PHY_WOL_UPPER_PASSWD, 0);
}
- reg_val = phy_read(phydev, MSCC_PHY_WOL_MAC_CONTROL);
+ reg_val = __phy_read(phydev, MSCC_PHY_WOL_MAC_CONTROL);
if (wol_conf->wolopts & WAKE_MAGICSECURE)
reg_val |= SECURE_ON_ENABLE;
else
reg_val &= ~SECURE_ON_ENABLE;
- phy_write(phydev, MSCC_PHY_WOL_MAC_CONTROL, reg_val);
+ __phy_write(phydev, MSCC_PHY_WOL_MAC_CONTROL, reg_val);
- rc = vsc85xx_phy_page_set(phydev, MSCC_PHY_PAGE_STANDARD);
- if (rc != 0)
+ rc = phy_restore_page(phydev, rc, rc > 0 ? 0 : rc);
+ if (rc < 0)
goto out_unlock;
if (wol->wolopts & WAKE_MAGIC) {
@@ -359,17 +340,17 @@ static void vsc85xx_wol_get(struct phy_device *phydev,
struct ethtool_wolinfo *wol_conf = wol;
mutex_lock(&phydev->lock);
- rc = vsc85xx_phy_page_set(phydev, MSCC_PHY_PAGE_EXTENDED_2);
- if (rc != 0)
+ rc = phy_select_page(phydev, MSCC_PHY_PAGE_EXTENDED_2);
+ if (rc < 0)
goto out_unlock;
- reg_val = phy_read(phydev, MSCC_PHY_WOL_MAC_CONTROL);
+ reg_val = __phy_read(phydev, MSCC_PHY_WOL_MAC_CONTROL);
if (reg_val & SECURE_ON_ENABLE)
wol_conf->wolopts |= WAKE_MAGICSECURE;
if (wol_conf->wolopts & WAKE_MAGICSECURE) {
- pwd[0] = phy_read(phydev, MSCC_PHY_WOL_LOWER_PASSWD);
- pwd[1] = phy_read(phydev, MSCC_PHY_WOL_MID_PASSWD);
- pwd[2] = phy_read(phydev, MSCC_PHY_WOL_UPPER_PASSWD);
+ pwd[0] = __phy_read(phydev, MSCC_PHY_WOL_LOWER_PASSWD);
+ pwd[1] = __phy_read(phydev, MSCC_PHY_WOL_MID_PASSWD);
+ pwd[2] = __phy_read(phydev, MSCC_PHY_WOL_UPPER_PASSWD);
for (i = 0; i < ARRAY_SIZE(pwd); i++) {
wol_conf->sopass[5 - i * 2] = pwd[i] & 0x00ff;
wol_conf->sopass[5 - (i * 2 + 1)] = (pwd[i] & 0xff00)
@@ -377,9 +358,8 @@ static void vsc85xx_wol_get(struct phy_device *phydev,
}
}
- rc = vsc85xx_phy_page_set(phydev, MSCC_PHY_PAGE_STANDARD);
-
out_unlock:
+ phy_restore_page(phydev, rc, rc > 0 ? 0 : rc);
mutex_unlock(&phydev->lock);
}
@@ -474,21 +454,11 @@ static int vsc85xx_dt_led_modes_get(struct phy_device *phydev,
static int vsc85xx_edge_rate_cntl_set(struct phy_device *phydev, u8 edge_rate)
{
int rc;
- u16 reg_val;
mutex_lock(&phydev->lock);
- rc = vsc85xx_phy_page_set(phydev, MSCC_PHY_PAGE_EXTENDED_2);
- if (rc != 0)
- goto out_unlock;
- reg_val = phy_read(phydev, MSCC_PHY_WOL_MAC_CONTROL);
- reg_val &= ~(EDGE_RATE_CNTL_MASK);
- reg_val |= (edge_rate << EDGE_RATE_CNTL_POS);
- rc = phy_write(phydev, MSCC_PHY_WOL_MAC_CONTROL, reg_val);
- if (rc != 0)
- goto out_unlock;
- rc = vsc85xx_phy_page_set(phydev, MSCC_PHY_PAGE_STANDARD);
-
-out_unlock:
+ rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_EXTENDED_2,
+ MSCC_PHY_WOL_MAC_CONTROL, EDGE_RATE_CNTL_MASK,
+ edge_rate << EDGE_RATE_CNTL_POS);
mutex_unlock(&phydev->lock);
return rc;
@@ -537,17 +507,17 @@ static int vsc85xx_default_config(struct phy_device *phydev)
phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
mutex_lock(&phydev->lock);
- rc = vsc85xx_phy_page_set(phydev, MSCC_PHY_PAGE_EXTENDED_2);
- if (rc != 0)
+ rc = phy_select_page(phydev, MSCC_PHY_PAGE_EXTENDED_2);
+ if (rc < 0)
goto out_unlock;
reg_val = phy_read(phydev, MSCC_PHY_RGMII_CNTL);
reg_val &= ~(RGMII_RX_CLK_DELAY_MASK);
reg_val |= (RGMII_RX_CLK_DELAY_1_1_NS << RGMII_RX_CLK_DELAY_POS);
phy_write(phydev, MSCC_PHY_RGMII_CNTL, reg_val);
- rc = vsc85xx_phy_page_set(phydev, MSCC_PHY_PAGE_STANDARD);
out_unlock:
+ rc = phy_restore_page(phydev, rc, rc > 0 ? 0 : rc);
mutex_unlock(&phydev->lock);
return rc;
@@ -699,6 +669,8 @@ static struct phy_driver vsc85xx_driver[] = {
.get_wol = &vsc85xx_wol_get,
.get_tunable = &vsc85xx_get_tunable,
.set_tunable = &vsc85xx_set_tunable,
+ .read_page = &vsc85xx_phy_read_page,
+ .write_page = &vsc85xx_phy_write_page,
},
{
.phy_id = PHY_ID_VSC8531,
@@ -720,6 +692,8 @@ static struct phy_driver vsc85xx_driver[] = {
.get_wol = &vsc85xx_wol_get,
.get_tunable = &vsc85xx_get_tunable,
.set_tunable = &vsc85xx_set_tunable,
+ .read_page = &vsc85xx_phy_read_page,
+ .write_page = &vsc85xx_phy_write_page,
},
{
.phy_id = PHY_ID_VSC8540,
@@ -741,6 +715,8 @@ static struct phy_driver vsc85xx_driver[] = {
.get_wol = &vsc85xx_wol_get,
.get_tunable = &vsc85xx_get_tunable,
.set_tunable = &vsc85xx_set_tunable,
+ .read_page = &vsc85xx_phy_read_page,
+ .write_page = &vsc85xx_phy_write_page,
},
{
.phy_id = PHY_ID_VSC8541,
@@ -762,6 +738,8 @@ static struct phy_driver vsc85xx_driver[] = {
.get_wol = &vsc85xx_wol_get,
.get_tunable = &vsc85xx_get_tunable,
.set_tunable = &vsc85xx_set_tunable,
+ .read_page = &vsc85xx_phy_read_page,
+ .write_page = &vsc85xx_phy_write_page,
}
};
--
2.17.1
^ permalink raw reply related
* Re: [PATCH v2 net-next 07/23] net/ipv4: Update inet_dump_ifaddr for strict data checking
From: Christian Brauner @ 2018-10-08 10:06 UTC (permalink / raw)
To: David Ahern; +Cc: netdev, davem, jbenc, stephen, David Ahern
In-Reply-To: <20181008031644.15989-8-dsahern@kernel.org>
On Sun, Oct 07, 2018 at 08:16:28PM -0700, David Ahern wrote:
> From: David Ahern <dsahern@gmail.com>
>
> Update inet_dump_ifaddr for strict data checking. If the flag is set,
> the dump request is expected to have an ifaddrmsg struct as the header
> potentially followed by one or more attributes. Any data passed in the
> header or as an attribute is taken as a request to influence the data
> returned. Only values supported by the dump handler are allowed to be
> non-0 or set in the request. At the moment only the IFA_TARGET_NETNSID
> attribute is supported. Follow on patches can support for other fields
> (e.g., honor ifa_index and only return data for the given device index).
>
> Signed-off-by: David Ahern <dsahern@gmail.com>
Thanks, with the *_strict() it looks way cleaner now.
Acked-by: Christian Brauner <christian@brauner.io>
> ---
> net/ipv4/devinet.c | 72 +++++++++++++++++++++++++++++++++++++++++++++---------
> 1 file changed, 61 insertions(+), 11 deletions(-)
>
> diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
> index ab2b11df5ea4..6f2bbd04e950 100644
> --- a/net/ipv4/devinet.c
> +++ b/net/ipv4/devinet.c
> @@ -1660,17 +1660,70 @@ static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa,
> return -EMSGSIZE;
> }
>
> +static int inet_valid_dump_ifaddr_req(const struct nlmsghdr *nlh,
> + struct inet_fill_args *fillargs,
> + struct net **tgt_net, struct sock *sk,
> + struct netlink_ext_ack *extack)
> +{
> + struct nlattr *tb[IFA_MAX+1];
> + struct ifaddrmsg *ifm;
> + int err, i;
> +
> + if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ifm))) {
> + NL_SET_ERR_MSG(extack, "ipv4: Invalid header for address dump request");
> + return -EINVAL;
> + }
> +
> + ifm = nlmsg_data(nlh);
> + if (ifm->ifa_prefixlen || ifm->ifa_flags || ifm->ifa_scope) {
> + NL_SET_ERR_MSG(extack, "ipv4: Invalid values in header for address dump request");
> + return -EINVAL;
> + }
> + if (ifm->ifa_index) {
> + NL_SET_ERR_MSG(extack, "ipv4: Filter by device index not supported for address dump");
> + return -EINVAL;
> + }
> +
> + err = nlmsg_parse_strict(nlh, sizeof(*ifm), tb, IFA_MAX,
> + ifa_ipv4_policy, extack);
> + if (err < 0)
> + return err;
> +
> + for (i = 0; i <= IFA_MAX; ++i) {
> + if (!tb[i])
> + continue;
> +
> + if (i == IFA_TARGET_NETNSID) {
> + struct net *net;
> +
> + fillargs->netnsid = nla_get_s32(tb[i]);
> +
> + net = rtnl_get_net_ns_capable(sk, fillargs->netnsid);
> + if (IS_ERR(net)) {
> + NL_SET_ERR_MSG(extack, "ipv4: Invalid target network namespace id");
> + return PTR_ERR(net);
> + }
> + *tgt_net = net;
> + } else {
> + NL_SET_ERR_MSG(extack, "ipv4: Unsupported attribute in dump request");
> + return -EINVAL;
> + }
> + }
> +
> + return 0;
> +}
> +
> static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
> {
> + const struct nlmsghdr *nlh = cb->nlh;
> struct inet_fill_args fillargs = {
> .portid = NETLINK_CB(cb->skb).portid,
> - .seq = cb->nlh->nlmsg_seq,
> + .seq = nlh->nlmsg_seq,
> .event = RTM_NEWADDR,
> .flags = NLM_F_MULTI,
> .netnsid = -1,
> };
> struct net *net = sock_net(skb->sk);
> - struct nlattr *tb[IFA_MAX+1];
> struct net *tgt_net = net;
> int h, s_h;
> int idx, s_idx;
> @@ -1684,16 +1737,13 @@ static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
> s_idx = idx = cb->args[1];
> s_ip_idx = ip_idx = cb->args[2];
>
> - if (nlmsg_parse(cb->nlh, sizeof(struct ifaddrmsg), tb, IFA_MAX,
> - ifa_ipv4_policy, cb->extack) >= 0) {
> - if (tb[IFA_TARGET_NETNSID]) {
> - fillargs.netnsid = nla_get_s32(tb[IFA_TARGET_NETNSID]);
> + if (cb->strict_check) {
> + int err;
>
> - tgt_net = rtnl_get_net_ns_capable(skb->sk,
> - fillargs.netnsid);
> - if (IS_ERR(tgt_net))
> - return PTR_ERR(tgt_net);
> - }
> + err = inet_valid_dump_ifaddr_req(nlh, &fillargs, &tgt_net,
> + skb->sk, cb->extack);
> + if (err < 0)
> + return err;
> }
>
> for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
> --
> 2.11.0
>
^ permalink raw reply
* Re: [PATCH v2 net-next 06/23] netlink: Add new socket option to enable strict checking on dumps
From: Christian Brauner @ 2018-10-08 10:04 UTC (permalink / raw)
To: David Ahern; +Cc: netdev, davem, jbenc, stephen, David Ahern
In-Reply-To: <20181008031644.15989-7-dsahern@kernel.org>
On Sun, Oct 07, 2018 at 08:16:27PM -0700, David Ahern wrote:
> From: David Ahern <dsahern@gmail.com>
>
> Add a new socket option, NETLINK_DUMP_STRICT_CHK, that userspace
> can use via setsockopt to request strict checking of headers and
> attributes on dump requests.
>
> To get dump features such as kernel side filtering based on data in
> the header or attributes appended to the dump request, userspace
> must call setsockopt() for NETLINK_DUMP_STRICT_CHK and a non-zero
> value. Since the netlink sock and its flags are private to the
> af_netlink code, the strict checking flag is passed to dump handlers
> via a flag in the netlink_callback struct.
>
> For old userspace on new kernel there is no impact as all of the data
> checks in later patches are wrapped in a check on the new strict flag.
>
> For new userspace on old kernel, the setsockopt will fail and even if
> new userspace sets data in the headers and appended attributes the
> kernel will silently ignore it. Moving forward when the setsockopt
> succeeds, the new userspace on old kernel means the dump request can
> pass an attribute the kernel does not understand. The dump will then
> fail as the older kernel does not understand it.
>
> New userspace on new kernel setting the socket option gets the benefit
> of the improved data dump.
>
> Kernel side the NETLINK_DUMP_STRICT_CHK uapi is converted to a generic
> NETLINK_F_STRICT_CHK flag which can potentially be leveraged for tighter
> checking on the NEW, DEL, and SET commands.
>
> Signed-off-by: David Ahern <dsahern@gmail.com>
Thanks for the bool. :)
Acked-by: Christian Brauner <christian@brauner.io>
> ---
> include/linux/netlink.h | 1 +
> include/uapi/linux/netlink.h | 1 +
> net/netlink/af_netlink.c | 21 ++++++++++++++++++++-
> net/netlink/af_netlink.h | 1 +
> 4 files changed, 23 insertions(+), 1 deletion(-)
>
> diff --git a/include/linux/netlink.h b/include/linux/netlink.h
> index 88c8a2d83eb3..72580f1a72a2 100644
> --- a/include/linux/netlink.h
> +++ b/include/linux/netlink.h
> @@ -179,6 +179,7 @@ struct netlink_callback {
> struct netlink_ext_ack *extack;
> u16 family;
> u16 min_dump_alloc;
> + bool strict_check;
> unsigned int prev_seq, seq;
> long args[6];
> };
> diff --git a/include/uapi/linux/netlink.h b/include/uapi/linux/netlink.h
> index 776bc92e9118..486ed1f0c0bc 100644
> --- a/include/uapi/linux/netlink.h
> +++ b/include/uapi/linux/netlink.h
> @@ -155,6 +155,7 @@ enum nlmsgerr_attrs {
> #define NETLINK_LIST_MEMBERSHIPS 9
> #define NETLINK_CAP_ACK 10
> #define NETLINK_EXT_ACK 11
> +#define NETLINK_DUMP_STRICT_CHK 12
>
> struct nl_pktinfo {
> __u32 group;
> diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
> index 7ac585f33a9e..e613a9f89600 100644
> --- a/net/netlink/af_netlink.c
> +++ b/net/netlink/af_netlink.c
> @@ -1706,6 +1706,13 @@ static int netlink_setsockopt(struct socket *sock, int level, int optname,
> nlk->flags &= ~NETLINK_F_EXT_ACK;
> err = 0;
> break;
> + case NETLINK_DUMP_STRICT_CHK:
> + if (val)
> + nlk->flags |= NETLINK_F_STRICT_CHK;
> + else
> + nlk->flags &= ~NETLINK_F_STRICT_CHK;
> + err = 0;
> + break;
> default:
> err = -ENOPROTOOPT;
> }
> @@ -1799,6 +1806,15 @@ static int netlink_getsockopt(struct socket *sock, int level, int optname,
> return -EFAULT;
> err = 0;
> break;
> + case NETLINK_DUMP_STRICT_CHK:
> + if (len < sizeof(int))
> + return -EINVAL;
> + len = sizeof(int);
> + val = nlk->flags & NETLINK_F_STRICT_CHK ? 1 : 0;
> + if (put_user(len, optlen) || put_user(val, optval))
> + return -EFAULT;
> + err = 0;
> + break;
> default:
> err = -ENOPROTOOPT;
> }
> @@ -2282,9 +2298,9 @@ int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
> const struct nlmsghdr *nlh,
> struct netlink_dump_control *control)
> {
> + struct netlink_sock *nlk, *nlk2;
> struct netlink_callback *cb;
> struct sock *sk;
> - struct netlink_sock *nlk;
> int ret;
>
> refcount_inc(&skb->users);
> @@ -2318,6 +2334,9 @@ int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
> cb->min_dump_alloc = control->min_dump_alloc;
> cb->skb = skb;
>
> + nlk2 = nlk_sk(NETLINK_CB(skb).sk);
> + cb->strict_check = !!(nlk2->flags & NETLINK_F_STRICT_CHK);
> +
> if (control->start) {
> ret = control->start(cb);
> if (ret)
> diff --git a/net/netlink/af_netlink.h b/net/netlink/af_netlink.h
> index 962de7b3c023..5f454c8de6a4 100644
> --- a/net/netlink/af_netlink.h
> +++ b/net/netlink/af_netlink.h
> @@ -15,6 +15,7 @@
> #define NETLINK_F_LISTEN_ALL_NSID 0x10
> #define NETLINK_F_CAP_ACK 0x20
> #define NETLINK_F_EXT_ACK 0x40
> +#define NETLINK_F_STRICT_CHK 0x80
>
> #define NLGRPSZ(x) (ALIGN(x, sizeof(unsigned long) * 8) / 8)
> #define NLGRPLONGS(x) (NLGRPSZ(x)/sizeof(unsigned long))
> --
> 2.11.0
>
^ permalink raw reply
* Re: [PATCH v2 net-next 04/23] netlink: Add strict version of nlmsg_parse and nla_parse
From: Christian Brauner @ 2018-10-08 9:52 UTC (permalink / raw)
To: David Ahern; +Cc: netdev, davem, jbenc, stephen, David Ahern
In-Reply-To: <20181008031644.15989-5-dsahern@kernel.org>
On Sun, Oct 07, 2018 at 08:16:25PM -0700, David Ahern wrote:
> From: David Ahern <dsahern@gmail.com>
>
> nla_parse is currently lenient on message parsing, allowing type to be 0
> or greater than max expected and only logging a message
>
> "netlink: %d bytes leftover after parsing attributes in process `%s'."
>
> if the netlink message has unknown data at the end after parsing. What this
> could mean is that the header at the front of the attributes is actually
> wrong and the parsing is shifted from what is expected.
>
> Add a new strict version that actually fails with EINVAL if there are any
> bytes remaining after the parsing loop completes, if the atttrbitue type
> is 0 or greater than max expected.
>
> Signed-off-by: David Ahern <dsahern@gmail.com>
+1
Acked-by: Christian Brauner <christian@brauner.io>
> ---
> include/net/netlink.h | 17 +++++++++++++++++
> lib/nlattr.c | 48 ++++++++++++++++++++++++++++++++++++------------
> 2 files changed, 53 insertions(+), 12 deletions(-)
>
> diff --git a/include/net/netlink.h b/include/net/netlink.h
> index 9522a0bf1f3a..f1db8e594847 100644
> --- a/include/net/netlink.h
> +++ b/include/net/netlink.h
> @@ -373,6 +373,9 @@ int nla_validate(const struct nlattr *head, int len, int maxtype,
> int nla_parse(struct nlattr **tb, int maxtype, const struct nlattr *head,
> int len, const struct nla_policy *policy,
> struct netlink_ext_ack *extack);
> +int nla_parse_strict(struct nlattr **tb, int maxtype, const struct nlattr *head,
> + int len, const struct nla_policy *policy,
> + struct netlink_ext_ack *extack);
> int nla_policy_len(const struct nla_policy *, int);
> struct nlattr *nla_find(const struct nlattr *head, int len, int attrtype);
> size_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize);
> @@ -525,6 +528,20 @@ static inline int nlmsg_parse(const struct nlmsghdr *nlh, int hdrlen,
> nlmsg_attrlen(nlh, hdrlen), policy, extack);
> }
>
> +static inline int nlmsg_parse_strict(const struct nlmsghdr *nlh, int hdrlen,
> + struct nlattr *tb[], int maxtype,
> + const struct nla_policy *policy,
> + struct netlink_ext_ack *extack)
> +{
> + if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen)) {
> + NL_SET_ERR_MSG(extack, "Invalid header length");
> + return -EINVAL;
> + }
> +
> + return nla_parse_strict(tb, maxtype, nlmsg_attrdata(nlh, hdrlen),
> + nlmsg_attrlen(nlh, hdrlen), policy, extack);
> +}
> +
> /**
> * nlmsg_find_attr - find a specific attribute in a netlink message
> * @nlh: netlink message header
> diff --git a/lib/nlattr.c b/lib/nlattr.c
> index 1e900bb414ef..d26de6156b97 100644
> --- a/lib/nlattr.c
> +++ b/lib/nlattr.c
> @@ -391,9 +391,10 @@ EXPORT_SYMBOL(nla_policy_len);
> *
> * Returns 0 on success or a negative error code.
> */
> -int nla_parse(struct nlattr **tb, int maxtype, const struct nlattr *head,
> - int len, const struct nla_policy *policy,
> - struct netlink_ext_ack *extack)
> +static int __nla_parse(struct nlattr **tb, int maxtype,
> + const struct nlattr *head, int len,
> + bool strict, const struct nla_policy *policy,
> + struct netlink_ext_ack *extack)
> {
> const struct nlattr *nla;
> int rem;
> @@ -403,27 +404,50 @@ int nla_parse(struct nlattr **tb, int maxtype, const struct nlattr *head,
> nla_for_each_attr(nla, head, len, rem) {
> u16 type = nla_type(nla);
>
> - if (type > 0 && type <= maxtype) {
> - if (policy) {
> - int err = validate_nla(nla, maxtype, policy,
> - extack);
> -
> - if (err < 0)
> - return err;
> + if (type == 0 || type > maxtype) {
> + if (strict) {
> + NL_SET_ERR_MSG(extack, "Unknown attribute type");
> + return -EINVAL;
> }
> + continue;
> + }
> + if (policy) {
> + int err = validate_nla(nla, maxtype, policy, extack);
>
> - tb[type] = (struct nlattr *)nla;
> + if (err < 0)
> + return err;
> }
> +
> + tb[type] = (struct nlattr *)nla;
> }
>
> - if (unlikely(rem > 0))
> + if (unlikely(rem > 0)) {
> pr_warn_ratelimited("netlink: %d bytes leftover after parsing attributes in process `%s'.\n",
> rem, current->comm);
> + NL_SET_ERR_MSG(extack, "bytes leftover after parsing attributes");
> + if (strict)
> + return -EINVAL;
> + }
>
> return 0;
> }
> +
> +int nla_parse(struct nlattr **tb, int maxtype, const struct nlattr *head,
> + int len, const struct nla_policy *policy,
> + struct netlink_ext_ack *extack)
> +{
> + return __nla_parse(tb, maxtype, head, len, false, policy, extack);
> +}
> EXPORT_SYMBOL(nla_parse);
>
> +int nla_parse_strict(struct nlattr **tb, int maxtype, const struct nlattr *head,
> + int len, const struct nla_policy *policy,
> + struct netlink_ext_ack *extack)
> +{
> + return __nla_parse(tb, maxtype, head, len, true, policy, extack);
> +}
> +EXPORT_SYMBOL(nla_parse_strict);
> +
> /**
> * nla_find - Find a specific attribute in a stream of attributes
> * @head: head of attribute stream
> --
> 2.11.0
>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox