Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

can: bcm: check timer values before ktime conversion

Kyungtae Kim detected a potential integer overflow in bcm_[rx|tx]_setup()
when the conversion into ktime multiplies the given value with NSEC_PER_USEC
(1000).

Reference: https://marc.info/?l=linux-can&m=154732118819828&w=2

Add a check for the given tv_usec, so that the value stays below one second.
Additionally limit the tv_sec value to a reasonable value for CAN related
use-cases of 400 days and ensure all values to be positive.

Reported-by: Kyungtae Kim <kt0755@gmail.com>
Tested-by: Oliver Hartkopp <socketcan@hartkopp.net>
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
Cc: linux-stable <stable@vger.kernel.org> # >= 2.6.26
Tested-by: Kyungtae Kim <kt0755@gmail.com>
Acked-by: Andre Naujoks <nautsch2@gmail.com>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>

authored by

Oliver Hartkopp and committed by
Marc Kleine-Budde
93171ba6 7b12c818

+27
+27
net/can/bcm.c
··· 67 67 */ 68 68 #define MAX_NFRAMES 256 69 69 70 + /* limit timers to 400 days for sending/timeouts */ 71 + #define BCM_TIMER_SEC_MAX (400 * 24 * 60 * 60) 72 + 70 73 /* use of last_frames[index].flags */ 71 74 #define RX_RECV 0x40 /* received data for this element */ 72 75 #define RX_THR 0x80 /* element not been sent due to throttle feature */ ··· 141 138 static inline ktime_t bcm_timeval_to_ktime(struct bcm_timeval tv) 142 139 { 143 140 return ktime_set(tv.tv_sec, tv.tv_usec * NSEC_PER_USEC); 141 + } 142 + 143 + /* check limitations for timeval provided by user */ 144 + static bool bcm_is_invalid_tv(struct bcm_msg_head *msg_head) 145 + { 146 + if ((msg_head->ival1.tv_sec < 0) || 147 + (msg_head->ival1.tv_sec > BCM_TIMER_SEC_MAX) || 148 + (msg_head->ival1.tv_usec < 0) || 149 + (msg_head->ival1.tv_usec >= USEC_PER_SEC) || 150 + (msg_head->ival2.tv_sec < 0) || 151 + (msg_head->ival2.tv_sec > BCM_TIMER_SEC_MAX) || 152 + (msg_head->ival2.tv_usec < 0) || 153 + (msg_head->ival2.tv_usec >= USEC_PER_SEC)) 154 + return true; 155 + 156 + return false; 144 157 } 145 158 146 159 #define CFSIZ(flags) ((flags & CAN_FD_FRAME) ? CANFD_MTU : CAN_MTU) ··· 892 873 if (msg_head->nframes < 1 || msg_head->nframes > MAX_NFRAMES) 893 874 return -EINVAL; 894 875 876 + /* check timeval limitations */ 877 + if ((msg_head->flags & SETTIMER) && bcm_is_invalid_tv(msg_head)) 878 + return -EINVAL; 879 + 895 880 /* check the given can_id */ 896 881 op = bcm_find_op(&bo->tx_ops, msg_head, ifindex); 897 882 if (op) { ··· 1074 1051 if ((msg_head->flags & RX_RTR_FRAME) && 1075 1052 ((msg_head->nframes != 1) || 1076 1053 (!(msg_head->can_id & CAN_RTR_FLAG)))) 1054 + return -EINVAL; 1055 + 1056 + /* check timeval limitations */ 1057 + if ((msg_head->flags & SETTIMER) && bcm_is_invalid_tv(msg_head)) 1077 1058 return -EINVAL; 1078 1059 1079 1060 /* check the given can_id */