diff --git a/include/linux/can/skb.h b/include/linux/can/skb.h index 1abc25a8d144e891c9a54cb8171ec44b25b83602..0987eafbd95bac38c41acb3e18a5e1b2a0e37bb3 100644 --- a/include/linux/can/skb.h +++ b/include/linux/can/skb.h @@ -109,6 +109,11 @@ static inline bool can_is_can_skb(const struct sk_buff *skb) return (skb->len == CAN_MTU && cf->len <= CAN_MAX_DLEN); } +static inline bool can_is_can_linear_skb(struct sk_buff *skb) +{ + return !skb_linearize(skb) && can_is_can_skb(skb); +} + static inline bool can_is_canfd_skb(const struct sk_buff *skb) { struct canfd_frame *cfd = (struct canfd_frame *)skb->data; @@ -117,6 +122,11 @@ static inline bool can_is_canfd_skb(const struct sk_buff *skb) return (skb->len == CANFD_MTU && cfd->len <= CANFD_MAX_DLEN); } +static inline bool can_is_canfd_linear_skb(struct sk_buff *skb) +{ + return !skb_linearize(skb) && can_is_canfd_skb(skb); +} + static inline bool can_is_canxl_skb(const struct sk_buff *skb) { const struct canxl_frame *cxl = (struct canxl_frame *)skb->data; @@ -131,6 +141,11 @@ static inline bool can_is_canxl_skb(const struct sk_buff *skb) return cxl->flags & CANXL_XLF; } +static inline bool can_is_canxl_linear_skb(struct sk_buff *skb) +{ + return !skb_linearize(skb) && can_is_canxl_skb(skb); +} + /* get length element value from can[|fd|xl]_frame structure */ static inline unsigned int can_skb_get_len_val(struct sk_buff *skb) { diff --git a/net/can/af_can.c b/net/can/af_can.c index b2387a46794a576973f3d865a5ca8e2ba696d167..1eecf8e7d49e4d3c8cd2c287da16a3e396351d93 100644 --- a/net/can/af_can.c +++ b/net/can/af_can.c @@ -679,7 +679,8 @@ static void can_receive(struct sk_buff *skb, struct net_device *dev) static int can_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev) { - if (unlikely(dev->type != ARPHRD_CAN || !can_get_ml_priv(dev) || !can_is_can_skb(skb))) { + if (unlikely(dev->type != ARPHRD_CAN || !can_get_ml_priv(dev) || + !can_is_can_linear_skb(skb))) { pr_warn_once("PF_CAN: dropped non conform CAN skbuff: dev type %d, len %d\n", dev->type, skb->len); @@ -694,7 +695,8 @@ static int can_rcv(struct sk_buff *skb, struct net_device *dev, static int canfd_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev) { - if (unlikely(dev->type != ARPHRD_CAN || !can_get_ml_priv(dev) || !can_is_canfd_skb(skb))) { + if (unlikely(dev->type != ARPHRD_CAN || !can_get_ml_priv(dev) || + !can_is_canfd_linear_skb(skb))) { pr_warn_once("PF_CAN: dropped non conform CAN FD skbuff: dev type %d, len %d\n", dev->type, skb->len); @@ -709,7 +711,8 @@ static int canfd_rcv(struct sk_buff *skb, struct net_device *dev, static int canxl_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev) { - if (unlikely(dev->type != ARPHRD_CAN || !can_get_ml_priv(dev) || !can_is_canxl_skb(skb))) { + if (unlikely(dev->type != ARPHRD_CAN || !can_get_ml_priv(dev) || + !can_is_canxl_linear_skb(skb))) { pr_warn_once("PF_CAN: dropped non conform CAN XL skbuff: dev type %d, len %d\n", dev->type, skb->len);