linux-can-fixes-for-5.0-20190122

-----BEGIN PGP SIGNATURE-----
 
 iQFHBAABCgAxFiEENrCndlB/VnAEWuH5k9IU1zQoZfEFAlxHFuoTHG1rbEBwZW5n
 dXRyb25peC5kZQAKCRCT0hTXNChl8eRAB/9Sp32xbjIVeyyEro8+vmlJ/HlSNgcC
 txqmmh0ce4n1gglV3G5ll8mDYJsk5Qz+ur8wbud7CVxFmpeGqkAA7qoYeD8DawSp
 /77dBG8yX/t8vxU5jGK9l5FomVcrqKSVbK20R6u0MLeZhF+VdJCu7cDElgIsKDqX
 N76Df/mTnfdhReoM05CXEwzvEN8StHljm+oecyunxfw3XPtqDkO7QHEVYpk2zwVI
 4U2aYu9L1gDbj5yGXNu8l/WwEL4ttyC7rqoW9we1hsDVtxRh1/o+Tond6/HPxIcN
 voO/fm97ZKxpDL3cE0Jg6Grq9jUek7GT8oRRkAdWO4YaLr3f70kibQ3s
 =d+ps
 -----END PGP SIGNATURE-----

Merge tag 'linux-can-fixes-for-5.0-20190122' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can

Marc Kleine-Budde says:

====================
pull-request: can 2019-01-22

this is a pull request of 4 patches for net/master.

The first patch by is by Manfred Schlaegl and reverts a patch that caused wrong
warning messages in certain use cases. The next patch is by Oliver Hartkopp for
the bcm that adds sanity checks for the timer value before using it to detect
potential interger overflows. The last two patches are for the flexcan driver,
YueHaibing's patch fixes the the return value in the error path of the
flexcan_setup_stop_mode() function. The second patch is by Uwe Kleine-König and
fixes a NULL pointer deref on older flexcan cores in flexcan_chip_start().
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2019-01-24 21:52:37 -08:00
commit 9620d6f683
3 changed files with 42 additions and 16 deletions

View File

@ -480,8 +480,6 @@ EXPORT_SYMBOL_GPL(can_put_echo_skb);
struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr) struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr)
{ {
struct can_priv *priv = netdev_priv(dev); struct can_priv *priv = netdev_priv(dev);
struct sk_buff *skb = priv->echo_skb[idx];
struct canfd_frame *cf;
if (idx >= priv->echo_skb_max) { if (idx >= priv->echo_skb_max) {
netdev_err(dev, "%s: BUG! Trying to access can_priv::echo_skb out of bounds (%u/max %u)\n", netdev_err(dev, "%s: BUG! Trying to access can_priv::echo_skb out of bounds (%u/max %u)\n",
@ -489,20 +487,21 @@ struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8
return NULL; return NULL;
} }
if (!skb) { if (priv->echo_skb[idx]) {
netdev_err(dev, "%s: BUG! Trying to echo non existing skb: can_priv::echo_skb[%u]\n",
__func__, idx);
return NULL;
}
/* Using "struct canfd_frame::len" for the frame /* Using "struct canfd_frame::len" for the frame
* length is supported on both CAN and CANFD frames. * length is supported on both CAN and CANFD frames.
*/ */
cf = (struct canfd_frame *)skb->data; struct sk_buff *skb = priv->echo_skb[idx];
*len_ptr = cf->len; struct canfd_frame *cf = (struct canfd_frame *)skb->data;
u8 len = cf->len;
*len_ptr = len;
priv->echo_skb[idx] = NULL; priv->echo_skb[idx] = NULL;
return skb; return skb;
}
return NULL;
} }
/* /*

View File

@ -1106,7 +1106,7 @@ static int flexcan_chip_start(struct net_device *dev)
} }
} else { } else {
/* clear and invalidate unused mailboxes first */ /* clear and invalidate unused mailboxes first */
for (i = FLEXCAN_TX_MB_RESERVED_OFF_FIFO; i <= priv->mb_count; i++) { for (i = FLEXCAN_TX_MB_RESERVED_OFF_FIFO; i < priv->mb_count; i++) {
mb = flexcan_get_mb(priv, i); mb = flexcan_get_mb(priv, i);
priv->write(FLEXCAN_MB_CODE_RX_INACTIVE, priv->write(FLEXCAN_MB_CODE_RX_INACTIVE,
&mb->can_ctrl); &mb->can_ctrl);
@ -1432,7 +1432,7 @@ static int flexcan_setup_stop_mode(struct platform_device *pdev)
gpr_np = of_find_node_by_phandle(phandle); gpr_np = of_find_node_by_phandle(phandle);
if (!gpr_np) { if (!gpr_np) {
dev_dbg(&pdev->dev, "could not find gpr node by phandle\n"); dev_dbg(&pdev->dev, "could not find gpr node by phandle\n");
return PTR_ERR(gpr_np); return -ENODEV;
} }
priv = netdev_priv(dev); priv = netdev_priv(dev);

View File

@ -67,6 +67,9 @@
*/ */
#define MAX_NFRAMES 256 #define MAX_NFRAMES 256
/* limit timers to 400 days for sending/timeouts */
#define BCM_TIMER_SEC_MAX (400 * 24 * 60 * 60)
/* use of last_frames[index].flags */ /* use of last_frames[index].flags */
#define RX_RECV 0x40 /* received data for this element */ #define RX_RECV 0x40 /* received data for this element */
#define RX_THR 0x80 /* element not been sent due to throttle feature */ #define RX_THR 0x80 /* element not been sent due to throttle feature */
@ -140,6 +143,22 @@ static inline ktime_t bcm_timeval_to_ktime(struct bcm_timeval tv)
return ktime_set(tv.tv_sec, tv.tv_usec * NSEC_PER_USEC); return ktime_set(tv.tv_sec, tv.tv_usec * NSEC_PER_USEC);
} }
/* check limitations for timeval provided by user */
static bool bcm_is_invalid_tv(struct bcm_msg_head *msg_head)
{
if ((msg_head->ival1.tv_sec < 0) ||
(msg_head->ival1.tv_sec > BCM_TIMER_SEC_MAX) ||
(msg_head->ival1.tv_usec < 0) ||
(msg_head->ival1.tv_usec >= USEC_PER_SEC) ||
(msg_head->ival2.tv_sec < 0) ||
(msg_head->ival2.tv_sec > BCM_TIMER_SEC_MAX) ||
(msg_head->ival2.tv_usec < 0) ||
(msg_head->ival2.tv_usec >= USEC_PER_SEC))
return true;
return false;
}
#define CFSIZ(flags) ((flags & CAN_FD_FRAME) ? CANFD_MTU : CAN_MTU) #define CFSIZ(flags) ((flags & CAN_FD_FRAME) ? CANFD_MTU : CAN_MTU)
#define OPSIZ sizeof(struct bcm_op) #define OPSIZ sizeof(struct bcm_op)
#define MHSIZ sizeof(struct bcm_msg_head) #define MHSIZ sizeof(struct bcm_msg_head)
@ -873,6 +892,10 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
if (msg_head->nframes < 1 || msg_head->nframes > MAX_NFRAMES) if (msg_head->nframes < 1 || msg_head->nframes > MAX_NFRAMES)
return -EINVAL; return -EINVAL;
/* check timeval limitations */
if ((msg_head->flags & SETTIMER) && bcm_is_invalid_tv(msg_head))
return -EINVAL;
/* check the given can_id */ /* check the given can_id */
op = bcm_find_op(&bo->tx_ops, msg_head, ifindex); op = bcm_find_op(&bo->tx_ops, msg_head, ifindex);
if (op) { if (op) {
@ -1053,6 +1076,10 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
(!(msg_head->can_id & CAN_RTR_FLAG)))) (!(msg_head->can_id & CAN_RTR_FLAG))))
return -EINVAL; return -EINVAL;
/* check timeval limitations */
if ((msg_head->flags & SETTIMER) && bcm_is_invalid_tv(msg_head))
return -EINVAL;
/* check the given can_id */ /* check the given can_id */
op = bcm_find_op(&bo->rx_ops, msg_head, ifindex); op = bcm_find_op(&bo->rx_ops, msg_head, ifindex);
if (op) { if (op) {