diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-07 12:24:28 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-07 12:24:28 -0400 |
commit | b2798bf0ec2cb5a17bfc1430c5ba6d971c436a03 (patch) | |
tree | ef2b01160811d8d6312518a177968d58d5fe9e44 /net | |
parent | 3bc5ab9b7f2760d2892fd0a0589e1077e869d4f5 (diff) | |
parent | 7f2d38eb7a42bea1c1df51bbdaa2ca0f0bdda07f (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6:
can: add sanity checks
fs_enet: restore promiscuous and multicast settings in restart()
ibm_newemac: Fixes entry of short packets
ibm_newemac: Fixes kernel crashes when speed of cable connected changes
pasemi_mac: Access iph->tot_len with correct endianness
ehea: Access iph->tot_len with correct endianness
ehea: fix race condition
ehea: add MODULE_DEVICE_TABLE
ehea: fix might sleep problem
forcedeth: fix lockdep warning on ethtool -s
Add missing skb->dev assignment in Frame Relay RX code
bridge: fix use-after-free in br_cleanup_bridges()
tcp: fix a size_t < 0 comparison in tcp_read_sock
tcp: net/ipv4/tcp.c needs linux/scatterlist.h
libertas: support USB persistence on suspend/resume (resend)
iwlwifi: drop skb silently for Tx request in monitor mode
iwlwifi: fix incorrect 5GHz rates reported in monitor mode
Diffstat (limited to 'net')
-rw-r--r-- | net/bridge/br_if.c | 10 | ||||
-rw-r--r-- | net/can/af_can.c | 10 | ||||
-rw-r--r-- | net/can/bcm.c | 23 | ||||
-rw-r--r-- | net/can/raw.c | 3 | ||||
-rw-r--r-- | net/ipv4/tcp.c | 4 |
5 files changed, 42 insertions, 8 deletions
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index c2397f503b0..f38cc5317b8 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c | |||
@@ -442,12 +442,16 @@ int br_del_if(struct net_bridge *br, struct net_device *dev) | |||
442 | 442 | ||
443 | void __exit br_cleanup_bridges(void) | 443 | void __exit br_cleanup_bridges(void) |
444 | { | 444 | { |
445 | struct net_device *dev, *nxt; | 445 | struct net_device *dev; |
446 | 446 | ||
447 | rtnl_lock(); | 447 | rtnl_lock(); |
448 | for_each_netdev_safe(&init_net, dev, nxt) | 448 | restart: |
449 | if (dev->priv_flags & IFF_EBRIDGE) | 449 | for_each_netdev(&init_net, dev) { |
450 | if (dev->priv_flags & IFF_EBRIDGE) { | ||
450 | del_br(dev->priv); | 451 | del_br(dev->priv); |
452 | goto restart; | ||
453 | } | ||
454 | } | ||
451 | rtnl_unlock(); | 455 | rtnl_unlock(); |
452 | 456 | ||
453 | } | 457 | } |
diff --git a/net/can/af_can.c b/net/can/af_can.c index 7e8ca283645..484bbf6dd03 100644 --- a/net/can/af_can.c +++ b/net/can/af_can.c | |||
@@ -205,12 +205,19 @@ static int can_create(struct net *net, struct socket *sock, int protocol) | |||
205 | * -ENOBUFS on full driver queue (see net_xmit_errno()) | 205 | * -ENOBUFS on full driver queue (see net_xmit_errno()) |
206 | * -ENOMEM when local loopback failed at calling skb_clone() | 206 | * -ENOMEM when local loopback failed at calling skb_clone() |
207 | * -EPERM when trying to send on a non-CAN interface | 207 | * -EPERM when trying to send on a non-CAN interface |
208 | * -EINVAL when the skb->data does not contain a valid CAN frame | ||
208 | */ | 209 | */ |
209 | int can_send(struct sk_buff *skb, int loop) | 210 | int can_send(struct sk_buff *skb, int loop) |
210 | { | 211 | { |
211 | struct sk_buff *newskb = NULL; | 212 | struct sk_buff *newskb = NULL; |
213 | struct can_frame *cf = (struct can_frame *)skb->data; | ||
212 | int err; | 214 | int err; |
213 | 215 | ||
216 | if (skb->len != sizeof(struct can_frame) || cf->can_dlc > 8) { | ||
217 | kfree_skb(skb); | ||
218 | return -EINVAL; | ||
219 | } | ||
220 | |||
214 | if (skb->dev->type != ARPHRD_CAN) { | 221 | if (skb->dev->type != ARPHRD_CAN) { |
215 | kfree_skb(skb); | 222 | kfree_skb(skb); |
216 | return -EPERM; | 223 | return -EPERM; |
@@ -605,6 +612,7 @@ static int can_rcv(struct sk_buff *skb, struct net_device *dev, | |||
605 | struct packet_type *pt, struct net_device *orig_dev) | 612 | struct packet_type *pt, struct net_device *orig_dev) |
606 | { | 613 | { |
607 | struct dev_rcv_lists *d; | 614 | struct dev_rcv_lists *d; |
615 | struct can_frame *cf = (struct can_frame *)skb->data; | ||
608 | int matches; | 616 | int matches; |
609 | 617 | ||
610 | if (dev->type != ARPHRD_CAN || dev_net(dev) != &init_net) { | 618 | if (dev->type != ARPHRD_CAN || dev_net(dev) != &init_net) { |
@@ -612,6 +620,8 @@ static int can_rcv(struct sk_buff *skb, struct net_device *dev, | |||
612 | return 0; | 620 | return 0; |
613 | } | 621 | } |
614 | 622 | ||
623 | BUG_ON(skb->len != sizeof(struct can_frame) || cf->can_dlc > 8); | ||
624 | |||
615 | /* update statistics */ | 625 | /* update statistics */ |
616 | can_stats.rx_frames++; | 626 | can_stats.rx_frames++; |
617 | can_stats.rx_frames_delta++; | 627 | can_stats.rx_frames_delta++; |
diff --git a/net/can/bcm.c b/net/can/bcm.c index d9a3a9d13be..72c2ce904f8 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); |
diff --git a/net/can/raw.c b/net/can/raw.c index 69877b8e7e9..3e46ee36a1a 100644 --- a/net/can/raw.c +++ b/net/can/raw.c | |||
@@ -632,6 +632,9 @@ static int raw_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
632 | } else | 632 | } else |
633 | ifindex = ro->ifindex; | 633 | ifindex = ro->ifindex; |
634 | 634 | ||
635 | if (size != sizeof(struct can_frame)) | ||
636 | return -EINVAL; | ||
637 | |||
635 | dev = dev_get_by_index(&init_net, ifindex); | 638 | dev = dev_get_by_index(&init_net, ifindex); |
636 | if (!dev) | 639 | if (!dev) |
637 | return -ENXIO; | 640 | return -ENXIO; |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 850825dc86e..1d723de1868 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -255,6 +255,7 @@ | |||
255 | #include <linux/init.h> | 255 | #include <linux/init.h> |
256 | #include <linux/fs.h> | 256 | #include <linux/fs.h> |
257 | #include <linux/skbuff.h> | 257 | #include <linux/skbuff.h> |
258 | #include <linux/scatterlist.h> | ||
258 | #include <linux/splice.h> | 259 | #include <linux/splice.h> |
259 | #include <linux/net.h> | 260 | #include <linux/net.h> |
260 | #include <linux/socket.h> | 261 | #include <linux/socket.h> |
@@ -1208,7 +1209,8 @@ int tcp_read_sock(struct sock *sk, read_descriptor_t *desc, | |||
1208 | return -ENOTCONN; | 1209 | return -ENOTCONN; |
1209 | while ((skb = tcp_recv_skb(sk, seq, &offset)) != NULL) { | 1210 | while ((skb = tcp_recv_skb(sk, seq, &offset)) != NULL) { |
1210 | if (offset < skb->len) { | 1211 | if (offset < skb->len) { |
1211 | size_t used, len; | 1212 | int used; |
1213 | size_t len; | ||
1212 | 1214 | ||
1213 | len = skb->len - offset; | 1215 | len = skb->len - offset; |
1214 | /* Stop reading if we hit a patch of urgent data */ | 1216 | /* Stop reading if we hit a patch of urgent data */ |