lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <55B679B8.30705@hartkopp.net>
Date:	Mon, 27 Jul 2015 20:34:32 +0200
From:	Oliver Hartkopp <socketcan@...tkopp.net>
To:	Greg KH <gregkh@...uxfoundation.org>
CC:	Marc Kleine-Budde <mkl@...gutronix.de>, netdev@...r.kernel.org,
	davem@...emloft.net, linux-can@...r.kernel.org,
	kernel@...gutronix.de, linux-stable <stable@...r.kernel.org>
Subject: Re: [PATCH 8/8] can: replace timestamp as unique skb attribute

Hello Greg,

On 12.07.2015 21:18, Marc Kleine-Budde wrote:
> From: Oliver Hartkopp <socketcan@...tkopp.net>
>
> Commit 514ac99c64b "can: fix multiple delivery of a single CAN frame for
> overlapping CAN filters" requires the skb->tstamp to be set to check for
> identical CAN skbs.
>
> Without timestamping to be required by user space applications this timestamp
> was not generated which lead to commit 36c01245eb8 "can: fix loss of CAN frames
> in raw_rcv" - which forces the timestamp to be set in all CAN related skbuffs
> by introducing several __net_timestamp() calls.
>
> This forces e.g. out of tree drivers which are not using alloc_can{,fd}_skb()
> to add __net_timestamp() after skbuff creation to prevent the frame loss fixed
> in mainline Linux.
>
> This patch removes the timestamp dependency and uses an atomic counter to
> create an unique identifier together with the skbuff pointer.
>
> Btw: the new skbcnt element introduced in struct can_skb_priv has to be
> initialized with zero in out-of-tree drivers which are not using
> alloc_can{,fd}_skb() too.
>
> Signed-off-by: Oliver Hartkopp <socketcan@...tkopp.net>
> Cc: linux-stable <stable@...r.kernel.org>

Can you please queue up this missing/lost patch for the long term 4.1.x ?

It fixes the mess with commits

514ac99c64b "can: fix multiple delivery of a single CAN frame for overlapping 
CAN filters"

which originally fixed

36c01245eb8 "can: fix loss of CAN frames in raw_rcv"

So finally this missing patch would bring 4.1.x into the proper state we now 
have in 4.2-rc4.

Upstream commit of this patch is:

http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=d3b58c47d330de8c29898fe9746f7530408f8a59

Best regards,
Oliver


> Signed-off-by: Marc Kleine-Budde <mkl@...gutronix.de>
> ---
>   drivers/net/can/dev.c   |  7 ++-----
>   drivers/net/can/slcan.c |  2 +-
>   drivers/net/can/vcan.c  |  3 ---
>   include/linux/can/skb.h |  2 ++
>   net/can/af_can.c        | 12 +++++++-----
>   net/can/bcm.c           |  2 ++
>   net/can/raw.c           |  7 ++++---
>   7 files changed, 18 insertions(+), 17 deletions(-)
>
> diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c
> index e9b1810d319f..aede704605c6 100644
> --- a/drivers/net/can/dev.c
> +++ b/drivers/net/can/dev.c
> @@ -440,9 +440,6 @@ unsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx)
>   		struct can_frame *cf = (struct can_frame *)skb->data;
>   		u8 dlc = cf->can_dlc;
>
> -		if (!(skb->tstamp.tv64))
> -			__net_timestamp(skb);
> -
>   		netif_rx(priv->echo_skb[idx]);
>   		priv->echo_skb[idx] = NULL;
>
> @@ -578,7 +575,6 @@ struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf)
>   	if (unlikely(!skb))
>   		return NULL;
>
> -	__net_timestamp(skb);
>   	skb->protocol = htons(ETH_P_CAN);
>   	skb->pkt_type = PACKET_BROADCAST;
>   	skb->ip_summed = CHECKSUM_UNNECESSARY;
> @@ -589,6 +585,7 @@ struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf)
>
>   	can_skb_reserve(skb);
>   	can_skb_prv(skb)->ifindex = dev->ifindex;
> +	can_skb_prv(skb)->skbcnt = 0;
>
>   	*cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame));
>   	memset(*cf, 0, sizeof(struct can_frame));
> @@ -607,7 +604,6 @@ struct sk_buff *alloc_canfd_skb(struct net_device *dev,
>   	if (unlikely(!skb))
>   		return NULL;
>
> -	__net_timestamp(skb);
>   	skb->protocol = htons(ETH_P_CANFD);
>   	skb->pkt_type = PACKET_BROADCAST;
>   	skb->ip_summed = CHECKSUM_UNNECESSARY;
> @@ -618,6 +614,7 @@ struct sk_buff *alloc_canfd_skb(struct net_device *dev,
>
>   	can_skb_reserve(skb);
>   	can_skb_prv(skb)->ifindex = dev->ifindex;
> +	can_skb_prv(skb)->skbcnt = 0;
>
>   	*cfd = (struct canfd_frame *)skb_put(skb, sizeof(struct canfd_frame));
>   	memset(*cfd, 0, sizeof(struct canfd_frame));
> diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c
> index f64f5290d6f8..a23a7af8eb9a 100644
> --- a/drivers/net/can/slcan.c
> +++ b/drivers/net/can/slcan.c
> @@ -207,7 +207,6 @@ static void slc_bump(struct slcan *sl)
>   	if (!skb)
>   		return;
>
> -	__net_timestamp(skb);
>   	skb->dev = sl->dev;
>   	skb->protocol = htons(ETH_P_CAN);
>   	skb->pkt_type = PACKET_BROADCAST;
> @@ -215,6 +214,7 @@ static void slc_bump(struct slcan *sl)
>
>   	can_skb_reserve(skb);
>   	can_skb_prv(skb)->ifindex = sl->dev->ifindex;
> +	can_skb_prv(skb)->skbcnt = 0;
>
>   	memcpy(skb_put(skb, sizeof(struct can_frame)),
>   	       &cf, sizeof(struct can_frame));
> diff --git a/drivers/net/can/vcan.c b/drivers/net/can/vcan.c
> index 0ce868de855d..674f367087c5 100644
> --- a/drivers/net/can/vcan.c
> +++ b/drivers/net/can/vcan.c
> @@ -78,9 +78,6 @@ static void vcan_rx(struct sk_buff *skb, struct net_device *dev)
>   	skb->dev       = dev;
>   	skb->ip_summed = CHECKSUM_UNNECESSARY;
>
> -	if (!(skb->tstamp.tv64))
> -		__net_timestamp(skb);
> -
>   	netif_rx_ni(skb);
>   }
>
> diff --git a/include/linux/can/skb.h b/include/linux/can/skb.h
> index b6a52a4b457a..51bb6532785c 100644
> --- a/include/linux/can/skb.h
> +++ b/include/linux/can/skb.h
> @@ -27,10 +27,12 @@
>   /**
>    * struct can_skb_priv - private additional data inside CAN sk_buffs
>    * @ifindex:	ifindex of the first interface the CAN frame appeared on
> + * @skbcnt:	atomic counter to have an unique id together with skb pointer
>    * @cf:		align to the following CAN frame at skb->data
>    */
>   struct can_skb_priv {
>   	int ifindex;
> +	int skbcnt;
>   	struct can_frame cf[0];
>   };
>
> diff --git a/net/can/af_can.c b/net/can/af_can.c
> index 7933e62a7318..166d436196c1 100644
> --- a/net/can/af_can.c
> +++ b/net/can/af_can.c
> @@ -89,6 +89,8 @@ struct timer_list can_stattimer;   /* timer for statistics update */
>   struct s_stats    can_stats;       /* packet statistics */
>   struct s_pstats   can_pstats;      /* receive list statistics */
>
> +static atomic_t skbcounter = ATOMIC_INIT(0);
> +
>   /*
>    * af_can socket functions
>    */
> @@ -310,12 +312,8 @@ int can_send(struct sk_buff *skb, int loop)
>   		return err;
>   	}
>
> -	if (newskb) {
> -		if (!(newskb->tstamp.tv64))
> -			__net_timestamp(newskb);
> -
> +	if (newskb)
>   		netif_rx_ni(newskb);
> -	}
>
>   	/* update statistics */
>   	can_stats.tx_frames++;
> @@ -683,6 +681,10 @@ static void can_receive(struct sk_buff *skb, struct net_device *dev)
>   	can_stats.rx_frames++;
>   	can_stats.rx_frames_delta++;
>
> +	/* create non-zero unique skb identifier together with *skb */
> +	while (!(can_skb_prv(skb)->skbcnt))
> +		can_skb_prv(skb)->skbcnt = atomic_inc_return(&skbcounter);
> +
>   	rcu_read_lock();
>
>   	/* deliver the packet to sockets listening on all devices */
> diff --git a/net/can/bcm.c b/net/can/bcm.c
> index b523453585be..a1ba6875c2a2 100644
> --- a/net/can/bcm.c
> +++ b/net/can/bcm.c
> @@ -261,6 +261,7 @@ static void bcm_can_tx(struct bcm_op *op)
>
>   	can_skb_reserve(skb);
>   	can_skb_prv(skb)->ifindex = dev->ifindex;
> +	can_skb_prv(skb)->skbcnt = 0;
>
>   	memcpy(skb_put(skb, CFSIZ), cf, CFSIZ);
>
> @@ -1217,6 +1218,7 @@ static int bcm_tx_send(struct msghdr *msg, int ifindex, struct sock *sk)
>   	}
>
>   	can_skb_prv(skb)->ifindex = dev->ifindex;
> +	can_skb_prv(skb)->skbcnt = 0;
>   	skb->dev = dev;
>   	can_skb_set_owner(skb, sk);
>   	err = can_send(skb, 1); /* send with loopback */
> diff --git a/net/can/raw.c b/net/can/raw.c
> index 31b9748cbb4e..2e67b1423cd3 100644
> --- a/net/can/raw.c
> +++ b/net/can/raw.c
> @@ -75,7 +75,7 @@ MODULE_ALIAS("can-proto-1");
>    */
>
>   struct uniqframe {
> -	ktime_t tstamp;
> +	int skbcnt;
>   	const struct sk_buff *skb;
>   	unsigned int join_rx_count;
>   };
> @@ -133,7 +133,7 @@ static void raw_rcv(struct sk_buff *oskb, void *data)
>
>   	/* eliminate multiple filter matches for the same skb */
>   	if (this_cpu_ptr(ro->uniq)->skb == oskb &&
> -	    ktime_equal(this_cpu_ptr(ro->uniq)->tstamp, oskb->tstamp)) {
> +	    this_cpu_ptr(ro->uniq)->skbcnt == can_skb_prv(oskb)->skbcnt) {
>   		if (ro->join_filters) {
>   			this_cpu_inc(ro->uniq->join_rx_count);
>   			/* drop frame until all enabled filters matched */
> @@ -144,7 +144,7 @@ static void raw_rcv(struct sk_buff *oskb, void *data)
>   		}
>   	} else {
>   		this_cpu_ptr(ro->uniq)->skb = oskb;
> -		this_cpu_ptr(ro->uniq)->tstamp = oskb->tstamp;
> +		this_cpu_ptr(ro->uniq)->skbcnt = can_skb_prv(oskb)->skbcnt;
>   		this_cpu_ptr(ro->uniq)->join_rx_count = 1;
>   		/* drop first frame to check all enabled filters? */
>   		if (ro->join_filters && ro->count > 1)
> @@ -749,6 +749,7 @@ static int raw_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
>
>   	can_skb_reserve(skb);
>   	can_skb_prv(skb)->ifindex = dev->ifindex;
> +	can_skb_prv(skb)->skbcnt = 0;
>
>   	err = memcpy_from_msg(skb_put(skb, size), msg, size);
>   	if (err < 0)
>
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ