]> rtime.felk.cvut.cz Git - socketcan-devel.git/commitdiff
Added some sanity checks to prevent skbuffs from containing inconsistent
authorhartkopp <hartkopp@030b6a49-0b11-0410-94ab-b0dab22257f2>
Tue, 1 Jul 2008 08:47:47 +0000 (08:47 +0000)
committerhartkopp <hartkopp@030b6a49-0b11-0410-94ab-b0dab22257f2>
Tue, 1 Jul 2008 08:47:47 +0000 (08:47 +0000)
CAN frames.

git-svn-id: svn://svn.berlios.de//socketcan/trunk@800 030b6a49-0b11-0410-94ab-b0dab22257f2

kernel/2.6/net/can/af_can.c
kernel/2.6/net/can/bcm.c
kernel/2.6/net/can/raw.c

index a081f22b62fa6e9caa2db6fbeb4597c0f4369ef8..15f478cca36a82c047e38de6c50bed96166fd701 100644 (file)
@@ -268,12 +268,19 @@ static int can_create(struct socket *sock, int protocol)
  *  -ENOBUFS on full driver queue (see net_xmit_errno())
  *  -ENOMEM when local loopback failed at calling skb_clone()
  *  -EPERM when trying to send on a non-CAN interface
+ *  -EINVAL when the skb->data does not contain a valid CAN frame
  */
 int can_send(struct sk_buff *skb, int loop)
 {
        struct sk_buff *newskb = NULL;
+       struct can_frame *cf = (struct can_frame *) skb->data;
        int err;
 
+       if (skb->len != sizeof(struct can_frame) || cf->can_dlc > 8) {
+               kfree_skb(skb);
+               return -EINVAL;
+       }
+
        if (skb->dev->type != ARPHRD_CAN) {
                kfree_skb(skb);
                return -EPERM;
@@ -681,6 +688,7 @@ static int can_rcv(struct sk_buff *skb, struct net_device *dev,
 #endif
 {
        struct dev_rcv_lists *d;
+       struct can_frame *cf = (struct can_frame *) skb->data;
        int matches;
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
@@ -694,6 +702,8 @@ static int can_rcv(struct sk_buff *skb, struct net_device *dev,
                return 0;
        }
 
+       BUG_ON(skb->len != sizeof(struct can_frame) || cf->can_dlc > 8);
+
        /* update statistics */
        can_stats.rx_frames++;
        can_stats.rx_frames_delta++;
index 528c84ef833ff3c279679464d15d32edfe7a060b..1401b3de15acdca36a02143acb1bbefe0f98f942 100644 (file)
@@ -1025,6 +1025,10 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
                for (i = 0; i < msg_head->nframes; i++) {
                        err = memcpy_fromiovec((u8 *)&op->frames[i],
                                               msg->msg_iov, CFSIZ);
+
+                       if (op->frames[i].can_dlc > 8)
+                               err = -EINVAL;
+
                        if (err < 0)
                                return err;
 
@@ -1057,6 +1061,10 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
                for (i = 0; i < msg_head->nframes; i++) {
                        err = memcpy_fromiovec((u8 *)&op->frames[i],
                                               msg->msg_iov, CFSIZ);
+
+                       if (op->frames[i].can_dlc > 8)
+                               err = -EINVAL;
+
                        if (err < 0) {
                                if (op->frames != &op->sframe)
                                        kfree(op->frames);
@@ -1442,9 +1450,12 @@ static int bcm_tx_send(struct msghdr *msg, int ifindex, struct sock *sk)
 
        skb->dev = dev;
        skb->sk  = sk;
-       can_send(skb, 1); /* send with loopback */
+       err = can_send(skb, 1); /* send with loopback */
        dev_put(dev);
 
+       if (err)
+               return err;
+
        return CFSIZ + MHSIZ;
 }
 
@@ -1463,6 +1474,10 @@ static int bcm_sendmsg(struct kiocb *iocb, struct socket *sock,
        if (!bo->bound)
                return -ENOTCONN;
 
+       /* check for valid message length from userspace */
+       if (size < MHSIZ || (size - MHSIZ) % CFSIZ)
+               return -EINVAL;
+
        /* check for alternative ifindex for this bcm_op */
 
        if (!ifindex && msg->msg_name) {
@@ -1537,8 +1552,8 @@ static int bcm_sendmsg(struct kiocb *iocb, struct socket *sock,
                break;
 
        case TX_SEND:
-               /* we need at least one can_frame */
-               if (msg_head.nframes < 1)
+               /* we need at exactly one can_frame behind the msg head */
+               if ((msg_head.nframes != 1) || (size != CFSIZ + MHSIZ))
                        ret = -EINVAL;
                else
                        ret = bcm_tx_send(msg, ifindex, sk);
index a5e9ee03033376e12f1ab27469a6541e28a58768..76e7168088e94b0033d19702e11651955ba01c7e 100644 (file)
@@ -665,6 +665,9 @@ static int raw_sendmsg(struct kiocb *iocb, struct socket *sock,
        if (!dev)
                return -ENXIO;
 
+       if (size != sizeof(struct can_frame))
+               return -EINVAL;
+
        skb = sock_alloc_send_skb(sk, size, msg->msg_flags & MSG_DONTWAIT,
                                  &err);
        if (!skb) {