| From 48135709d4a0ebfc1e6ea41698726a610b62b68e Mon Sep 17 00:00:00 2001 |
| From: Oliver Hartkopp <socketcan@hartkopp.net> |
| Date: Wed, 11 Aug 2010 16:12:35 -0700 |
| Subject: can: add limit for nframes and clean up signed/unsigned variables |
| |
| |
| From: Oliver Hartkopp <socketcan@hartkopp.net> |
| |
| [ Upstream commit 5b75c4973ce779520b9d1e392483207d6f842cde ] |
| |
| This patch adds a limit for nframes as the number of frames in TX_SETUP and |
| RX_SETUP are derived from a single byte multiplex value by default. |
| Use-cases that would require to send/filter more than 256 CAN frames should |
| be implemented in userspace for complexity reasons anyway. |
| |
| Additionally the assignments of unsigned values from userspace to signed |
| values in kernelspace and vice versa are fixed by using unsigned values in |
| kernelspace consistently. |
| |
| Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net> |
| Reported-by: Ben Hawkes <hawkes@google.com> |
| Acked-by: Urs Thuermann <urs.thuermann@volkswagen.de> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| --- |
| net/can/bcm.c | 41 +++++++++++++++++++++++++++-------------- |
| 1 file changed, 27 insertions(+), 14 deletions(-) |
| |
| --- a/net/can/bcm.c |
| +++ b/net/can/bcm.c |
| @@ -60,6 +60,13 @@ |
| #include <net/sock.h> |
| #include <net/net_namespace.h> |
| |
| +/* |
| + * To send multiple CAN frame content within TX_SETUP or to filter |
| + * CAN messages with multiplex index within RX_SETUP, the number of |
| + * different filters is limited to 256 due to the one byte index value. |
| + */ |
| +#define MAX_NFRAMES 256 |
| + |
| /* use of last_frames[index].can_dlc */ |
| #define RX_RECV 0x40 /* received data for this element */ |
| #define RX_THR 0x80 /* element not been sent due to throttle feature */ |
| @@ -89,16 +96,16 @@ struct bcm_op { |
| struct list_head list; |
| int ifindex; |
| canid_t can_id; |
| - int flags; |
| + u32 flags; |
| unsigned long frames_abs, frames_filtered; |
| struct timeval ival1, ival2; |
| struct hrtimer timer, thrtimer; |
| struct tasklet_struct tsklet, thrtsklet; |
| ktime_t rx_stamp, kt_ival1, kt_ival2, kt_lastmsg; |
| int rx_ifindex; |
| - int count; |
| - int nframes; |
| - int currframe; |
| + u32 count; |
| + u32 nframes; |
| + u32 currframe; |
| struct can_frame *frames; |
| struct can_frame *last_frames; |
| struct can_frame sframe; |
| @@ -175,7 +182,7 @@ static int bcm_proc_show(struct seq_file |
| |
| seq_printf(m, "rx_op: %03X %-5s ", |
| op->can_id, bcm_proc_getifname(ifname, op->ifindex)); |
| - seq_printf(m, "[%d]%c ", op->nframes, |
| + seq_printf(m, "[%u]%c ", op->nframes, |
| (op->flags & RX_CHECK_DLC)?'d':' '); |
| if (op->kt_ival1.tv64) |
| seq_printf(m, "timeo=%lld ", |
| @@ -198,7 +205,7 @@ static int bcm_proc_show(struct seq_file |
| |
| list_for_each_entry(op, &bo->tx_ops, list) { |
| |
| - seq_printf(m, "tx_op: %03X %s [%d] ", |
| + seq_printf(m, "tx_op: %03X %s [%u] ", |
| op->can_id, |
| bcm_proc_getifname(ifname, op->ifindex), |
| op->nframes); |
| @@ -283,7 +290,7 @@ static void bcm_send_to_user(struct bcm_ |
| struct can_frame *firstframe; |
| struct sockaddr_can *addr; |
| struct sock *sk = op->sk; |
| - int datalen = head->nframes * CFSIZ; |
| + unsigned int datalen = head->nframes * CFSIZ; |
| int err; |
| |
| skb = alloc_skb(sizeof(*head) + datalen, gfp_any()); |
| @@ -468,7 +475,7 @@ rx_changed_settime: |
| * bcm_rx_cmp_to_index - (bit)compares the currently received data to formerly |
| * received data stored in op->last_frames[] |
| */ |
| -static void bcm_rx_cmp_to_index(struct bcm_op *op, int index, |
| +static void bcm_rx_cmp_to_index(struct bcm_op *op, unsigned int index, |
| const struct can_frame *rxdata) |
| { |
| /* |
| @@ -554,7 +561,8 @@ static enum hrtimer_restart bcm_rx_timeo |
| /* |
| * bcm_rx_do_flush - helper for bcm_rx_thr_flush |
| */ |
| -static inline int bcm_rx_do_flush(struct bcm_op *op, int update, int index) |
| +static inline int bcm_rx_do_flush(struct bcm_op *op, int update, |
| + unsigned int index) |
| { |
| if ((op->last_frames) && (op->last_frames[index].can_dlc & RX_THR)) { |
| if (update) |
| @@ -575,7 +583,7 @@ static int bcm_rx_thr_flush(struct bcm_o |
| int updated = 0; |
| |
| if (op->nframes > 1) { |
| - int i; |
| + unsigned int i; |
| |
| /* for MUX filter we start at index 1 */ |
| for (i = 1; i < op->nframes; i++) |
| @@ -624,7 +632,7 @@ static void bcm_rx_handler(struct sk_buf |
| { |
| struct bcm_op *op = (struct bcm_op *)data; |
| const struct can_frame *rxframe = (struct can_frame *)skb->data; |
| - int i; |
| + unsigned int i; |
| |
| /* disable timeout */ |
| hrtimer_cancel(&op->timer); |
| @@ -824,14 +832,15 @@ static int bcm_tx_setup(struct bcm_msg_h |
| { |
| struct bcm_sock *bo = bcm_sk(sk); |
| struct bcm_op *op; |
| - int i, err; |
| + unsigned int i; |
| + int err; |
| |
| /* we need a real device to send frames */ |
| if (!ifindex) |
| return -ENODEV; |
| |
| - /* we need at least one can_frame */ |
| - if (msg_head->nframes < 1) |
| + /* check nframes boundaries - we need at least one can_frame */ |
| + if (msg_head->nframes < 1 || msg_head->nframes > MAX_NFRAMES) |
| return -EINVAL; |
| |
| /* check the given can_id */ |
| @@ -995,6 +1004,10 @@ static int bcm_rx_setup(struct bcm_msg_h |
| msg_head->nframes = 0; |
| } |
| |
| + /* the first element contains the mux-mask => MAX_NFRAMES + 1 */ |
| + if (msg_head->nframes > MAX_NFRAMES + 1) |
| + return -EINVAL; |
| + |
| if ((msg_head->flags & RX_RTR_FRAME) && |
| ((msg_head->nframes != 1) || |
| (!(msg_head->can_id & CAN_RTR_FLAG)))) |