diff options
author | Gerrit Renker <gerrit@erg.abdn.ac.uk> | 2007-10-24 08:46:58 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@ghostprotocols.net> | 2007-10-24 08:46:58 -0400 |
commit | 76fd1e87d9456c8185b8df76ac5e533e0c8b39bb (patch) | |
tree | 2706975f5e479de467afd959d68866dd12bbb363 /net | |
parent | d8ef2c29a0dcfccb2d90cac990143d1a4668708a (diff) |
[DCCP]: Unaligned pointer access
This fixes `unaligned (read) access' errors of the type
Kernel unaligned access at TPC[100f970c] dccp_parse_options+0x4f4/0x7e0 [dccp]
Kernel unaligned access at TPC[1011f2e4] ccid3_hc_tx_parse_options+0x1ac/0x380 [dccp_ccid3]
Kernel unaligned access at TPC[100f9898] dccp_parse_options+0x680/0x880 [dccp]
by using the get_unaligned macro for parsing options.
Commiter note: Preserved the sparse __be{16,32} annotations.
Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
Signed-off-by: Ian McDonald <ian.mcdonald@jandi.co.nz>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/dccp/ccids/ccid3.c | 11 | ||||
-rw-r--r-- | net/dccp/options.c | 33 |
2 files changed, 29 insertions, 15 deletions
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 25772c326172..05f263e9160d 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c | |||
@@ -40,6 +40,8 @@ | |||
40 | #include "lib/tfrc.h" | 40 | #include "lib/tfrc.h" |
41 | #include "ccid3.h" | 41 | #include "ccid3.h" |
42 | 42 | ||
43 | #include <asm/unaligned.h> | ||
44 | |||
43 | #ifdef CONFIG_IP_DCCP_CCID3_DEBUG | 45 | #ifdef CONFIG_IP_DCCP_CCID3_DEBUG |
44 | static int ccid3_debug; | 46 | static int ccid3_debug; |
45 | #define ccid3_pr_debug(format, a...) DCCP_PR_DEBUG(ccid3_debug, format, ##a) | 47 | #define ccid3_pr_debug(format, a...) DCCP_PR_DEBUG(ccid3_debug, format, ##a) |
@@ -544,6 +546,7 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option, | |||
544 | const struct dccp_sock *dp = dccp_sk(sk); | 546 | const struct dccp_sock *dp = dccp_sk(sk); |
545 | struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); | 547 | struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); |
546 | struct ccid3_options_received *opt_recv; | 548 | struct ccid3_options_received *opt_recv; |
549 | __be32 opt_val; | ||
547 | 550 | ||
548 | opt_recv = &hctx->ccid3hctx_options_received; | 551 | opt_recv = &hctx->ccid3hctx_options_received; |
549 | 552 | ||
@@ -563,8 +566,8 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option, | |||
563 | dccp_role(sk), sk, len); | 566 | dccp_role(sk), sk, len); |
564 | rc = -EINVAL; | 567 | rc = -EINVAL; |
565 | } else { | 568 | } else { |
566 | opt_recv->ccid3or_loss_event_rate = | 569 | opt_val = get_unaligned((__be32 *)value); |
567 | ntohl(*(__be32 *)value); | 570 | opt_recv->ccid3or_loss_event_rate = ntohl(opt_val); |
568 | ccid3_pr_debug("%s(%p), LOSS_EVENT_RATE=%u\n", | 571 | ccid3_pr_debug("%s(%p), LOSS_EVENT_RATE=%u\n", |
569 | dccp_role(sk), sk, | 572 | dccp_role(sk), sk, |
570 | opt_recv->ccid3or_loss_event_rate); | 573 | opt_recv->ccid3or_loss_event_rate); |
@@ -585,8 +588,8 @@ static int ccid3_hc_tx_parse_options(struct sock *sk, unsigned char option, | |||
585 | dccp_role(sk), sk, len); | 588 | dccp_role(sk), sk, len); |
586 | rc = -EINVAL; | 589 | rc = -EINVAL; |
587 | } else { | 590 | } else { |
588 | opt_recv->ccid3or_receive_rate = | 591 | opt_val = get_unaligned((__be32 *)value); |
589 | ntohl(*(__be32 *)value); | 592 | opt_recv->ccid3or_receive_rate = ntohl(opt_val); |
590 | ccid3_pr_debug("%s(%p), RECEIVE_RATE=%u\n", | 593 | ccid3_pr_debug("%s(%p), RECEIVE_RATE=%u\n", |
591 | dccp_role(sk), sk, | 594 | dccp_role(sk), sk, |
592 | opt_recv->ccid3or_receive_rate); | 595 | opt_recv->ccid3or_receive_rate); |
diff --git a/net/dccp/options.c b/net/dccp/options.c index d361b5533309..d286cffe2c49 100644 --- a/net/dccp/options.c +++ b/net/dccp/options.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/dccp.h> | 14 | #include <linux/dccp.h> |
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/types.h> | 16 | #include <linux/types.h> |
17 | #include <asm/unaligned.h> | ||
17 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
18 | #include <linux/skbuff.h> | 19 | #include <linux/skbuff.h> |
19 | 20 | ||
@@ -59,6 +60,7 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) | |||
59 | unsigned char opt, len; | 60 | unsigned char opt, len; |
60 | unsigned char *value; | 61 | unsigned char *value; |
61 | u32 elapsed_time; | 62 | u32 elapsed_time; |
63 | __be32 opt_val; | ||
62 | int rc; | 64 | int rc; |
63 | int mandatory = 0; | 65 | int mandatory = 0; |
64 | 66 | ||
@@ -145,7 +147,8 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) | |||
145 | if (len != 4) | 147 | if (len != 4) |
146 | goto out_invalid_option; | 148 | goto out_invalid_option; |
147 | 149 | ||
148 | opt_recv->dccpor_timestamp = ntohl(*(__be32 *)value); | 150 | opt_val = get_unaligned((__be32 *)value); |
151 | opt_recv->dccpor_timestamp = ntohl(opt_val); | ||
149 | 152 | ||
150 | dp->dccps_timestamp_echo = opt_recv->dccpor_timestamp; | 153 | dp->dccps_timestamp_echo = opt_recv->dccpor_timestamp; |
151 | dp->dccps_timestamp_time = ktime_get_real(); | 154 | dp->dccps_timestamp_time = ktime_get_real(); |
@@ -159,7 +162,8 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) | |||
159 | if (len != 4 && len != 6 && len != 8) | 162 | if (len != 4 && len != 6 && len != 8) |
160 | goto out_invalid_option; | 163 | goto out_invalid_option; |
161 | 164 | ||
162 | opt_recv->dccpor_timestamp_echo = ntohl(*(__be32 *)value); | 165 | opt_val = get_unaligned((__be32 *)value); |
166 | opt_recv->dccpor_timestamp_echo = ntohl(opt_val); | ||
163 | 167 | ||
164 | dccp_pr_debug("%s rx opt: TIMESTAMP_ECHO=%u, len=%d, " | 168 | dccp_pr_debug("%s rx opt: TIMESTAMP_ECHO=%u, len=%d, " |
165 | "ackno=%llu", dccp_role(sk), | 169 | "ackno=%llu", dccp_role(sk), |
@@ -168,16 +172,20 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) | |||
168 | (unsigned long long) | 172 | (unsigned long long) |
169 | DCCP_SKB_CB(skb)->dccpd_ack_seq); | 173 | DCCP_SKB_CB(skb)->dccpd_ack_seq); |
170 | 174 | ||
175 | value += 4; | ||
171 | 176 | ||
172 | if (len == 4) { | 177 | if (len == 4) { /* no elapsed time included */ |
173 | dccp_pr_debug_cat("\n"); | 178 | dccp_pr_debug_cat("\n"); |
174 | break; | 179 | break; |
175 | } | 180 | } |
176 | 181 | ||
177 | if (len == 6) | 182 | if (len == 6) { /* 2-byte elapsed time */ |
178 | elapsed_time = ntohs(*(__be16 *)(value + 4)); | 183 | __be16 opt_val2 = get_unaligned((__be16 *)value); |
179 | else | 184 | elapsed_time = ntohs(opt_val2); |
180 | elapsed_time = ntohl(*(__be32 *)(value + 4)); | 185 | } else { /* 4-byte elapsed time */ |
186 | opt_val = get_unaligned((__be32 *)value); | ||
187 | elapsed_time = ntohl(opt_val); | ||
188 | } | ||
181 | 189 | ||
182 | dccp_pr_debug_cat(", ELAPSED_TIME=%u\n", elapsed_time); | 190 | dccp_pr_debug_cat(", ELAPSED_TIME=%u\n", elapsed_time); |
183 | 191 | ||
@@ -192,10 +200,13 @@ int dccp_parse_options(struct sock *sk, struct sk_buff *skb) | |||
192 | if (pkt_type == DCCP_PKT_DATA) | 200 | if (pkt_type == DCCP_PKT_DATA) |
193 | continue; | 201 | continue; |
194 | 202 | ||
195 | if (len == 2) | 203 | if (len == 2) { |
196 | elapsed_time = ntohs(*(__be16 *)value); | 204 | __be16 opt_val2 = get_unaligned((__be16 *)value); |
197 | else | 205 | elapsed_time = ntohs(opt_val2); |
198 | elapsed_time = ntohl(*(__be32 *)value); | 206 | } else { |
207 | opt_val = get_unaligned((__be32 *)value); | ||
208 | elapsed_time = ntohl(opt_val); | ||
209 | } | ||
199 | 210 | ||
200 | if (elapsed_time > opt_recv->dccpor_elapsed_time) | 211 | if (elapsed_time > opt_recv->dccpor_elapsed_time) |
201 | opt_recv->dccpor_elapsed_time = elapsed_time; | 212 | opt_recv->dccpor_elapsed_time = elapsed_time; |