]> rtime.felk.cvut.cz Git - socketcan-devel.git/blobdiff - kernel/2.6/net/can/bcm.c
can: add limit for nframes and clean up signed/unsigned variables
[socketcan-devel.git] / kernel / 2.6 / net / can / bcm.c
index 97078d45a72d7cfafd547a0fe72e228b29f96bc6..1e4ac669120ccfdf9f702b277ffc537de8cb8e79 100644 (file)
 #include <socketcan/can/version.h> /* for RCSID. Removed by mkpatch script */
 RCSID("$Id$");
 
+/*
+ * 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 */
@@ -104,16 +111,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;
@@ -148,24 +155,28 @@ static inline struct bcm_sock *bcm_sk(const struct sock *sk)
 /*
  * procfs functions
  */
-static char *bcm_proc_getifname(int ifindex)
+static char *bcm_proc_getifname(char *result, int ifindex)
 {
        struct net_device *dev;
 
        if (!ifindex)
                return "any";
 
-       /* no usage counting */
+       read_lock(&dev_base_lock);
        dev = __dev_get_by_index(&init_net, ifindex);
        if (dev)
-               return dev->name;
+               strcpy(result, dev->name);
+       else
+               strcpy(result, "???");
+       read_unlock(&dev_base_lock);
 
-       return "???";
+       return result;
 }
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
 static int bcm_proc_show(struct seq_file *m, void *v)
 {
+       char ifname[IFNAMSIZ];
        struct sock *sk = (struct sock *)m->private;
        struct bcm_sock *bo = bcm_sk(sk);
        struct bcm_op *op;
@@ -174,7 +185,7 @@ static int bcm_proc_show(struct seq_file *m, void *v)
        seq_printf(m, " / sk %p", sk);
        seq_printf(m, " / bo %p", bo);
        seq_printf(m, " / dropped %lu", bo->dropped_usr_msgs);
-       seq_printf(m, " / bound %s", bcm_proc_getifname(bo->ifindex));
+       seq_printf(m, " / bound %s", bcm_proc_getifname(ifname, bo->ifindex));
        seq_printf(m, " <<<\n");
 
        list_for_each_entry(op, &bo->rx_ops, list) {
@@ -186,8 +197,8 @@ static int bcm_proc_show(struct seq_file *m, void *v)
                        continue;
 
                seq_printf(m, "rx_op: %03X %-5s ",
-                               op->can_id, bcm_proc_getifname(op->ifindex));
-               seq_printf(m, "[%d]%c ", op->nframes,
+                               op->can_id, bcm_proc_getifname(ifname, op->ifindex));
+               seq_printf(m, "[%u]%c ", op->nframes,
                                (op->flags & RX_CHECK_DLC)?'d':' ');
                if (op->kt_ival1.tv64)
                        seq_printf(m, "timeo=%lld ",
@@ -210,8 +221,9 @@ static int bcm_proc_show(struct seq_file *m, void *v)
 
        list_for_each_entry(op, &bo->tx_ops, list) {
 
-               seq_printf(m, "tx_op: %03X %s [%d] ",
-                               op->can_id, bcm_proc_getifname(op->ifindex),
+               seq_printf(m, "tx_op: %03X %s [%u] ",
+                               op->can_id,
+                               bcm_proc_getifname(ifname, op->ifindex),
                                op->nframes);
 
                if (op->kt_ival1.tv64)
@@ -244,6 +256,7 @@ static const struct file_operations bcm_proc_fops = {
 static int bcm_read_proc(char *page, char **start, off_t off,
                         int count, int *eof, void *data)
 {
+       char ifname[IFNAMSIZ];
        int len = 0;
        struct sock *sk = (struct sock *)data;
        struct bcm_sock *bo = bcm_sk(sk);
@@ -256,7 +269,7 @@ static int bcm_read_proc(char *page, char **start, off_t off,
        len += snprintf(page + len, PAGE_SIZE - len, " / dropped %lu",
                        bo->dropped_usr_msgs);
        len += snprintf(page + len, PAGE_SIZE - len, " / bound %s",
-                       bcm_proc_getifname(bo->ifindex));
+                       bcm_proc_getifname(ifname, bo->ifindex));
        len += snprintf(page + len, PAGE_SIZE - len, " <<<\n");
 
        list_for_each_entry(op, &bo->rx_ops, list) {
@@ -269,7 +282,7 @@ static int bcm_read_proc(char *page, char **start, off_t off,
 
                len += snprintf(page + len, PAGE_SIZE - len,
                                "rx_op: %03X %-5s ",
-                               op->can_id, bcm_proc_getifname(op->ifindex));
+                               op->can_id, bcm_proc_getifname(ifname, op->ifindex));
                len += snprintf(page + len, PAGE_SIZE - len, "[%d]%c ",
                                op->nframes,
                                (op->flags & RX_CHECK_DLC)?'d':' ');
@@ -305,7 +318,8 @@ static int bcm_read_proc(char *page, char **start, off_t off,
 
                len += snprintf(page + len, PAGE_SIZE - len,
                                "tx_op: %03X %s [%d] ",
-                               op->can_id, bcm_proc_getifname(op->ifindex),
+                               op->can_id,
+                               bcm_proc_getifname(ifname, op->ifindex),
                                op->nframes);
 
                if (op->kt_ival1.tv64)
@@ -386,7 +400,7 @@ static void bcm_send_to_user(struct bcm_op *op, struct bcm_msg_head *head,
        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());
@@ -584,7 +598,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)
 {
        /*
@@ -670,7 +684,8 @@ static enum hrtimer_restart bcm_rx_timeout_handler(struct hrtimer *hrtimer)
 /*
  * 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)
@@ -691,7 +706,7 @@ static int bcm_rx_thr_flush(struct bcm_op *op, int update)
        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++)
@@ -740,7 +755,7 @@ static void bcm_rx_handler(struct sk_buff *skb, void *data)
 {
        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);
@@ -940,14 +955,15 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
 {
        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 */
@@ -1111,6 +1127,10 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
                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))))