diff options
Diffstat (limited to 'net/x25/x25_in.c')
-rw-r--r-- | net/x25/x25_in.c | 43 |
1 files changed, 38 insertions, 5 deletions
diff --git a/net/x25/x25_in.c b/net/x25/x25_in.c index 0b073b51b183..a49cd4ec551a 100644 --- a/net/x25/x25_in.c +++ b/net/x25/x25_in.c | |||
@@ -107,6 +107,8 @@ static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametyp | |||
107 | /* | 107 | /* |
108 | * Parse the data in the frame. | 108 | * Parse the data in the frame. |
109 | */ | 109 | */ |
110 | if (!pskb_may_pull(skb, X25_STD_MIN_LEN)) | ||
111 | goto out_clear; | ||
110 | skb_pull(skb, X25_STD_MIN_LEN); | 112 | skb_pull(skb, X25_STD_MIN_LEN); |
111 | 113 | ||
112 | len = x25_parse_address_block(skb, &source_addr, | 114 | len = x25_parse_address_block(skb, &source_addr, |
@@ -127,9 +129,11 @@ static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametyp | |||
127 | * Copy any Call User Data. | 129 | * Copy any Call User Data. |
128 | */ | 130 | */ |
129 | if (skb->len > 0) { | 131 | if (skb->len > 0) { |
130 | skb_copy_from_linear_data(skb, | 132 | if (skb->len > X25_MAX_CUD_LEN) |
131 | x25->calluserdata.cuddata, | 133 | goto out_clear; |
132 | skb->len); | 134 | |
135 | skb_copy_bits(skb, 0, x25->calluserdata.cuddata, | ||
136 | skb->len); | ||
133 | x25->calluserdata.cudlength = skb->len; | 137 | x25->calluserdata.cudlength = skb->len; |
134 | } | 138 | } |
135 | if (!sock_flag(sk, SOCK_DEAD)) | 139 | if (!sock_flag(sk, SOCK_DEAD)) |
@@ -137,6 +141,9 @@ static int x25_state1_machine(struct sock *sk, struct sk_buff *skb, int frametyp | |||
137 | break; | 141 | break; |
138 | } | 142 | } |
139 | case X25_CLEAR_REQUEST: | 143 | case X25_CLEAR_REQUEST: |
144 | if (!pskb_may_pull(skb, X25_STD_MIN_LEN + 2)) | ||
145 | goto out_clear; | ||
146 | |||
140 | x25_write_internal(sk, X25_CLEAR_CONFIRMATION); | 147 | x25_write_internal(sk, X25_CLEAR_CONFIRMATION); |
141 | x25_disconnect(sk, ECONNREFUSED, skb->data[3], skb->data[4]); | 148 | x25_disconnect(sk, ECONNREFUSED, skb->data[3], skb->data[4]); |
142 | break; | 149 | break; |
@@ -164,6 +171,9 @@ static int x25_state2_machine(struct sock *sk, struct sk_buff *skb, int frametyp | |||
164 | switch (frametype) { | 171 | switch (frametype) { |
165 | 172 | ||
166 | case X25_CLEAR_REQUEST: | 173 | case X25_CLEAR_REQUEST: |
174 | if (!pskb_may_pull(skb, X25_STD_MIN_LEN + 2)) | ||
175 | goto out_clear; | ||
176 | |||
167 | x25_write_internal(sk, X25_CLEAR_CONFIRMATION); | 177 | x25_write_internal(sk, X25_CLEAR_CONFIRMATION); |
168 | x25_disconnect(sk, 0, skb->data[3], skb->data[4]); | 178 | x25_disconnect(sk, 0, skb->data[3], skb->data[4]); |
169 | break; | 179 | break; |
@@ -177,6 +187,11 @@ static int x25_state2_machine(struct sock *sk, struct sk_buff *skb, int frametyp | |||
177 | } | 187 | } |
178 | 188 | ||
179 | return 0; | 189 | return 0; |
190 | |||
191 | out_clear: | ||
192 | x25_write_internal(sk, X25_CLEAR_REQUEST); | ||
193 | x25_start_t23timer(sk); | ||
194 | return 0; | ||
180 | } | 195 | } |
181 | 196 | ||
182 | /* | 197 | /* |
@@ -206,6 +221,9 @@ static int x25_state3_machine(struct sock *sk, struct sk_buff *skb, int frametyp | |||
206 | break; | 221 | break; |
207 | 222 | ||
208 | case X25_CLEAR_REQUEST: | 223 | case X25_CLEAR_REQUEST: |
224 | if (!pskb_may_pull(skb, X25_STD_MIN_LEN + 2)) | ||
225 | goto out_clear; | ||
226 | |||
209 | x25_write_internal(sk, X25_CLEAR_CONFIRMATION); | 227 | x25_write_internal(sk, X25_CLEAR_CONFIRMATION); |
210 | x25_disconnect(sk, 0, skb->data[3], skb->data[4]); | 228 | x25_disconnect(sk, 0, skb->data[3], skb->data[4]); |
211 | break; | 229 | break; |
@@ -304,6 +322,12 @@ static int x25_state3_machine(struct sock *sk, struct sk_buff *skb, int frametyp | |||
304 | } | 322 | } |
305 | 323 | ||
306 | return queued; | 324 | return queued; |
325 | |||
326 | out_clear: | ||
327 | x25_write_internal(sk, X25_CLEAR_REQUEST); | ||
328 | x25->state = X25_STATE_2; | ||
329 | x25_start_t23timer(sk); | ||
330 | return 0; | ||
307 | } | 331 | } |
308 | 332 | ||
309 | /* | 333 | /* |
@@ -313,13 +337,13 @@ static int x25_state3_machine(struct sock *sk, struct sk_buff *skb, int frametyp | |||
313 | */ | 337 | */ |
314 | static int x25_state4_machine(struct sock *sk, struct sk_buff *skb, int frametype) | 338 | static int x25_state4_machine(struct sock *sk, struct sk_buff *skb, int frametype) |
315 | { | 339 | { |
340 | struct x25_sock *x25 = x25_sk(sk); | ||
341 | |||
316 | switch (frametype) { | 342 | switch (frametype) { |
317 | 343 | ||
318 | case X25_RESET_REQUEST: | 344 | case X25_RESET_REQUEST: |
319 | x25_write_internal(sk, X25_RESET_CONFIRMATION); | 345 | x25_write_internal(sk, X25_RESET_CONFIRMATION); |
320 | case X25_RESET_CONFIRMATION: { | 346 | case X25_RESET_CONFIRMATION: { |
321 | struct x25_sock *x25 = x25_sk(sk); | ||
322 | |||
323 | x25_stop_timer(sk); | 347 | x25_stop_timer(sk); |
324 | x25->condition = 0x00; | 348 | x25->condition = 0x00; |
325 | x25->va = 0; | 349 | x25->va = 0; |
@@ -331,6 +355,9 @@ static int x25_state4_machine(struct sock *sk, struct sk_buff *skb, int frametyp | |||
331 | break; | 355 | break; |
332 | } | 356 | } |
333 | case X25_CLEAR_REQUEST: | 357 | case X25_CLEAR_REQUEST: |
358 | if (!pskb_may_pull(skb, X25_STD_MIN_LEN + 2)) | ||
359 | goto out_clear; | ||
360 | |||
334 | x25_write_internal(sk, X25_CLEAR_CONFIRMATION); | 361 | x25_write_internal(sk, X25_CLEAR_CONFIRMATION); |
335 | x25_disconnect(sk, 0, skb->data[3], skb->data[4]); | 362 | x25_disconnect(sk, 0, skb->data[3], skb->data[4]); |
336 | break; | 363 | break; |
@@ -340,6 +367,12 @@ static int x25_state4_machine(struct sock *sk, struct sk_buff *skb, int frametyp | |||
340 | } | 367 | } |
341 | 368 | ||
342 | return 0; | 369 | return 0; |
370 | |||
371 | out_clear: | ||
372 | x25_write_internal(sk, X25_CLEAR_REQUEST); | ||
373 | x25->state = X25_STATE_2; | ||
374 | x25_start_t23timer(sk); | ||
375 | return 0; | ||
343 | } | 376 | } |
344 | 377 | ||
345 | /* Higher level upcall for a LAPB frame */ | 378 | /* Higher level upcall for a LAPB frame */ |