Netdev List
 help / color / mirror / Atom feed
* [PATCH net-next 1/2] virtio_net: Introduce VIRTIO_NET_F_MASTER feature bit
From: Sridhar Samudrala @ 2018-01-03  0:35 UTC (permalink / raw)
  To: mst, stephen, netdev, virtualization, virtio-dev,
	jesse.brandeburg, sridhar.samudrala
In-Reply-To: <1514939738-22423-1-git-send-email-sridhar.samudrala@intel.com>

This feature bit can be used by hypervisor to indicate virtio_net device to
act as a master for a directly attached passthru device with the same MAC
address.

Signed-off-by: Sridhar Samudrala <sridhar.samudrala@intel.com>
---
 drivers/net/virtio_net.c        | 3 ++-
 include/uapi/linux/virtio_net.h | 1 +
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 6fb7b658a6cc..46844a1d9a62 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -2796,7 +2796,8 @@ static struct virtio_device_id id_table[] = {
 	VIRTIO_NET_F_CTRL_RX, VIRTIO_NET_F_CTRL_VLAN, \
 	VIRTIO_NET_F_GUEST_ANNOUNCE, VIRTIO_NET_F_MQ, \
 	VIRTIO_NET_F_CTRL_MAC_ADDR, \
-	VIRTIO_NET_F_MTU, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS
+	VIRTIO_NET_F_MTU, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS, \
+	VIRTIO_NET_F_MASTER
 
 static unsigned int features[] = {
 	VIRTNET_FEATURES,
diff --git a/include/uapi/linux/virtio_net.h b/include/uapi/linux/virtio_net.h
index fc353b518288..a9b4e0836786 100644
--- a/include/uapi/linux/virtio_net.h
+++ b/include/uapi/linux/virtio_net.h
@@ -56,6 +56,7 @@
 #define VIRTIO_NET_F_MQ	22	/* Device supports Receive Flow
 					 * Steering */
 #define VIRTIO_NET_F_CTRL_MAC_ADDR 23	/* Set MAC address */
+#define VIRTIO_NET_F_MASTER	62	/* act as master for a VF device */
 
 #ifndef VIRTIO_NET_NO_LEGACY
 #define VIRTIO_NET_F_GSO	6	/* Host handles pkts w/ any GSO type */
-- 
2.14.3

^ permalink raw reply related

* [PATCH net-next 2/2] virtio_net: Extend virtio to use VF datapath when available
From: Sridhar Samudrala @ 2018-01-03  0:35 UTC (permalink / raw)
  To: mst, stephen, netdev, virtualization, virtio-dev,
	jesse.brandeburg, sridhar.samudrala
In-Reply-To: <1514939738-22423-1-git-send-email-sridhar.samudrala@intel.com>

This patch enables virtio to switch over to a VF datapath when a VF netdev
is present with the same MAC address.  It allows live migration of a VM
with a direct attached VF without the need to setup a bond/team between a
VF and virtio net device in the guest.

The hypervisor needs to unplug the VF device from the guest on the source
host and reset the MAC filter of the VF to initiate failover of datapath to
virtio before starting the migration. After the migration is completed, the
destination hypervisor sets the MAC filter on the VF and plugs it back to
the guest to switch over to VF datapath.

This patch is based on the discussion initiated by Jesse on this thread.
https://marc.info/?l=linux-virtualization&m=151189725224231&w=2

Signed-off-by: Sridhar Samudrala <sridhar.samudrala@intel.com>
Reviewed-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
---
 drivers/net/virtio_net.c | 305 ++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 303 insertions(+), 2 deletions(-)

diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 46844a1d9a62..6516dcb55b7d 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -31,6 +31,8 @@
 #include <linux/average.h>
 #include <linux/filter.h>
 #include <net/route.h>
+#include <linux/netdevice.h>
+#include <linux/netpoll.h>
 
 static int napi_weight = NAPI_POLL_WEIGHT;
 module_param(napi_weight, int, 0444);
@@ -117,6 +119,15 @@ struct receive_queue {
 	char name[40];
 };
 
+struct virtnet_vf_pcpu_stats {
+	u64	rx_packets;
+	u64	rx_bytes;
+	u64	tx_packets;
+	u64	tx_bytes;
+	struct u64_stats_sync   syncp;
+	u32	tx_dropped;
+};
+
 struct virtnet_info {
 	struct virtio_device *vdev;
 	struct virtqueue *cvq;
@@ -179,6 +190,10 @@ struct virtnet_info {
 	u32 speed;
 
 	unsigned long guest_offloads;
+
+	/* State to manage the associated VF interface. */
+	struct net_device __rcu *vf_netdev;
+	struct virtnet_vf_pcpu_stats __percpu *vf_stats;
 };
 
 struct padded_vnet_hdr {
@@ -1303,16 +1318,51 @@ static int xmit_skb(struct send_queue *sq, struct sk_buff *skb)
 	return virtqueue_add_outbuf(sq->vq, sq->sg, num_sg, skb, GFP_ATOMIC);
 }
 
+/* Send skb on the slave VF device. */
+static int virtnet_vf_xmit(struct net_device *dev, struct net_device *vf_netdev,
+			   struct sk_buff *skb)
+{
+	struct virtnet_info *vi = netdev_priv(dev);
+	unsigned int len = skb->len;
+	int rc;
+
+	skb->dev = vf_netdev;
+	skb->queue_mapping = qdisc_skb_cb(skb)->slave_dev_queue_mapping;
+
+	rc = dev_queue_xmit(skb);
+	if (likely(rc == NET_XMIT_SUCCESS || rc == NET_XMIT_CN)) {
+		struct virtnet_vf_pcpu_stats *pcpu_stats
+			= this_cpu_ptr(vi->vf_stats);
+
+		u64_stats_update_begin(&pcpu_stats->syncp);
+		pcpu_stats->tx_packets++;
+		pcpu_stats->tx_bytes += len;
+		u64_stats_update_end(&pcpu_stats->syncp);
+	} else {
+		this_cpu_inc(vi->vf_stats->tx_dropped);
+	}
+
+	return rc;
+}
+
 static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct virtnet_info *vi = netdev_priv(dev);
 	int qnum = skb_get_queue_mapping(skb);
 	struct send_queue *sq = &vi->sq[qnum];
+	struct net_device *vf_netdev;
 	int err;
 	struct netdev_queue *txq = netdev_get_tx_queue(dev, qnum);
 	bool kick = !skb->xmit_more;
 	bool use_napi = sq->napi.weight;
 
+	/* If VF is present and up then redirect packets
+	 * called with rcu_read_lock_bh
+	 */
+	vf_netdev = rcu_dereference_bh(vi->vf_netdev);
+	if (vf_netdev && netif_running(vf_netdev) && !netpoll_tx_running(dev))
+		return virtnet_vf_xmit(dev, vf_netdev, skb);
+
 	/* Free up any pending old buffers before queueing new ones. */
 	free_old_xmit_skbs(sq);
 
@@ -1459,10 +1509,41 @@ static int virtnet_set_mac_address(struct net_device *dev, void *p)
 	return ret;
 }
 
+static void virtnet_get_vf_stats(struct net_device *dev,
+				 struct virtnet_vf_pcpu_stats *tot)
+{
+	struct virtnet_info *vi = netdev_priv(dev);
+	int i;
+
+	memset(tot, 0, sizeof(*tot));
+
+	for_each_possible_cpu(i) {
+		const struct virtnet_vf_pcpu_stats *stats
+				= per_cpu_ptr(vi->vf_stats, i);
+		u64 rx_packets, rx_bytes, tx_packets, tx_bytes;
+		unsigned int start;
+
+		do {
+			start = u64_stats_fetch_begin_irq(&stats->syncp);
+			rx_packets = stats->rx_packets;
+			tx_packets = stats->tx_packets;
+			rx_bytes = stats->rx_bytes;
+			tx_bytes = stats->tx_bytes;
+		} while (u64_stats_fetch_retry_irq(&stats->syncp, start));
+
+		tot->rx_packets += rx_packets;
+		tot->tx_packets += tx_packets;
+		tot->rx_bytes   += rx_bytes;
+		tot->tx_bytes   += tx_bytes;
+		tot->tx_dropped += stats->tx_dropped;
+	}
+}
+
 static void virtnet_stats(struct net_device *dev,
 			  struct rtnl_link_stats64 *tot)
 {
 	struct virtnet_info *vi = netdev_priv(dev);
+	struct virtnet_vf_pcpu_stats vf_stats;
 	int cpu;
 	unsigned int start;
 
@@ -1493,6 +1574,13 @@ static void virtnet_stats(struct net_device *dev,
 	tot->rx_dropped = dev->stats.rx_dropped;
 	tot->rx_length_errors = dev->stats.rx_length_errors;
 	tot->rx_frame_errors = dev->stats.rx_frame_errors;
+
+	virtnet_get_vf_stats(dev, &vf_stats);
+	tot->rx_packets += vf_stats.rx_packets;
+	tot->tx_packets += vf_stats.tx_packets;
+	tot->rx_bytes += vf_stats.rx_bytes;
+	tot->tx_bytes += vf_stats.tx_bytes;
+	tot->tx_dropped += vf_stats.tx_dropped;
 }
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -2604,6 +2692,13 @@ static int virtnet_probe(struct virtio_device *vdev)
 
 	INIT_WORK(&vi->config_work, virtnet_config_changed_work);
 
+	if (virtio_has_feature(vdev, VIRTIO_NET_F_MASTER)) {
+		vi->vf_stats =
+			netdev_alloc_pcpu_stats(struct virtnet_vf_pcpu_stats);
+		if (!vi->vf_stats)
+			goto free_stats;
+	}
+
 	/* If we can receive ANY GSO packets, we must allocate large ones. */
 	if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO4) ||
 	    virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO6) ||
@@ -2637,7 +2732,7 @@ static int virtnet_probe(struct virtio_device *vdev)
 			 */
 			dev_err(&vdev->dev, "device MTU appears to have changed "
 				"it is now %d < %d", mtu, dev->min_mtu);
-			goto free_stats;
+			goto free_vf_stats;
 		}
 
 		dev->mtu = mtu;
@@ -2661,7 +2756,7 @@ static int virtnet_probe(struct virtio_device *vdev)
 	/* Allocate/initialize the rx/tx queues, and invoke find_vqs */
 	err = init_vqs(vi);
 	if (err)
-		goto free_stats;
+		goto free_vf_stats;
 
 #ifdef CONFIG_SYSFS
 	if (vi->mergeable_rx_bufs)
@@ -2715,6 +2810,8 @@ static int virtnet_probe(struct virtio_device *vdev)
 	cancel_delayed_work_sync(&vi->refill);
 	free_receive_page_frags(vi);
 	virtnet_del_vqs(vi);
+free_vf_stats:
+	free_percpu(vi->vf_stats);
 free_stats:
 	free_percpu(vi->stats);
 free:
@@ -2736,19 +2833,184 @@ static void remove_vq_common(struct virtnet_info *vi)
 	virtnet_del_vqs(vi);
 }
 
+static struct net_device *get_virtio_bymac(const u8 *mac)
+{
+	struct net_device *dev;
+
+	ASSERT_RTNL();
+
+	for_each_netdev(&init_net, dev) {
+		if (dev->netdev_ops != &virtnet_netdev)
+			continue;       /* not a virtio_net device */
+
+		if (ether_addr_equal(mac, dev->perm_addr))
+			return dev;
+	}
+
+	return NULL;
+}
+
+static struct net_device *get_virtio_byref(struct net_device *vf_netdev)
+{
+	struct net_device *dev;
+
+	ASSERT_RTNL();
+
+	for_each_netdev(&init_net, dev) {
+		struct virtnet_info *vi;
+
+		if (dev->netdev_ops != &virtnet_netdev)
+			continue;	/* not a virtio_net device */
+
+		vi = netdev_priv(dev);
+		if (rtnl_dereference(vi->vf_netdev) == vf_netdev)
+			return dev;	/* a match */
+	}
+
+	return NULL;
+}
+
+/* Called when VF is injecting data into network stack.
+ * Change the associated network device from VF to virtio.
+ * note: already called with rcu_read_lock
+ */
+static rx_handler_result_t virtnet_vf_handle_frame(struct sk_buff **pskb)
+{
+	struct sk_buff *skb = *pskb;
+	struct net_device *ndev = rcu_dereference(skb->dev->rx_handler_data);
+	struct virtnet_info *vi = netdev_priv(ndev);
+	struct virtnet_vf_pcpu_stats *pcpu_stats =
+				this_cpu_ptr(vi->vf_stats);
+
+	skb->dev = ndev;
+
+	u64_stats_update_begin(&pcpu_stats->syncp);
+	pcpu_stats->rx_packets++;
+	pcpu_stats->rx_bytes += skb->len;
+	u64_stats_update_end(&pcpu_stats->syncp);
+
+	return RX_HANDLER_ANOTHER;
+}
+
+static int virtnet_vf_join(struct net_device *vf_netdev,
+			   struct net_device *ndev)
+{
+	int ret;
+
+	ret = netdev_rx_handler_register(vf_netdev,
+					 virtnet_vf_handle_frame, ndev);
+	if (ret != 0) {
+		netdev_err(vf_netdev,
+			   "can not register virtio VF receive handler (err = %d)\n",
+			   ret);
+		goto rx_handler_failed;
+	}
+
+	ret = netdev_upper_dev_link(vf_netdev, ndev, NULL);
+	if (ret != 0) {
+		netdev_err(vf_netdev,
+			   "can not set master device %s (err = %d)\n",
+			   ndev->name, ret);
+		goto upper_link_failed;
+	}
+
+	vf_netdev->flags |= IFF_SLAVE;
+
+	/* Align MTU of VF with master */
+	ret = dev_set_mtu(vf_netdev, ndev->mtu);
+	if (ret)
+		netdev_warn(vf_netdev,
+			    "unable to change mtu to %u\n", ndev->mtu);
+
+	call_netdevice_notifiers(NETDEV_JOIN, vf_netdev);
+
+	netdev_info(vf_netdev, "joined to %s\n", ndev->name);
+	return 0;
+
+upper_link_failed:
+	netdev_rx_handler_unregister(vf_netdev);
+rx_handler_failed:
+	return ret;
+}
+
+static int virtnet_register_vf(struct net_device *vf_netdev)
+{
+	struct net_device *ndev;
+	struct virtnet_info *vi;
+
+	if (vf_netdev->addr_len != ETH_ALEN)
+		return NOTIFY_DONE;
+
+	/* We will use the MAC address to locate the virtio_net interface to
+	 * associate with the VF interface. If we don't find a matching
+	 * virtio interface, move on.
+	 */
+	ndev = get_virtio_bymac(vf_netdev->perm_addr);
+	if (!ndev)
+		return NOTIFY_DONE;
+
+	vi = netdev_priv(ndev);
+	if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_MASTER))
+		return NOTIFY_DONE;
+
+	if (rtnl_dereference(vi->vf_netdev))
+		return NOTIFY_DONE;
+
+	if (virtnet_vf_join(vf_netdev, ndev) != 0)
+		return NOTIFY_DONE;
+
+	netdev_info(ndev, "VF registering %s\n", vf_netdev->name);
+
+	dev_hold(vf_netdev);
+	rcu_assign_pointer(vi->vf_netdev, vf_netdev);
+
+	return NOTIFY_OK;
+}
+
+static int virtnet_unregister_vf(struct net_device *vf_netdev)
+{
+	struct net_device *ndev;
+	struct virtnet_info *vi;
+
+	ndev = get_virtio_byref(vf_netdev);
+	if (!ndev)
+		return NOTIFY_DONE;
+
+	vi = netdev_priv(ndev);
+	if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_MASTER))
+		return NOTIFY_DONE;
+
+	netdev_info(ndev, "VF unregistering %s\n", vf_netdev->name);
+
+	netdev_rx_handler_unregister(vf_netdev);
+	netdev_upper_dev_unlink(vf_netdev, ndev);
+	RCU_INIT_POINTER(vi->vf_netdev, NULL);
+	dev_put(vf_netdev);
+
+	return NOTIFY_OK;
+}
+
 static void virtnet_remove(struct virtio_device *vdev)
 {
 	struct virtnet_info *vi = vdev->priv;
+	struct net_device *vf_netdev;
 
 	virtnet_cpu_notif_remove(vi);
 
 	/* Make sure no work handler is accessing the device. */
 	flush_work(&vi->config_work);
 
+	rtnl_lock();
+	vf_netdev = rtnl_dereference(vi->vf_netdev);
+	if (vf_netdev)
+		virtnet_unregister_vf(vf_netdev);
+	rtnl_unlock();
+
 	unregister_netdev(vi->dev);
 
 	remove_vq_common(vi);
 
+	free_percpu(vi->vf_stats);
 	free_percpu(vi->stats);
 	free_netdev(vi->dev);
 }
@@ -2827,6 +3089,42 @@ static struct virtio_driver virtio_net_driver = {
 #endif
 };
 
+static int virtio_netdev_event(struct notifier_block *this,
+			       unsigned long event, void *ptr)
+{
+	struct net_device *event_dev = netdev_notifier_info_to_dev(ptr);
+
+	/* Skip our own events */
+	if (event_dev->netdev_ops == &virtnet_netdev)
+		return NOTIFY_DONE;
+
+	/* Avoid non-Ethernet type devices */
+	if (event_dev->type != ARPHRD_ETHER)
+		return NOTIFY_DONE;
+
+	/* Avoid Vlan dev with same MAC registering as VF */
+	if (is_vlan_dev(event_dev))
+		return NOTIFY_DONE;
+
+	/* Avoid Bonding master dev with same MAC registering as VF */
+	if ((event_dev->priv_flags & IFF_BONDING) &&
+	    (event_dev->flags & IFF_MASTER))
+		return NOTIFY_DONE;
+
+	switch (event) {
+	case NETDEV_REGISTER:
+		return virtnet_register_vf(event_dev);
+	case NETDEV_UNREGISTER:
+		return virtnet_unregister_vf(event_dev);
+	default:
+		return NOTIFY_DONE;
+	}
+}
+
+static struct notifier_block virtio_netdev_notifier = {
+	.notifier_call = virtio_netdev_event,
+};
+
 static __init int virtio_net_driver_init(void)
 {
 	int ret;
@@ -2845,6 +3143,8 @@ static __init int virtio_net_driver_init(void)
         ret = register_virtio_driver(&virtio_net_driver);
 	if (ret)
 		goto err_virtio;
+
+	register_netdevice_notifier(&virtio_netdev_notifier);
 	return 0;
 err_virtio:
 	cpuhp_remove_multi_state(CPUHP_VIRT_NET_DEAD);
@@ -2857,6 +3157,7 @@ module_init(virtio_net_driver_init);
 
 static __exit void virtio_net_driver_exit(void)
 {
+	unregister_netdevice_notifier(&virtio_netdev_notifier);
 	unregister_virtio_driver(&virtio_net_driver);
 	cpuhp_remove_multi_state(CPUHP_VIRT_NET_DEAD);
 	cpuhp_remove_multi_state(virtionet_online);
-- 
2.14.3

^ permalink raw reply related

* [PATCH] rtlwifi: rtl8723de: Add firmware for new driver/device
From: Larry Finger @ 2018-01-03  0:44 UTC (permalink / raw)
  To: linux-firmware; +Cc: linux-wireless, Larry Finger, netdev, Ping-Ke Shih

A driver for the RTL8723DE is nearing submission to staging. This commit supplies
the firmware for it.

Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
Cc: Ping-Ke Shih <pkshih@realtek.com>
---
 WHENCE                  |   9 +++++++++
 rtlwifi/rtl8723defw.bin | Bin 0 -> 27726 bytes
 2 files changed, 9 insertions(+)
 create mode 100644 rtlwifi/rtl8723defw.bin

diff --git a/WHENCE b/WHENCE
index 7518a93..a4dc54f 100644
--- a/WHENCE
+++ b/WHENCE
@@ -2469,6 +2469,15 @@ Licence: Redistributable. See LICENCE.rtlwifi_firmware.txt for details.
 
 --------------------------------------------------------------------------
 
+Driver: rtl8723de - Realtek 802.11ac WLAN driver for RTL8723DE
+
+Info: Supplied by Vendor at https://github.com/pkshih/rtlwifi_rtl8723de
+File: rtlwifi/rtl8723defw.bin
+
+Licence: Redistributable. See LICENCE.rtlwifi_firmware.txt for details.
+
+--------------------------------------------------------------------------
+
 Driver: r8723au - Realtek 802.11n WLAN driver for RTL8723AU
 
 Info: Taken from Realtek driver rtl8723A_WiFi_linux_v4.1.3_6044.20121224
diff --git a/rtlwifi/rtl8723defw.bin b/rtlwifi/rtl8723defw.bin
new file mode 100644
index 0000000000000000000000000000000000000000..6d2c95392a947e454d0365d6d982d393a5dfadf6
GIT binary patch
literal 27726
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
Z7mXEWL<j9lgB@a1=G&v%b)Wz7{{VRD`t<++

literal 0
HcmV?d00001

-- 
2.15.1

^ permalink raw reply related

* RE: [PATCH net,stable 1/1] net: fec: defer probe if regulator is not ready
From: Andy Duan @ 2018-01-03  1:28 UTC (permalink / raw)
  To: Fabio Estevam
  Cc: David S. Miller, netdev@vger.kernel.org, Troy Kisky, Andrew Lunn
In-Reply-To: <CAOMZO5CeF+JOqna-+ES8y5kCokORPm5v5NTvtvjurVJGyNXv=g@mail.gmail.com>

From: Fabio Estevam <festevam@gmail.com> Sent: Tuesday, January 02, 2018 6:21 PM
>Hi Andy,
>
>On Tue, Jan 2, 2018 at 7:57 AM, Fugang Duan <fugang.duan@nxp.com> wrote:
>
>> @@ -3576,6 +3580,7 @@ static int fec_enet_get_irq_cnt(struct
>platform_device *pdev)
>>         of_node_put(phy_node);
>>  failed_ioremap:
>>         free_netdev(ndev);
>> +       dev_id--;
>
>This seems to be a different fix and should be part of a separate patch.
>
>Thanks

Okay, I can split the fix as separate patch.
Thanks for your comment.

^ permalink raw reply

* Re: [PATCHv3 0/2] capability controlled user-namespaces
From: Mahesh Bandewar (महेश बंडेवार) @ 2018-01-03  1:30 UTC (permalink / raw)
  To: James Morris
  Cc: LKML, Netdev, Kernel-hardening, Linux API, Kees Cook,
	Serge Hallyn, Eric W . Biederman, Eric Dumazet, David Miller,
	Mahesh Bandewar
In-Reply-To: <alpine.LFD.2.20.1712301931360.24310@localhost>

On Sat, Dec 30, 2017 at 12:31 AM, James Morris
<james.l.morris@oracle.com> wrote:
> On Wed, 27 Dec 2017, Mahesh Bandewar (महेश बंडेवार) wrote:
>
>> Hello James,
>>
>> Seems like I missed your name to be added into the review of this
>> patch series. Would you be willing be pull this into the security
>> tree? Serge Hallyn has already ACKed it.
>
> Sure!
>
Thank you James.
>
>>
>> Thanks,
>> --mahesh..
>>
>> On Tue, Dec 5, 2017 at 2:30 PM, Mahesh Bandewar <mahesh@bandewar.net> wrote:
>> > From: Mahesh Bandewar <maheshb@google.com>
>> >
>> > TL;DR version
>> > -------------
>> > Creating a sandbox environment with namespaces is challenging
>> > considering what these sandboxed processes can engage into. e.g.
>> > CVE-2017-6074, CVE-2017-7184, CVE-2017-7308 etc. just to name few.
>> > Current form of user-namespaces, however, if changed a bit can allow
>> > us to create a sandbox environment without locking down user-
>> > namespaces.
>> >
>> > Detailed version
>> > ----------------
>> >
>> > Problem
>> > -------
>> > User-namespaces in the current form have increased the attack surface as
>> > any process can acquire capabilities which are not available to them (by
>> > default) by performing combination of clone()/unshare()/setns() syscalls.
>> >
>> >     #define _GNU_SOURCE
>> >     #include <stdio.h>
>> >     #include <sched.h>
>> >     #include <netinet/in.h>
>> >
>> >     int main(int ac, char **av)
>> >     {
>> >         int sock = -1;
>> >
>> >         printf("Attempting to open RAW socket before unshare()...\n");
>> >         sock = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW);
>> >         if (sock < 0) {
>> >             perror("socket() SOCK_RAW failed: ");
>> >         } else {
>> >             printf("Successfully opened RAW-Sock before unshare().\n");
>> >             close(sock);
>> >             sock = -1;
>> >         }
>> >
>> >         if (unshare(CLONE_NEWUSER | CLONE_NEWNET) < 0) {
>> >             perror("unshare() failed: ");
>> >             return 1;
>> >         }
>> >
>> >         printf("Attempting to open RAW socket after unshare()...\n");
>> >         sock = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW);
>> >         if (sock < 0) {
>> >             perror("socket() SOCK_RAW failed: ");
>> >         } else {
>> >             printf("Successfully opened RAW-Sock after unshare().\n");
>> >             close(sock);
>> >             sock = -1;
>> >         }
>> >
>> >         return 0;
>> >     }
>> >
>> > The above example shows how easy it is to acquire NET_RAW capabilities
>> > and once acquired, these processes could take benefit of above mentioned
>> > or similar issues discovered/undiscovered with malicious intent. Note
>> > that this is just an example and the problem/solution is not limited
>> > to NET_RAW capability *only*.
>> >
>> > The easiest fix one can apply here is to lock-down user-namespaces which
>> > many of the distros do (i.e. don't allow users to create user namespaces),
>> > but unfortunately that prevents everyone from using them.
>> >
>> > Approach
>> > --------
>> > Introduce a notion of 'controlled' user-namespaces. Every process on
>> > the host is allowed to create user-namespaces (governed by the limit
>> > imposed by per-ns sysctl) however, mark user-namespaces created by
>> > sandboxed processes as 'controlled'. Use this 'mark' at the time of
>> > capability check in conjunction with a global capability whitelist.
>> > If the capability is not whitelisted, processes that belong to
>> > controlled user-namespaces will not be allowed.
>> >
>> > Once a user-ns is marked as 'controlled'; all its child user-
>> > namespaces are marked as 'controlled' too.
>> >
>> > A global whitelist is list of capabilities governed by the
>> > sysctl which is available to (privileged) user in init-ns to modify
>> > while it's applicable to all controlled user-namespaces on the host.
>> >
>> > Marking user-namespaces controlled without modifying the whitelist is
>> > equivalent of the current behavior. The default value of whitelist includes
>> > all capabilities so that the compatibility is maintained. However it gives
>> > admins fine-grained ability to control various capabilities system wide
>> > without locking down user-namespaces.
>> >
>> > Please see individual patches in this series.
>> >
>> > Mahesh Bandewar (2):
>> >   capability: introduce sysctl for controlled user-ns capability whitelist
>> >   userns: control capabilities of some user namespaces
>> >
>> >  Documentation/sysctl/kernel.txt | 21 +++++++++++++++++
>> >  include/linux/capability.h      |  7 ++++++
>> >  include/linux/user_namespace.h  | 25 ++++++++++++++++++++
>> >  kernel/capability.c             | 52 +++++++++++++++++++++++++++++++++++++++++
>> >  kernel/sysctl.c                 |  5 ++++
>> >  kernel/user_namespace.c         |  4 ++++
>> >  security/commoncap.c            |  8 +++++++
>> >  7 files changed, 122 insertions(+)
>> >
>> > --
>> > 2.15.0.531.g2ccb3012c9-goog
>> >
>>
>
> --
> James Morris
> <james.l.morris@oracle.com>

^ permalink raw reply

* Re: [PATCHv3 0/2] capability controlled user-namespaces
From: Mahesh Bandewar (महेश बंडेवार) @ 2018-01-03  1:35 UTC (permalink / raw)
  To: Michael Kerrisk (man-pages)
  Cc: James Morris, LKML, Netdev, Kernel-hardening, Linux API,
	Kees Cook, Serge Hallyn, Eric W . Biederman, Eric Dumazet,
	David Miller, Mahesh Bandewar
In-Reply-To: <7658ff18-23fc-6aff-6bac-15573f67ddfb@gmail.com>

Hello Michael,

I really don't want to turn this into how-to-hack guide but I do see
few points in your argument to make the case clearer. Please see the
comments inline.

On Sat, Dec 30, 2017 at 12:50 AM, Michael Kerrisk (man-pages)
<mtk.manpages@gmail.com> wrote:
> Hello Mahesh,
>
> On 12/28/2017 01:45 AM, Mahesh Bandewar (महेश बंडेवार) wrote:
>> On Wed, Dec 27, 2017 at 12:23 PM, Michael Kerrisk (man-pages)
>> <mtk.manpages@gmail.com> wrote:
>>> Hello Mahesh,
>>>
>>> On 27 December 2017 at 18:09, Mahesh Bandewar (महेश बंडेवार)
>>> <maheshb@google.com> wrote:
>>>> Hello James,
>>>>
>>>> Seems like I missed your name to be added into the review of this
>>>> patch series. Would you be willing be pull this into the security
>>>> tree? Serge Hallyn has already ACKed it.
>>>
>>> We seem to have no formal documentation/specification of this feature.
>>> I think that should be written up before this patch goes into
>>> mainline...
>>>
>> absolutely. I have added enough information into the Documentation dir
>> relevant to this feature (please look at the  individual patches),
>> that could be used. I could help if needed.
>
> Yes, but I think that the documentation is rather incomplete.
> I'll also reply to the relevant Documentation thread.
>
> See also some comments below about this commit message, which
> should make things *much* easier for the reader.
>
>>>> On Tue, Dec 5, 2017 at 2:30 PM, Mahesh Bandewar <mahesh@bandewar.net> wrote:
>>>>> From: Mahesh Bandewar <maheshb@google.com>
>>>>>
>>>>> TL;DR version
>>>>> -------------
>>>>> Creating a sandbox environment with namespaces is challenging
>>>>> considering what these sandboxed processes can engage into. e.g.
>>>>> CVE-2017-6074, CVE-2017-7184, CVE-2017-7308 etc. just to name few.
>>>>> Current form of user-namespaces, however, if changed a bit can allow
>>>>> us to create a sandbox environment without locking down user-
>>>>> namespaces.
>>>>>
>>>>> Detailed version
>>>>> ----------------
>>>>>
>>>>> Problem
>>>>> -------
>>>>> User-namespaces in the current form have increased the attack surface as
>>>>> any process can acquire capabilities which are not available to them (by
>>>>> default) by performing combination of clone()/unshare()/setns() syscalls.
>>>>>
>>>>>     #define _GNU_SOURCE
>>>>>     #include <stdio.h>
>>>>>     #include <sched.h>
>>>>>     #include <netinet/in.h>
>>>>>
>>>>>     int main(int ac, char **av)
>>>>>     {
>>>>>         int sock = -1;
>>>>>
>>>>>         printf("Attempting to open RAW socket before unshare()...\n");
>>>>>         sock = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW);
>>>>>         if (sock < 0) {
>>>>>             perror("socket() SOCK_RAW failed: ");
>>>>>         } else {
>>>>>             printf("Successfully opened RAW-Sock before unshare().\n");
>>>>>             close(sock);
>>>>>             sock = -1;
>>>>>         }
>>>>>
>>>>>         if (unshare(CLONE_NEWUSER | CLONE_NEWNET) < 0) {
>>>>>             perror("unshare() failed: ");
>>>>>             return 1;
>>>>>         }
>>>>>
>>>>>         printf("Attempting to open RAW socket after unshare()...\n");
>>>>>         sock = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW);
>>>>>         if (sock < 0) {
>>>>>             perror("socket() SOCK_RAW failed: ");
>>>>>         } else {
>>>>>             printf("Successfully opened RAW-Sock after unshare().\n");
>>>>>             close(sock);
>>>>>             sock = -1;
>>>>>         }
>>>>>
>>>>>         return 0;
>>>>>     }
>>>>>
>>>>> The above example shows how easy it is to acquire NET_RAW capabilities
>>>>> and once acquired, these processes could take benefit of above mentioned
>>>>> or similar issues discovered/undiscovered with malicious intent.
>
> But you do not actually describe what the problem is. I think
> it's not sufficient to simply refer to some CVEs.
> Your mail message/commit should clearly describe what the issue is,
> rather than leave the reader to decipher a bunch of CVEs, and derive
> your concerns from those CVEs.
>
I have mentioned in the 'problem' section of this log - how easy to
acquire 'the capability' and then CVE describes if you have 'the
capability' you can exploit! So I'm not sure why there is any decipher
needed. Also that is the general example while this patch-set
addresses this for any generic capability and not just the one
mentioned in the a.m.CVEs. So rather than going deep into the CVE, I
will try to demonstrate the modified behavior to give an idea.

>>>>> Note
>>>>> that this is just an example and the problem/solution is not limited
>>>>> to NET_RAW capability *only*.
>>>>>
>>>>> The easiest fix one can apply here is to lock-down user-namespaces which
>>>>> many of the distros do (i.e. don't allow users to create user namespaces),
>>>>> but unfortunately that prevents everyone from using them.
>>>>>
>>>>> Approach
>>>>> --------
>>>>> Introduce a notion of 'controlled' user-namespaces. Every process on
>>>>> the host is allowed to create user-namespaces (governed by the limit
>>>>> imposed by per-ns sysctl) however, mark user-namespaces created by
>>>>> sandboxed processes as 'controlled'. Use this 'mark' at the time of
>>>>> capability check in conjunction with a global capability whitelist.
>>>>> If the capability is not whitelisted, processes that belong to
>>>>> controlled user-namespaces will not be allowed.
>>>>>
>>>>> Once a user-ns is marked as 'controlled'; all its child user-
>>>>> namespaces are marked as 'controlled' too.
>
> How is a user-ns marked as "controlled"? It is not clear at this point.
> Please clarify this in your cover mail (and on the Documentation patch.)
>
Yes, I would add some more text describing how user-ns gets marked as
controlled. It's actually part of the Documentation patch in this
series but it does makes sense to add some text here to describe it
clearly.

>>>>> A global whitelist is list of capabilities governed by the
>>>>> sysctl which is available to (privileged) user in init-ns to modify
>
> What "the sysctl? Please name it at this point. (This may be purely a
> language issue. Do you mean "...governed by *a* sysctl,
> [sysctl-name-inserted-here]"?)
>
Correct, '..governed by a sysctl var kernel.controlled_userns_caps_whitelist'.

>>>>> while it's applicable to all controlled user-namespaces on the host.
>>>>>
>>>>> Marking user-namespaces controlled without modifying the whitelist is
>>>>> equivalent of the current behavior. The default value of whitelist includes
>>>>> all capabilities so that the compatibility is maintained. However it gives
>>>>> admins fine-grained ability to control various capabilities system wide
>>>>> without locking down user-namespaces.
>
> Is there a way that a process can see whether it is a controlled user-ns
> versus an uncontrolled user-ns? I think it would be good to explain that
> in this cover mail, and perhaps also in the documentation patch.
>
There is no direct way of doing this and I'm not sure it's a good
idea/investment to add a new syscall just for that.

> In general, it's not too obvious what you are trying to do, based on
> this commit message.
>
> Can I suggest including as part of the commit messages a walk through
> shell session that demonstrates the use of these interfaces and how
> they allow/disallow capabilities. I think such a walkthrough might also
> be worth including in the Documentation patch.
>
OK, I'll add something to address these concerns.

Thanks,
--mahesh..

> Thanks,
>
> Michael
>
>
>>>>>
>>>>> Please see individual patches in this series.
>>>>>
>>>>> Mahesh Bandewar (2):
>>>>>   capability: introduce sysctl for controlled user-ns capability whitelist
>>>>>   userns: control capabilities of some user namespaces
>>>>>
>>>>>  Documentation/sysctl/kernel.txt | 21 +++++++++++++++++
>>>>>  include/linux/capability.h      |  7 ++++++
>>>>>  include/linux/user_namespace.h  | 25 ++++++++++++++++++++
>>>>>  kernel/capability.c             | 52 +++++++++++++++++++++++++++++++++++++++++
>>>>>  kernel/sysctl.c                 |  5 ++++
>>>>>  kernel/user_namespace.c         |  4 ++++
>>>>>  security/commoncap.c            |  8 +++++++
>>>>>  7 files changed, 122 insertions(+)
>>>>>
>>>>> --
>>>>> 2.15.0.531.g2ccb3012c9-goog
>>>>>
>>>> --
>>>> To unsubscribe from this list: send the line "unsubscribe linux-api" in
>>>> the body of a message to majordomo@vger.kernel.org
>>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>>
>>>
>>>
>>> --
>>> Michael Kerrisk
>>> Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
>>> Linux/UNIX System Programming Training: http://man7.org/training/
>>
>
>
> --
> Michael Kerrisk
> Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
> Linux/UNIX System Programming Training: http://man7.org/training/

^ permalink raw reply

* Re: [PATCHv3 1/2] capability: introduce sysctl for controlled user-ns capability whitelist
From: Mahesh Bandewar (महेश बंडेवार) @ 2018-01-03  1:39 UTC (permalink / raw)
  To: Michael Kerrisk (man-pages)
  Cc: Mahesh Bandewar, LKML, Netdev, Kernel-hardening, Linux API,
	Kees Cook, Serge Hallyn, Eric W . Biederman, Eric Dumazet,
	David Miller
In-Reply-To: <fd118a72-ce69-99fe-1cc4-0adaee3660c9-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>

On Sat, Dec 30, 2017 at 12:50 AM, Michael Kerrisk (man-pages)
<mtk.manpages-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:
> Hello Mahesh,
>
> On 12/05/2017 11:31 PM, Mahesh Bandewar wrote:
>> From: Mahesh Bandewar <maheshb-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
>>
>> Add a sysctl variable kernel.controlled_userns_caps_whitelist. This
>> takes input as capability mask expressed as two comma separated hex
>> u32 words. The mask, however, is stored in kernel as kernel_cap_t type.
>
> Just by the way, why is it not expressed as a 64 bit value? (The answer
> to that question should I think be part of this commit message.)
>
I think I mentioned in the earlier threads but it's as simple as using
the existing kernel API that deals with larger bit masks/arrays.
Capability mask is an array of u32 and one cannot guarantee that
kernel_cap_t is only 64 bits. So expressing it as u32 hex values makes
logical sense. Yes, one can simplify this even further and make this
sysctl accept string values. But bringing possibly buggy string
manipulation inside kernel is far more desirable than an already used
API that is designed specifically for this purpose. Also not expecting
this sysctl to be changed very often so robustness is preferred over
simplicity if that simplicity is accompanied by buggy behavior.

I'll add similar text in the commit log.

>> Any capabilities that are not part of this mask will be controlled and
>> will not be allowed to processes in controlled user-ns.
>>
>> Acked-by: Serge Hallyn <serge-A9i7LUbDfNHQT0dZR+AlfA@public.gmane.org>
>> Signed-off-by: Mahesh Bandewar <maheshb-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
>> ---
>> v3:
>>   Added couple of comments as requested by Serge Hallyn
>> v2:
>>   Rebase
>> v1:
>>   Initial submission
>>
>>  Documentation/sysctl/kernel.txt | 21 ++++++++++++++++++
>>  include/linux/capability.h      |  3 +++
>>  kernel/capability.c             | 47 +++++++++++++++++++++++++++++++++++++++++
>>  kernel/sysctl.c                 |  5 +++++
>>  4 files changed, 76 insertions(+)
>>
>> diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt
>> index 694968c7523c..a1d39dbae847 100644
>> --- a/Documentation/sysctl/kernel.txt
>> +++ b/Documentation/sysctl/kernel.txt
>> @@ -25,6 +25,7 @@ show up in /proc/sys/kernel:
>>  - bootloader_version      [ X86 only ]
>>  - callhome                [ S390 only ]
>>  - cap_last_cap
>> +- controlled_userns_caps_whitelist
>>  - core_pattern
>>  - core_pipe_limit
>>  - core_uses_pid
>> @@ -187,6 +188,26 @@ CAP_LAST_CAP from the kernel.
>>
>>  ==============================================================
>>
>> +controlled_userns_caps_whitelist
>> +
>> +Capability mask that is whitelisted for "controlled" user namespaces.
>
> How is a user-ns marked as "controlled"? Please clarify this.
>
Hmm, it's mentioned in this same paragraph (at the end). Looks like you miss it!

>> +Any capability that is missing from this mask will not be allowed to
>> +any process that is attached to a controlled-userns. e.g. if CAP_NET_RAW
>> +is not part of this mask, then processes running inside any controlled
>> +userns's will not be allowed to perform action that needs CAP_NET_RAW
>> +capability. However, processes that are attached to a parent user-ns
>> +hierarchy that is *not* controlled and has CAP_NET_RAW can continue
>> +performing those actions. User-namespaces are marked "controlled" at
>> +the time of their creation based on the capabilities of the creator.
>> +A process that does not have CAP_SYS_ADMIN will create user-namespaces
>> +that are controlled.
>> +
>> +The value is expressed as two comma separated hex words (u32). This
>> +sysctl is avaialble in init-ns and users with CAP_SYS_ADMIN in init-ns
>> +are allowed to make changes.
>
> Could you add here a shell session that demonstrates the use of these
> interfaces and how they allow/disallow capabilities.
>
OK, will add something to address this.

> Is there a way that a process can see whether it is a controlled user-ns
> vs an uncontrolled user-ns? I think it would be good to explain in this
> doc patch.
>
> Thanks,
>
> Michael
>
>> +==============================================================
>> +
>>  core_pattern:
>>
>>  core_pattern is used to specify a core dumpfile pattern name.
>> diff --git a/include/linux/capability.h b/include/linux/capability.h
>> index f640dcbc880c..7d79a4689625 100644
>> --- a/include/linux/capability.h
>> +++ b/include/linux/capability.h
>> @@ -14,6 +14,7 @@
>>  #define _LINUX_CAPABILITY_H
>>
>>  #include <uapi/linux/capability.h>
>> +#include <linux/sysctl.h>
>>
>>
>>  #define _KERNEL_CAPABILITY_VERSION _LINUX_CAPABILITY_VERSION_3
>> @@ -248,6 +249,8 @@ extern bool ptracer_capable(struct task_struct *tsk, struct user_namespace *ns);
>>
>>  /* audit system wants to get cap info from files as well */
>>  extern int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data *cpu_caps);
>> +int proc_douserns_caps_whitelist(struct ctl_table *table, int write,
>> +                              void __user *buff, size_t *lenp, loff_t *ppos);
>>
>>  extern int cap_convert_nscap(struct dentry *dentry, void **ivalue, size_t size);
>>
>> diff --git a/kernel/capability.c b/kernel/capability.c
>> index 1e1c0236f55b..4a859b7d4902 100644
>> --- a/kernel/capability.c
>> +++ b/kernel/capability.c
>> @@ -29,6 +29,8 @@ EXPORT_SYMBOL(__cap_empty_set);
>>
>>  int file_caps_enabled = 1;
>>
>> +kernel_cap_t controlled_userns_caps_whitelist = CAP_FULL_SET;
>> +
>>  static int __init file_caps_disable(char *str)
>>  {
>>       file_caps_enabled = 0;
>> @@ -507,3 +509,48 @@ bool ptracer_capable(struct task_struct *tsk, struct user_namespace *ns)
>>       rcu_read_unlock();
>>       return (ret == 0);
>>  }
>> +
>> +/* Controlled-userns capabilities routines */
>> +#ifdef CONFIG_SYSCTL
>> +int proc_douserns_caps_whitelist(struct ctl_table *table, int write,
>> +                              void __user *buff, size_t *lenp, loff_t *ppos)
>> +{
>> +     DECLARE_BITMAP(caps_bitmap, CAP_LAST_CAP);
>> +     struct ctl_table caps_table;
>> +     char tbuf[NAME_MAX];
>> +     int ret;
>> +
>> +     ret = bitmap_from_u32array(caps_bitmap, CAP_LAST_CAP,
>> +                                controlled_userns_caps_whitelist.cap,
>> +                                _KERNEL_CAPABILITY_U32S);
>> +     if (ret != CAP_LAST_CAP)
>> +             return -1;
>> +
>> +     scnprintf(tbuf, NAME_MAX, "%*pb", CAP_LAST_CAP, caps_bitmap);
>> +
>> +     caps_table.data = tbuf;
>> +     caps_table.maxlen = NAME_MAX;
>> +     caps_table.mode = table->mode;
>> +     ret = proc_dostring(&caps_table, write, buff, lenp, ppos);
>> +     if (ret)
>> +             return ret;
>> +     if (write) {
>> +             kernel_cap_t tmp;
>> +
>> +             if (!capable(CAP_SYS_ADMIN))
>> +                     return -EPERM;
>> +
>> +             ret = bitmap_parse_user(buff, *lenp, caps_bitmap, CAP_LAST_CAP);
>> +             if (ret)
>> +                     return ret;
>> +
>> +             ret = bitmap_to_u32array(tmp.cap, _KERNEL_CAPABILITY_U32S,
>> +                                      caps_bitmap, CAP_LAST_CAP);
>> +             if (ret != CAP_LAST_CAP)
>> +                     return -1;
>> +
>> +             controlled_userns_caps_whitelist = tmp;
>> +     }
>> +     return 0;
>> +}
>> +#endif /* CONFIG_SYSCTL */
>> diff --git a/kernel/sysctl.c b/kernel/sysctl.c
>> index 557d46728577..759b6c286806 100644
>> --- a/kernel/sysctl.c
>> +++ b/kernel/sysctl.c
>> @@ -1217,6 +1217,11 @@ static struct ctl_table kern_table[] = {
>>               .extra2         = &one,
>>       },
>>  #endif
>> +     {
>> +             .procname       = "controlled_userns_caps_whitelist",
>> +             .mode           = 0644,
>> +             .proc_handler   = proc_douserns_caps_whitelist,
>> +     },
>>       { }
>>  };
>>
>>
>
>
> --
> Michael Kerrisk
> Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
> Linux/UNIX System Programming Training: http://man7.org/training/

^ permalink raw reply

* Re: [PATCH v3 net-next 2/5] net: tracepoint: replace tcp_set_state tracepoint with inet_sock_set_state tracepoint
From: Yafang Shao @ 2018-01-03  1:48 UTC (permalink / raw)
  To: Brendan Gregg
  Cc: Song Liu, David S. Miller, Marcelo Ricardo Leitner,
	Steven Rostedt, Brendan Gregg, netdev, LKML
In-Reply-To: <CAE40pddorDmoaGn2og-7u7vxpDY8uiWN8qEbQ05YYnK8f0Q_XQ@mail.gmail.com>

On Wed, Jan 3, 2018 at 3:46 AM, Brendan Gregg <brendan.d.gregg@gmail.com> wrote:
> On Sat, Dec 30, 2017 at 7:06 PM, Yafang Shao <laoar.shao@gmail.com> wrote:
>> On Sun, Dec 31, 2017 at 6:33 AM, Brendan Gregg
>> <brendan.d.gregg@gmail.com> wrote:
>>> On Tue, Dec 19, 2017 at 7:12 PM, Yafang Shao <laoar.shao@gmail.com> wrote:
>>>> As sk_state is a common field for struct sock, so the state
>>>> transition tracepoint should not be a TCP specific feature.
>>>> Currently it traces all AF_INET state transition, so I rename this
>>>> tracepoint to inet_sock_set_state tracepoint with some minor changes and move it
>>>> into trace/events/sock.h.
>>>
>>> The tcp:tcp_set_state probe is tcp_set_state(), so it's only going to
>>> fire for TCP sessions. It's not broken, and we could add a
>>> sctp:sctp_set_state as well. Replacing tcp:tcp_set_state with
>>> inet_sk_set_state is feeling like we might be baking too much
>>> implementation detail into the tracepoint API.
>>>
>>> If we must have inet_sk_set_state, then must we also delete tcp:tcp_set_state?
>>>
>>
>> Hi Brendan,
>>
>> The reason we have to make this change could be got from this mail
>> thread, https://patchwork.kernel.org/patch/10099243/ .
>>
>> The original tcp:tcp_set_state probe doesn't traced all TCP state transitions.
>> There're some state transitions in inet_connection_sock.c and
>> inet_hashtables.c are missed.
>> So we have to place this probe into these two files to fix the issue.
>> But as inet_connection_sock.c and inet_hashtables.c are common files
>> for all IPv4 protocols, not only for TCP, so it is not proper to place
>> a tcp_ function in these two files.
>> That's why we decide to rename tcp:tcp_set_state probe to
>> sock:inet_sock_set_state.
>
> It kinda feels like we are fixing one exposing-implementation problem
> (the missing state changes, which I'm happy to see fixed), by exposing
> another (there's no tcp:tcp_set_state because we don't want to put tcp
> functions in inet*.c files). Anyway...
>
> If I'm to use sock:inet_sock_set_state for TCP tracing, I'd like
> sk->sk_protocol exposed as a tracepoint argument so I can match on
> IPPROTO_TCP. Otherwise I'll have to keep digging it out of (void
> *)skaddr. (And if we're adding arguments, maybe consider sk_family as
> well, to make it easier to see which address arguments to use).
>

I will improve it as your suggestion.

Thanks
Yafang

^ permalink raw reply

* Re: [patch net-next v4 00/10] net: sched: allow qdiscs to share filter block instances
From: David Ahern @ 2018-01-03  2:07 UTC (permalink / raw)
  To: Jiri Pirko
  Cc: netdev, davem, jhs, xiyou.wangcong, mlxsw, andrew, vivien.didelot,
	f.fainelli, michael.chan, ganeshgr, saeedm, matanb, leonro,
	idosch, jakub.kicinski, simon.horman, pieter.jansenvanvuuren,
	john.hurley, alexander.h.duyck, ogerlitz, john.fastabend, daniel
In-Reply-To: <20180102194944.GG2051@nanopsycho.orion>

On 1/2/18 12:49 PM, Jiri Pirko wrote:
> DaveA, please consider following example:
> 
> $ tc qdisc add dev ens7 ingress
> $ tc qdisc
> qdisc ingress ffff: dev ens7 parent ffff:fff1 block 1
> 
> Now I have one device with one qdisc attached.
> 
> I will add some filters, for example:
> $ tc filter add dev ens7 ingress protocol ip pref 25 flower dst_ip 192.168.0.0/16 action drop
> 
> No sharing is happening. The user is doing what he is used to do.
> 
> Now user decides to share this filters with another device. As you can
> see above, the block created for ens7 qdisc instance has id "1".
> User can simply do:
> 
> tc qdisc add dev ens8 ingress block 1
> 
> And the block gets shared among ens7 ingress qdisc instance and ens8
> ingress qdisc instance.
> 
> What is wrong with this? The approach you suggest would disallow this

Conceptually, absolutely nothing. We all agree that a shared block
feature is needed. So no argument on sharing the filters across devices.

The disagreement is in how they should be managed. I think my last
response concisely captures my concerns -- the principle of least surprise.

So with the initial commands above, all is fine. Then someone is
debugging a problem or wants to add another filter to ens8, so they run:

$ tc filter add dev ens8 ingress protocol ip pref 25 flower dst_ip
192.168.1.0/16 action drop

Then traffic flows through ens7 break and some other user is struggling
to understand what just happened. That the new filter magically appears
on ens7 when the user operated on ens8 is a surprise. Nothing about that
last command acknowledges that it is changing a shared resource.

Consider the commands being run by different people, and a time span
between. Allowing the shared block to be configured by any device using
the block is just setting up users for errors and confusion.

> forcing user to explicitly create some block entity and then to attach
> it to qdisc instances. I don't really see good reason for it. Could you
> please clear this up for me?

It forces the user to acknowledge it is changing a resource that may be
shared by more than one device.

$ tc filter add dev ens8 ingress protocol ip pref 25 flower dst_ip
192.168.1.0/16 action drop
Error: This qdisc is a shared block. Use the block API to configure.

$ tc qdisc show dev ens8
qdisc ingress ffff: dev ens7 parent ffff:fff1 block 1

$ tc filter add block 1 protocol ip pref 25 flower dst_ip 192.168.1.0/16
action drop

Now there are no surprises. I have to know that ens8 is using block 1,
and I have to specify that block when adding a filter.


BTW, is there an option to list all devices using the same shared block
- short of listing all and grepping?

^ permalink raw reply

* Re: ACPI issues on cold power on [bisected]
From: Joonsoo Kim @ 2018-01-03  2:11 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Jonathan McDowell, ACPI Devel Maling List,
	Linux Kernel Mailing List, Linux Memory Management List, netdev
In-Reply-To: <CAJZ5v0hSkEvmcubFzW03COW0f1TwB6W1d7vwJoF9qpJJ6Jc5JQ@mail.gmail.com>

On Tue, Jan 02, 2018 at 11:25:01AM +0100, Rafael J. Wysocki wrote:
> On Tue, Jan 2, 2018 at 3:54 AM, Joonsoo Kim <iamjoonsoo.kim@lge.com> wrote:
> > On Fri, Dec 29, 2017 at 04:36:59PM +0000, Jonathan McDowell wrote:
> >> On Fri, Dec 22, 2017 at 09:21:09AM +0900, Joonsoo Kim wrote:
> >> > On Fri, Dec 08, 2017 at 03:11:59PM +0000, Jonathan McDowell wrote:
> >> > > I've been sitting on this for a while and should have spent time to
> >> > > investigate sooner, but it's been an odd failure mode that wasn't quite
> >> > > obvious.
> >> > >
> >> > > In 4.9 if I cold power on my laptop (Dell E7240) it fails to boot - I
> >> > > don't see anything after grub says its booting. In 4.10 onwards the
> >> > > laptop boots, but I get an Oops as part of the boot and ACPI is unhappy
> >> > > (no suspend, no clean poweroff, no ACPI buttons). The Oops is below;
> >> > > taken from 4.12 as that's the most recent error dmesg I have saved but
> >> > > also seen back in 4.10. It's always address 0x30 for the dereference.
> >> > >
> >> > > Rebooting the laptop does not lead to these problems; it's *only* from a
> >> > > complete cold boot that they arise (which didn't help me in terms of
> >> > > being able to reliably bisect). Once I realised that I was able to
> >> > > bisect, but it leads me to an odd commit:
> >> > >
> >> > > 86d9f48534e800e4d62cdc1b5aaf539f4c1d47d6
> >> > > (mm/slab: fix kmemcg cache creation delayed issue)
> >> > >
> >> > > If I revert this then I can cold boot without problems.
> >> > >
> >> > > Also I don't see the problem with a stock Debian kernel, I think because
> >> > > the ACPI support is modularised.
> >> >
> >> > Sorry for late response. I was on a long vacation.
> >>
> >> No problem. I've been trying to get around to diagnosing this for a
> >> while now anyway and this isn't a great time of year for fast responses.
> >>
> >> > I have tried to solve the problem however I don't find any clue yet.
> >> >
> >> > >From my analysis, oops report shows that 'struct sock *ssk' passed to
> >> > netlink_broadcast_filtered() is NULL. It means that some of
> >> > netlink_kernel_create() returns NULL. Maybe, it is due to slab
> >> > allocation failure. Could you check it by inserting some log on that
> >> > part? The issue cannot be reproducible in my side so I need your help.
> >>
> >> I've added some debug in acpi_bus_generate_netlink_event +
> >> genlmsg_multicast and the problem seems to be that genlmsg_multicast is
> >> getting called when init_net.genl_sock has not yet been initialised,
> >> leading to the NULL deference.
> >>
> >> Full dmesg output from a cold 4.14.8 boot at:
> >>
> >> https://the.earth.li/~noodles/acpi-problem/dmesg-4.14.8-broken
> >>
> >> And the same kernel after a reboot ("shutdown -r now"):
> >>
> >> https://the.earth.li/~noodles/acpi-problem/dmesg-4.14.8-working
> >>
> >> Patch that I've applied is at
> >>
> >> https://the.earth.li/~noodles/acpi-problem/debug-acpi.diff
> >>
> >
> > Thanks for testing! It's very helpful.
> >
> >> The interesting difference seems to be:
> >>
> >>  PCI: Using ACPI for IRQ routing
> >> +ACPI: Generating event type 208 (:9DBB5994-A997-11DA-B012-B622A1EF5492)
> >> +ERROR: init_net.genl_sock is NULL
> >> +BUG: unable to handle kernel NULL pointer dereference at 0000000000000030
> >> +IP: netlink_broadcast_filtered+0x20/0x3d0
> >> +PGD 0 P4D 0
> >> +Oops: 0000 [#1] SMP
> >> +Modules linked in:
> >> +CPU: 0 PID: 29 Comm: kworker/0:1 Not tainted 4.14.8+ #1
> >> +Hardware name: Dell Inc. Latitude E7240/07RPNV, BIOS A22 10/18/2017
> >> +Workqueue: kacpi_notify acpi_os_execute_deferred
> >>
> >> 9DBB5994-A997-11DA-B012-B622A1EF5492 is the Dell WMI event GUID and
> >> there's no visible event for it on a reboot, just on a cold power on.
> >> Some sort of ordering issues such that genl_sock is being initialised
> >> later with the slab change?
> >
> > I have checked that there is an ordering issue.
> >
> > genl_init() which initializes init_net->genl_sock is called on
> > subsys_initcall().
> >
> > acpi_wmi_init() which schedules acpi_wmi_notify_handler() to the
> > workqueue is called on subsys_initcall(), too.
> > (acpi_wmi_notify_handler() -> acpi_bus_generate_netlink_event() ->
> > netlink_broadcast())
> >
> > In my system, acpi_wmi_init() is called before the genl_init().
> > Therefore, if the worker is scheduled before genl_init() is done, NULL
> > derefence would happen.
> 
> Does it help to change the subsys_initcall() in wmi.c to subsys_initcall_sync()?

I guess that it would work. I cannot reproduce the issue so it needs
to be checked by Jonathan. Jonathan, could you check the problem
is disappeared with above change?

Thanks.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

^ permalink raw reply

* Re: [PATCH net-next 0/2] Enable virtio to act as a master for a passthru device
From: Jakub Kicinski @ 2018-01-03  2:16 UTC (permalink / raw)
  To: jesse.brandeburg
  Cc: Sridhar Samudrala, mst, stephen, netdev, virtualization,
	virtio-dev, Alexander Duyck
In-Reply-To: <1514939738-22423-1-git-send-email-sridhar.samudrala@intel.com>

On Tue,  2 Jan 2018 16:35:36 -0800, Sridhar Samudrala wrote:
> This patch series enables virtio to switch over to a VF datapath when a VF
> netdev is present with the same MAC address. It allows live migration of a VM
> with a direct attached VF without the need to setup a bond/team between a
> VF and virtio net device in the guest.
> 
> The hypervisor needs to unplug the VF device from the guest on the source
> host and reset the MAC filter of the VF to initiate failover of datapath to
> virtio before starting the migration. After the migration is completed, the
> destination hypervisor sets the MAC filter on the VF and plugs it back to
> the guest to switch over to VF datapath.
> 
> It is based on netvsc implementation and it may be possible to make this code 
> generic and move it to a common location that can be shared by netvsc and virtio.
> 
> This patch series is based on the discussion initiated by Jesse on this thread.
> https://marc.info/?l=linux-virtualization&m=151189725224231&w=2

How does the notion of a device which is both a bond and a leg of a
bond fit with Alex's recent discussions about feature propagation?
Which propagation rules will apply to VirtIO master?  Meaning of the
flags on a software upper device may be different.  Why muddy the
architecture like this and not introduce a synthetic bond device?

^ permalink raw reply

* [PATCH v2 net,stable 0/2] net: fec: clean up in the cases of probe error
From: Fugang Duan @ 2018-01-03  2:39 UTC (permalink / raw)
  To: festevam, davem; +Cc: netdev, troy.kisky, andrew, fugang.duan

The simple patches just clean up in the cases of probe error like restore dev_id and
handle the defer probe when regulator is still not ready.

v2:
* Fabio Estevam's comment to suggest split v1 to separate patches.

Fugang Duan (2):
  net: fec: restore dev_id in the cases of probe error
  net: fec: defer probe if regulator is not ready

 drivers/net/ethernet/freescale/fec_main.c | 5 +++++
 1 file changed, 5 insertions(+)

-- 
1.9.1

^ permalink raw reply

* [PATCH v2 net,stable 1/2] net: fec: restore dev_id in the cases of probe error
From: Fugang Duan @ 2018-01-03  2:39 UTC (permalink / raw)
  To: festevam, davem; +Cc: netdev, troy.kisky, andrew, fugang.duan
In-Reply-To: <1514947170-8887-1-git-send-email-fugang.duan@nxp.com>

The static variable dev_id always plus one before netdev registerred.
It should restore the dev_id value in the cases of probe error.

Signed-off-by: Fugang Duan <fugang.duan@nxp.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index e17d10b..dae89bc 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -3576,6 +3576,7 @@ static int fec_enet_get_irq_cnt(struct platform_device *pdev)
 	of_node_put(phy_node);
 failed_ioremap:
 	free_netdev(ndev);
+	dev_id--;
 
 	return ret;
 }
-- 
1.9.1

^ permalink raw reply related

* [PATCH v2 net,stable 2/2] net: fec: defer probe if regulator is not ready
From: Fugang Duan @ 2018-01-03  2:39 UTC (permalink / raw)
  To: festevam, davem; +Cc: netdev, troy.kisky, andrew, fugang.duan
In-Reply-To: <1514947170-8887-1-git-send-email-fugang.duan@nxp.com>

Defer probe if regulator is not ready. E.g. some regulator is fixed
regulator controlled by i2c expander gpio, the i2c device may be probed
after the driver, then it should handle the case of defer probe error.

Signed-off-by: Fugang Duan <fugang.duan@nxp.com>
---
 drivers/net/ethernet/freescale/fec_main.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index dae89bc..feed383 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -3489,6 +3489,10 @@ static int fec_enet_get_irq_cnt(struct platform_device *pdev)
 			goto failed_regulator;
 		}
 	} else {
+		if (PTR_ERR(fep->reg_phy) == -EPROBE_DEFER) {
+			ret = -EPROBE_DEFER;
+			goto failed_regulator;
+		}
 		fep->reg_phy = NULL;
 	}
 
-- 
1.9.1

^ permalink raw reply related

* Re: [patch iproute2 v4 2/3] tc: Add -bs option to batch mode
From: Chris Mi @ 2018-01-03  2:44 UTC (permalink / raw)
  To: Marcelo Ricardo Leitner; +Cc: netdev, gerlitz.or, stephen, dsahern
In-Reply-To: <20180102200425.GA725@localhost.localdomain>


> On Tue, Jan 02, 2018 at 11:28:03PM +0900, Chris Mi wrote:
>> @@ -240,23 +244,49 @@ static int batch(const char *name)
>>   	}
>>   
>>   	cmdlineno = 0;
>> -	while (getcmdline(&line, &len, stdin) != -1) {
>> +	if (getcmdline(&line, &len, stdin) == -1)
>> +		goto Exit;
>> +	do {
>>   		char *largv[100];
>>   		int largc;
>>   
>> +		if (getcmdline(&line2, &len, stdin) == -1)
>> +			lastline = true;
>> +
>>   		largc = makeargs(line, largv, 100);
>>   		if (largc == 0)
>>   			continue;	/* blank line */
> If it reads a new line, it won't process anything else after it
> because line won't get updated.
Indeed. Thanks for catching it. After fixing it, I find that it only 
works if the blank line is
in the beginning or middle. If the blank line is in the end, we may lose 
at most batchsize - 1 rules.
It is not easy to fix it. I think this issue is trivial. It is not worth 
to make the code complex to fix it.
So I describe this limitation in the man page.

-Chris
>
>    Marcelo
>
>>   
>> -		if (do_cmd(largc, largv)) {
>> -			fprintf(stderr, "Command failed %s:%d\n", name, cmdlineno);
>> +		line = line2;
>> +		line2 = NULL;
>> +		len = 0;
>> +
>> +		/*
>> +		 * In batch mode, if we haven't accumulated enough commands
>> +		 * and this is not the last command, don't send the message
>> +		 * immediately.
>> +		 */
>> +		if (batch_size > 1 && msg_iov_index + 1 != batch_size
>> +		    && !lastline)
>> +			send = false;
>> +		else
>> +			send = true;
>> +
>> +		ret = do_cmd(largc, largv, batch_size, msg_iov_index++, send);
>> +		if (ret < 0) {
>> +			fprintf(stderr, "Command failed %s:%d\n", name,
>> +				cmdlineno);
>>   			ret = 1;
>>   			if (!force)
>>   				break;
>>   		}
>> -	}
>> -	if (line)
>> -		free(line);
>> +		msg_iov_index %= batch_size;
>> +	} while (!lastline);
>> +
>> +	free_filter_reqs();
>> +	free_action_reqs();
>> +Exit:
>> +	free(line);
>>   
>>   	rtnl_close(&rth);
>>   	return ret;

^ permalink raw reply

* Re: [PATCH net-next A 0/5] further sfp/phylink updates
From: David Miller @ 2018-01-03  2:45 UTC (permalink / raw)
  To: linux; +Cc: andrew, f.fainelli, netdev
In-Reply-To: <20171229121451.GY10595@n2100.armlinux.org.uk>

From: Russell King - ARM Linux <linux@armlinux.org.uk>
Date: Fri, 29 Dec 2017 12:14:51 +0000

> This series:
> - cleans up printing of module information
> - improves the transceiver capability decoding, getting rid of the
>   guessing by connector type, improves direct-attach cable support
>   and adds support for 1G Base-PX and Base-BX10 modules.
> - cleans up phylink_sfp_module_insert()

Series applied, thanks Russell.

^ permalink raw reply

* Re: [PATCH iproute2-next 1/9] rdam: Add option to provide "-" sign for the port number
From: David Ahern @ 2018-01-03  2:46 UTC (permalink / raw)
  To: Leon Romanovsky, Doug Ledford, Jason Gunthorpe
  Cc: RDMA mailing list, Leon Romanovsky, netdev, Stephen Hemminger
In-Reply-To: <20180102093725.6172-2-leon-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>

a couple of nits

On 1/2/18 2:37 AM, Leon Romanovsky wrote:
> diff --git a/rdma/utils.c b/rdma/utils.c
> index 7b2001e2..7c920a5c 100644
> --- a/rdma/utils.c
> +++ b/rdma/utils.c
> @@ -10,6 +10,7 @@
>   */
>  
>  #include "rdma.h"
> +#include <ctype.h>
>  
>  static int rd_argc(struct rd *rd)
>  {
> @@ -50,13 +51,43 @@ bool rd_no_arg(struct rd *rd)
>  	return rd_argc(rd) == 0;
>  }
>  
> -uint32_t get_port_from_argv(struct rd *rd)
> +/*
> + * Possible input:output
> + * dev/port    | first port | is_dump_all
> + * mlx5_1      | 0          | true
> + * mlx5_1/     | 0          | true
> + * mlx5_1/0    | 0          | false
> + * mlx5_1/1    | 1          | false
> + * mlx5_1/-    | 0          | false
> + *
> + * In strict mode, /- will return error.
> + */
> +static int get_port_from_argv(struct rd *rd, uint32_t *port,
> +			      bool *is_dump_all, bool strict_port)
>  {
>  	char *slash;
>  
> +	*port = 0;
> +	*is_dump_all = true;
> +
>  	slash = strchr(rd_argv(rd), '/');
>  	/* if no port found, return 0 */
> -	return slash ? atoi(slash + 1) : 0;
> +	if (slash) {

++slash here would alleviate the need for all of the +1's.


> +		if (*(slash + 1) == '-') {
> +			if (strict_port)
> +				return -EINVAL;
> +			*is_dump_all = false;
> +			return 0;
> +		}
> +
> +		if (isdigit(*(slash + 1))) {
> +			*is_dump_all = false;
> +			*port = atoi(slash + 1);
> +		}
> +		if (!*port && strlen(slash + 1))
> +			return -EINVAL;
> +	}
> +	return 0;
>  }
>  
>  static struct dev_map *dev_map_alloc(const char *dev_name)
> @@ -152,7 +183,7 @@ void rd_free(struct rd *rd)
>  	dev_map_cleanup(rd);
>  }
>  
> -int rd_exec_link(struct rd *rd, int (*cb)(struct rd *rd))
> +int rd_exec_link(struct rd *rd, int (*cb)(struct rd *rd), bool strict_port)
>  {
>  	struct dev_map *dev_map;
>  	uint32_t port;
> @@ -163,7 +194,8 @@ int rd_exec_link(struct rd *rd, int (*cb)(struct rd *rd))
>  	if (rd_no_arg(rd)) {
>  		list_for_each_entry(dev_map, &rd->dev_map_list, list) {
>  			rd->dev_idx = dev_map->idx;
> -			for (port = 1; port < dev_map->num_ports + 1; port++) {
> +			port = (strict_port) ? 1 : 0;
> +			for (; port < dev_map->num_ports + 1; port++) {
>  				rd->port_idx = port;
>  				ret = cb(rd);
>  				if (ret)
> @@ -172,21 +204,22 @@ int rd_exec_link(struct rd *rd, int (*cb)(struct rd *rd))
>  		}
>  
>  	} else {
> +		bool is_dump_all;
>  		dev_map = dev_map_lookup(rd, true);

newline between declarations and code.

> -		port = get_port_from_argv(rd);
> -		if (!dev_map || port > dev_map->num_ports) {
> +		ret = get_port_from_argv(rd, &port, &is_dump_all, strict_port);
> +		if (!dev_map || port > dev_map->num_ports || (!port && ret)) {
>  			pr_err("Wrong device name\n");
>  			ret = -ENOENT;
>  			goto out;
>  		}
>  		rd_arg_inc(rd);
>  		rd->dev_idx = dev_map->idx;
> -		rd->port_idx = port ? : 1;
> +		rd->port_idx = port;
>  		for (; rd->port_idx < dev_map->num_ports + 1; rd->port_idx++) {
>  			ret = cb(rd);
>  			if (ret)
>  				goto out;
> -			if (port)
> +			if (!is_dump_all)
>  				/*
>  				 * We got request to show link for devname
>  				 * with port index.
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH iproute2-next 3/9] rdma: Add filtering infrastructure
From: David Ahern @ 2018-01-03  2:47 UTC (permalink / raw)
  To: Leon Romanovsky, Doug Ledford, Jason Gunthorpe
  Cc: RDMA mailing list, Leon Romanovsky, netdev, Stephen Hemminger
In-Reply-To: <20180102093725.6172-4-leon@kernel.org>

On 1/2/18 2:37 AM, Leon Romanovsky wrote:
> +/*
> + * Check if string entry is filtered:
> + *  * key doesn't exist -> user didn't request -> not filtered
> + */
> +bool rd_check_is_string_filtered(struct rd *rd, const char *key, char *val)
> +{
> +	bool key_is_filtered = false;
> +	struct filter_entry *fe;
> +	char *p = NULL;
> +	char *str;
> +
> +	list_for_each_entry(fe, &rd->filter_list, list) {
> +		if (!strcmpx(fe->key, key)) {
> +			/* We found the key */
> +			p = strdup(fe->value);

if (p == NULL) ...

> +
> +			/*
> +			 * Need to check if value in range
> +			 * It can come in the following formats
> +			 * and their permutations:
> +			 * str
> +			 * str1,str2
> +			 */
> +			str = strtok(p, ",");
> +			while (str) {
> +				if (!strcmpx(str, val)) {
> +					key_is_filtered = true;
> +					goto out;
> +				}
> +				str = strtok(NULL, ",");
> +			}
> +			goto out;
> +		}
> +	}
> +
> +out:
> +	free(p);
> +	return key_is_filtered;
> +}
> +

^ permalink raw reply

* Re: [PATCH] 3c59x: fix missing dma_mapping_error check
From: David Miller @ 2018-01-03  2:48 UTC (permalink / raw)
  To: nhorman; +Cc: netdev, nhorman, klassert
In-Reply-To: <20171229164010.1991-1-nhorman@tuxdriver.com>

From: Neil Horman <nhorman@tuxdriver.com>
Date: Fri, 29 Dec 2017 11:40:10 -0500

> @@ -2067,6 +2072,9 @@ vortex_start_xmit(struct sk_buff *skb, struct net_device *dev)
>  		int len = (skb->len + 3) & ~3;
>  		vp->tx_skb_dma = pci_map_single(VORTEX_PCI(vp), skb->data, len,
>  						PCI_DMA_TODEVICE);
> +		if (dma_mapping_error(&VORTEX_PCI(vp)->dev, vp->tx_skb_dma))
> +			return NETDEV_TX_OK;
> +

This leaks the SKB, right?

And for the RX cases, it allows the RX ring to deplete to empty which
tends to hang most chips.  You need to make the DMA failure detection
early and recycle the RX buffer back to the chip instead of passing
it up to the stack.

^ permalink raw reply

* Re: [patch iproute2 v4 3/3] man: Add -bs option to tc manpage
From: Chris Mi @ 2018-01-03  2:48 UTC (permalink / raw)
  To: Marcelo Ricardo Leitner; +Cc: netdev, gerlitz.or, stephen, dsahern
In-Reply-To: <20180102200718.GB725@localhost.localdomain>

2018/1/3 4:07, Marcelo Ricardo Leitner:
> On Tue, Jan 02, 2018 at 11:28:04PM +0900, Chris Mi wrote:
>> Signed-off-by: Chris Mi <chrism@mellanox.com>
>> ---
>>   man/man8/tc.8 | 5 +++++
>>   1 file changed, 5 insertions(+)
>>
>> diff --git a/man/man8/tc.8 b/man/man8/tc.8
>> index ff071b33..de137e16 100644
>> --- a/man/man8/tc.8
>> +++ b/man/man8/tc.8
>> @@ -601,6 +601,11 @@ must exist already.
>>   read commands from provided file or standard input and invoke them.
>>   First failure will cause termination of tc.
>>   
>> +.TP
>> +.BR "\-bs", " \-bs size", " \-batchsize", " \-batchsize size"
>> +How many commands are accumulated before sending to kernel.
>> +By default, it is 1. It only takes effect in batch mode.
>> +
> You should also describe the limitations it has. Like, it only works
> for action and filter and that it shouldn't be mixed with other
> commands.
Done.
> And maybe even do such check in the code: refuse to do other commands
> if batch_size > 1.
I didn't add it because I'm afraid the benefit may be gone if I add the 
check.
But I add a warning in the man page.
>
>>   .TP
>>   .BR "\-force"
>>   don't terminate tc on errors in batch mode.
>> -- 
>> 2.14.3
>>

^ permalink raw reply

* Re: [PATCH net] ethtool: do not print warning for applications using legacy API
From: David Miller @ 2018-01-03  2:50 UTC (permalink / raw)
  To: stephen; +Cc: decot, netdev, linux-kernel
In-Reply-To: <20171229180252.6981-1-sthemmin@microsoft.com>

From: Stephen Hemminger <stephen@networkplumber.org>
Date: Fri, 29 Dec 2017 10:02:52 -0800

> From: Stephen Hemminger <stephen@networkplumber.org>
> 
> In kernel log ths message appears on every boot:
>  "warning: `NetworkChangeNo' uses legacy ethtool link settings API,
>   link modes are only partially reported"
> 
> When ethtool link settings API changed, it started complaining about
> usages of old API. Ironically, the original patch was from google but
> the application using the legacy API is chrome.

Chrome on my machine doesn't do this, FWIW...

> Linux ABI is fixed as much as possible. The kernel must not break it
> and should not complain about applications using legacy API's.
> This patch just removes the warning since using legacy API's
> in Linux is perfectly acceptable.
> 
> Fixes: 3f1ac7a700d0 ("net: ethtool: add new ETHTOOL_xLINKSETTINGS API")
> Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>

Applied and queued up for -stable.

^ permalink raw reply

* Re: [PATCH iproute2-next 6/9] rdma: Update kernel header file
From: David Ahern @ 2018-01-03  2:50 UTC (permalink / raw)
  To: Leon Romanovsky, Doug Ledford, Jason Gunthorpe
  Cc: RDMA mailing list, Leon Romanovsky, netdev, Stephen Hemminger
In-Reply-To: <20180102093725.6172-7-leon-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>

On 1/2/18 2:37 AM, Leon Romanovsky wrote:
> From: Leon Romanovsky <leonro-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
> 
> Synchronize iporute2 package with latest kernel
> RDMA netlink header file.
> 
> Signed-off-by: Leon Romanovsky <leonro-VPRAkNaXOzVWk0Htik3J/w@public.gmane.org>
> ---
>  include/uapi/rdma/rdma_netlink.h | 58 ++++++++++++++++++++++++++++++++++++++--
>  1 file changed, 56 insertions(+), 2 deletions(-)

FYI: uapi headers are updated separately. Once the patches hit net-next,
I will update the headers and drop this patch.
--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH net] cxgb4: Fix FW flash errors
From: David Miller @ 2018-01-03  2:51 UTC (permalink / raw)
  To: ganeshgr; +Cc: netdev, nirranjan, indranil, venkatesh, arjun, leedom
In-Reply-To: <1514572569-28462-1-git-send-email-ganeshgr@chelsio.com>

From: Ganesh Goudar <ganeshgr@chelsio.com>
Date: Sat, 30 Dec 2017 00:06:09 +0530

> From: Arjun Vynipadath <arjun@chelsio.com>
> 
> Initialize adapter->params.sf_fw_start to fix firmware flash
> issues. Use existing macros defined for FW flash addresses.
> 
> Fixes: 96ac18f14a5a ("cxgb4: Add support for new flash parts")
> Signed-off-by: Arjun Vynipadath <arjun@chelsio.com>
> Signed-off-by: Casey Leedom <leedom@chelsio.com>
> Signed-off-by: Ganesh Goudar <ganeshgr@chelsio.com>

This commit log message doesn't match the patch.

You say "Initialize adapter->params.sf_fw_start", but this patch
is removing that struct member altogether.

^ permalink raw reply

* Re: [net 1/1] tipc: fix problems with multipoint-to-point flow control
From: David Miller @ 2018-01-03  2:52 UTC (permalink / raw)
  To: jon.maloy
  Cc: netdev, mohan.krishna.ghanta.krishnamurthy, tung.q.nguyen,
	hoang.h.le, canh.d.luu, ying.xue, tipc-discussion
In-Reply-To: <1514573282-4355-1-git-send-email-jon.maloy@ericsson.com>

From: Jon Maloy <jon.maloy@ericsson.com>
Date: Fri, 29 Dec 2017 19:48:02 +0100

> In commit 04d7b574b245 ("tipc: add multipoint-to-point flow control") we
> introduced a protocol for preventing buffer overflow when many group
> members try to simultaneously send messages to the same receiving member.
> 
> Stress test of this mechanism has revealed a couple of related bugs:
> 
> - When the receiving member receives an advertisement REMIT message from
>   one of the senders, it will sometimes prematurely activate a pending
>   member and send it the remitted advertisement, although the upper
>   limit for active senders has been reached. This leads to accumulation
>   of illegal advertisements, and eventually to messages being dropped
>   because of receive buffer overflow.
> 
> - When the receiving member leaves REMITTED state while a received
>   message is being read, we miss to look at the pending queue, to
>   activate the oldest pending peer. This leads to some pending senders
>   being starved out, and never getting the opportunity to profit from
>   the remitted advertisement.
> 
> We fix the former in the function tipc_group_proto_rcv() by returning
> directly from the function once it becomes clear that the remitting
> peer cannot leave REMITTED state at that point.
> 
> We fix the latter in the function tipc_group_update_rcv_win() by looking
> up and activate the longest pending peer when it becomes clear that the
> remitting peer now can leave REMITTED state.
> 
> Signed-off-by: Jon Maloy <jon.maloy@ericsson.com>

Applied, thanks Jon.

^ permalink raw reply

* Re: [PATCH net-next 2/2] tun: allow to attach ebpf socket filter
From: Jason Wang @ 2018-01-03  2:53 UTC (permalink / raw)
  To: Willem de Bruijn
  Cc: Network Development, LKML, Michael S. Tsirkin, Willem de Bruijn
In-Reply-To: <CAF=yD-KydM326DErG5XaafCN=R=p2V48MgUDH0LRpPrXCUeOdA@mail.gmail.com>



On 2018年01月02日 17:19, Willem de Bruijn wrote:
>>> More importantly, should this program just return a boolean pass or
>>> drop. Taking a length and trimming may introduce bugs later on if the
>>> stack parses the packet unconditionally, expecting a minimum size
>>> to be present.
>>>
>>> This was the reason for introducing sk_filter_trim_cap and using that
>>> in other sk_filter sites.
>>>
>>> A quick scan shows that tun_put_user expects a full vlan tag to exist
>>> if skb_vlan_tag_present(skb), for instance. If trimmed to below this
>>> length the final call to skb_copy_datagram_iter may have negative
>>> length.
>>>
>>> This is an issue with the existing sk_filter call as much as with the
>>> new run_ebpf_filter call.
>> Good point, so consider it was used by sk_filter too, we need to fix it
>> anyway. Actually, I've considered the boolean return value but finally I
>> decide to obey the style of sk filter. Maybe the trimming has real user. e.g
>> high speed header recoding/analysis? Consider it's not hard to fix, how
>> about just keep that?
> I don't see an obvious use case, but sure. We'll just need to look
> at what the minimum trim length needs to be.

It looks to me that the minimum length is:

skb_vlan_tag_present(skb) ? offsetof(struct vlan_ethhdr, h_vlan_proto) : 0

And consider the vlan tag insertion done in tun_put_user(), we need trim 
4 more bytes if vlan tag is present.

Thanks

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox