diff options
author | David S. Miller <davem@davemloft.net> | 2006-10-29 19:14:55 -0500 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-10-30 18:24:38 -0500 |
commit | c20e3945c761502b9d5d73ef0ff5f1a84b3a717e (patch) | |
tree | 91ae6f4305174b929936d5ace5535b1e722976b2 /drivers/ieee1394 | |
parent | 234af4840135342ab295b4e1219fd35c27fdd439 (diff) |
[ETH1394]: Fix unaligned accesses.
Several u64 objects are derefernced in situations where the
pointer is not guarenteed to be aligned correctly. Use
get_unaligned() as needed.
Thanks to Will Simoneau for lots of testing and debugging
help.
Signed-off-by: David S. Miller <davem@davemloft.net>
Acked-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers/ieee1394')
-rw-r--r-- | drivers/ieee1394/eth1394.c | 20 |
1 files changed, 12 insertions, 8 deletions
diff --git a/drivers/ieee1394/eth1394.c b/drivers/ieee1394/eth1394.c index 8a7b8fab6238..31e5cc49d61a 100644 --- a/drivers/ieee1394/eth1394.c +++ b/drivers/ieee1394/eth1394.c | |||
@@ -64,6 +64,7 @@ | |||
64 | #include <linux/ethtool.h> | 64 | #include <linux/ethtool.h> |
65 | #include <asm/uaccess.h> | 65 | #include <asm/uaccess.h> |
66 | #include <asm/delay.h> | 66 | #include <asm/delay.h> |
67 | #include <asm/unaligned.h> | ||
67 | #include <net/arp.h> | 68 | #include <net/arp.h> |
68 | 69 | ||
69 | #include "config_roms.h" | 70 | #include "config_roms.h" |
@@ -491,7 +492,7 @@ static void ether1394_reset_priv (struct net_device *dev, int set_mtu) | |||
491 | int i; | 492 | int i; |
492 | struct eth1394_priv *priv = netdev_priv(dev); | 493 | struct eth1394_priv *priv = netdev_priv(dev); |
493 | struct hpsb_host *host = priv->host; | 494 | struct hpsb_host *host = priv->host; |
494 | u64 guid = *((u64*)&(host->csr.rom->bus_info_data[3])); | 495 | u64 guid = get_unaligned((u64*)&(host->csr.rom->bus_info_data[3])); |
495 | u16 maxpayload = 1 << (host->csr.max_rec + 1); | 496 | u16 maxpayload = 1 << (host->csr.max_rec + 1); |
496 | int max_speed = IEEE1394_SPEED_MAX; | 497 | int max_speed = IEEE1394_SPEED_MAX; |
497 | 498 | ||
@@ -514,8 +515,8 @@ static void ether1394_reset_priv (struct net_device *dev, int set_mtu) | |||
514 | ETHER1394_GASP_OVERHEAD))); | 515 | ETHER1394_GASP_OVERHEAD))); |
515 | 516 | ||
516 | /* Set our hardware address while we're at it */ | 517 | /* Set our hardware address while we're at it */ |
517 | *(u64*)dev->dev_addr = guid; | 518 | memcpy(dev->dev_addr, &guid, sizeof(u64)); |
518 | *(u64*)dev->broadcast = ~0x0ULL; | 519 | memset(dev->broadcast, 0xff, sizeof(u64)); |
519 | } | 520 | } |
520 | 521 | ||
521 | spin_unlock_irqrestore (&priv->lock, flags); | 522 | spin_unlock_irqrestore (&priv->lock, flags); |
@@ -894,6 +895,7 @@ static inline u16 ether1394_parse_encap(struct sk_buff *skb, | |||
894 | u16 maxpayload; | 895 | u16 maxpayload; |
895 | struct eth1394_node_ref *node; | 896 | struct eth1394_node_ref *node; |
896 | struct eth1394_node_info *node_info; | 897 | struct eth1394_node_info *node_info; |
898 | __be64 guid; | ||
897 | 899 | ||
898 | /* Sanity check. MacOSX seems to be sending us 131 in this | 900 | /* Sanity check. MacOSX seems to be sending us 131 in this |
899 | * field (atleast on my Panther G5). Not sure why. */ | 901 | * field (atleast on my Panther G5). Not sure why. */ |
@@ -902,8 +904,9 @@ static inline u16 ether1394_parse_encap(struct sk_buff *skb, | |||
902 | 904 | ||
903 | maxpayload = min(eth1394_speedto_maxpayload[sspd], (u16)(1 << (max_rec + 1))); | 905 | maxpayload = min(eth1394_speedto_maxpayload[sspd], (u16)(1 << (max_rec + 1))); |
904 | 906 | ||
907 | guid = get_unaligned(&arp1394->s_uniq_id); | ||
905 | node = eth1394_find_node_guid(&priv->ip_node_list, | 908 | node = eth1394_find_node_guid(&priv->ip_node_list, |
906 | be64_to_cpu(arp1394->s_uniq_id)); | 909 | be64_to_cpu(guid)); |
907 | if (!node) { | 910 | if (!node) { |
908 | return 0; | 911 | return 0; |
909 | } | 912 | } |
@@ -931,10 +934,9 @@ static inline u16 ether1394_parse_encap(struct sk_buff *skb, | |||
931 | arp_ptr += arp->ar_pln; /* skip over sender IP addr */ | 934 | arp_ptr += arp->ar_pln; /* skip over sender IP addr */ |
932 | 935 | ||
933 | if (arp->ar_op == htons(ARPOP_REQUEST)) | 936 | if (arp->ar_op == htons(ARPOP_REQUEST)) |
934 | /* just set ARP req target unique ID to 0 */ | 937 | memset(arp_ptr, 0, sizeof(u64)); |
935 | *((u64*)arp_ptr) = 0; | ||
936 | else | 938 | else |
937 | *((u64*)arp_ptr) = *((u64*)dev->dev_addr); | 939 | memcpy(arp_ptr, dev->dev_addr, sizeof(u64)); |
938 | } | 940 | } |
939 | 941 | ||
940 | /* Now add the ethernet header. */ | 942 | /* Now add the ethernet header. */ |
@@ -1675,8 +1677,10 @@ static int ether1394_tx (struct sk_buff *skb, struct net_device *dev) | |||
1675 | if (max_payload < dg_size + hdr_type_len[ETH1394_HDR_LF_UF]) | 1677 | if (max_payload < dg_size + hdr_type_len[ETH1394_HDR_LF_UF]) |
1676 | priv->bc_dgl++; | 1678 | priv->bc_dgl++; |
1677 | } else { | 1679 | } else { |
1680 | __be64 guid = get_unaligned((u64 *)eth->h_dest); | ||
1681 | |||
1678 | node = eth1394_find_node_guid(&priv->ip_node_list, | 1682 | node = eth1394_find_node_guid(&priv->ip_node_list, |
1679 | be64_to_cpu(*(u64*)eth->h_dest)); | 1683 | be64_to_cpu(guid)); |
1680 | if (!node) { | 1684 | if (!node) { |
1681 | ret = -EAGAIN; | 1685 | ret = -EAGAIN; |
1682 | goto fail; | 1686 | goto fail; |