diff options
Diffstat (limited to 'net/can/bcm.c')
-rw-r--r-- | net/can/bcm.c | 23 |
1 files changed, 19 insertions, 4 deletions
diff --git a/net/can/bcm.c b/net/can/bcm.c index d9a3a9d13bed..72c2ce904f83 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c | |||
@@ -298,7 +298,7 @@ static void bcm_send_to_user(struct bcm_op *op, struct bcm_msg_head *head, | |||
298 | 298 | ||
299 | if (head->nframes) { | 299 | if (head->nframes) { |
300 | /* can_frames starting here */ | 300 | /* can_frames starting here */ |
301 | firstframe = (struct can_frame *) skb_tail_pointer(skb); | 301 | firstframe = (struct can_frame *)skb_tail_pointer(skb); |
302 | 302 | ||
303 | memcpy(skb_put(skb, datalen), frames, datalen); | 303 | memcpy(skb_put(skb, datalen), frames, datalen); |
304 | 304 | ||
@@ -826,6 +826,10 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg, | |||
826 | for (i = 0; i < msg_head->nframes; i++) { | 826 | for (i = 0; i < msg_head->nframes; i++) { |
827 | err = memcpy_fromiovec((u8 *)&op->frames[i], | 827 | err = memcpy_fromiovec((u8 *)&op->frames[i], |
828 | msg->msg_iov, CFSIZ); | 828 | msg->msg_iov, CFSIZ); |
829 | |||
830 | if (op->frames[i].can_dlc > 8) | ||
831 | err = -EINVAL; | ||
832 | |||
829 | if (err < 0) | 833 | if (err < 0) |
830 | return err; | 834 | return err; |
831 | 835 | ||
@@ -858,6 +862,10 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg, | |||
858 | for (i = 0; i < msg_head->nframes; i++) { | 862 | for (i = 0; i < msg_head->nframes; i++) { |
859 | err = memcpy_fromiovec((u8 *)&op->frames[i], | 863 | err = memcpy_fromiovec((u8 *)&op->frames[i], |
860 | msg->msg_iov, CFSIZ); | 864 | msg->msg_iov, CFSIZ); |
865 | |||
866 | if (op->frames[i].can_dlc > 8) | ||
867 | err = -EINVAL; | ||
868 | |||
861 | if (err < 0) { | 869 | if (err < 0) { |
862 | if (op->frames != &op->sframe) | 870 | if (op->frames != &op->sframe) |
863 | kfree(op->frames); | 871 | kfree(op->frames); |
@@ -1164,9 +1172,12 @@ static int bcm_tx_send(struct msghdr *msg, int ifindex, struct sock *sk) | |||
1164 | 1172 | ||
1165 | skb->dev = dev; | 1173 | skb->dev = dev; |
1166 | skb->sk = sk; | 1174 | skb->sk = sk; |
1167 | can_send(skb, 1); /* send with loopback */ | 1175 | err = can_send(skb, 1); /* send with loopback */ |
1168 | dev_put(dev); | 1176 | dev_put(dev); |
1169 | 1177 | ||
1178 | if (err) | ||
1179 | return err; | ||
1180 | |||
1170 | return CFSIZ + MHSIZ; | 1181 | return CFSIZ + MHSIZ; |
1171 | } | 1182 | } |
1172 | 1183 | ||
@@ -1185,6 +1196,10 @@ static int bcm_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1185 | if (!bo->bound) | 1196 | if (!bo->bound) |
1186 | return -ENOTCONN; | 1197 | return -ENOTCONN; |
1187 | 1198 | ||
1199 | /* check for valid message length from userspace */ | ||
1200 | if (size < MHSIZ || (size - MHSIZ) % CFSIZ) | ||
1201 | return -EINVAL; | ||
1202 | |||
1188 | /* check for alternative ifindex for this bcm_op */ | 1203 | /* check for alternative ifindex for this bcm_op */ |
1189 | 1204 | ||
1190 | if (!ifindex && msg->msg_name) { | 1205 | if (!ifindex && msg->msg_name) { |
@@ -1259,8 +1274,8 @@ static int bcm_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1259 | break; | 1274 | break; |
1260 | 1275 | ||
1261 | case TX_SEND: | 1276 | case TX_SEND: |
1262 | /* we need at least one can_frame */ | 1277 | /* we need exactly one can_frame behind the msg head */ |
1263 | if (msg_head.nframes < 1) | 1278 | if ((msg_head.nframes != 1) || (size != CFSIZ + MHSIZ)) |
1264 | ret = -EINVAL; | 1279 | ret = -EINVAL; |
1265 | else | 1280 | else |
1266 | ret = bcm_tx_send(msg, ifindex, sk); | 1281 | ret = bcm_tx_send(msg, ifindex, sk); |