diff options
Diffstat (limited to 'net/can/gw.c')
| -rw-r--r-- | net/can/gw.c | 30 |
1 files changed, 27 insertions, 3 deletions
diff --git a/net/can/gw.c b/net/can/gw.c index faa3da88a127..53859346dc9a 100644 --- a/net/can/gw.c +++ b/net/can/gw.c | |||
| @@ -416,13 +416,29 @@ static void can_can_gw_rcv(struct sk_buff *skb, void *data) | |||
| 416 | while (modidx < MAX_MODFUNCTIONS && gwj->mod.modfunc[modidx]) | 416 | while (modidx < MAX_MODFUNCTIONS && gwj->mod.modfunc[modidx]) |
| 417 | (*gwj->mod.modfunc[modidx++])(cf, &gwj->mod); | 417 | (*gwj->mod.modfunc[modidx++])(cf, &gwj->mod); |
| 418 | 418 | ||
| 419 | /* check for checksum updates when the CAN frame has been modified */ | 419 | /* Has the CAN frame been modified? */ |
| 420 | if (modidx) { | 420 | if (modidx) { |
| 421 | if (gwj->mod.csumfunc.crc8) | 421 | /* get available space for the processed CAN frame type */ |
| 422 | int max_len = nskb->len - offsetof(struct can_frame, data); | ||
| 423 | |||
| 424 | /* dlc may have changed, make sure it fits to the CAN frame */ | ||
| 425 | if (cf->can_dlc > max_len) | ||
| 426 | goto out_delete; | ||
| 427 | |||
| 428 | /* check for checksum updates in classic CAN length only */ | ||
| 429 | if (gwj->mod.csumfunc.crc8) { | ||
| 430 | if (cf->can_dlc > 8) | ||
| 431 | goto out_delete; | ||
| 432 | |||
| 422 | (*gwj->mod.csumfunc.crc8)(cf, &gwj->mod.csum.crc8); | 433 | (*gwj->mod.csumfunc.crc8)(cf, &gwj->mod.csum.crc8); |
| 434 | } | ||
| 435 | |||
| 436 | if (gwj->mod.csumfunc.xor) { | ||
| 437 | if (cf->can_dlc > 8) | ||
| 438 | goto out_delete; | ||
| 423 | 439 | ||
| 424 | if (gwj->mod.csumfunc.xor) | ||
| 425 | (*gwj->mod.csumfunc.xor)(cf, &gwj->mod.csum.xor); | 440 | (*gwj->mod.csumfunc.xor)(cf, &gwj->mod.csum.xor); |
| 441 | } | ||
| 426 | } | 442 | } |
| 427 | 443 | ||
| 428 | /* clear the skb timestamp if not configured the other way */ | 444 | /* clear the skb timestamp if not configured the other way */ |
| @@ -434,6 +450,14 @@ static void can_can_gw_rcv(struct sk_buff *skb, void *data) | |||
| 434 | gwj->dropped_frames++; | 450 | gwj->dropped_frames++; |
| 435 | else | 451 | else |
| 436 | gwj->handled_frames++; | 452 | gwj->handled_frames++; |
| 453 | |||
| 454 | return; | ||
| 455 | |||
| 456 | out_delete: | ||
| 457 | /* delete frame due to misconfiguration */ | ||
| 458 | gwj->deleted_frames++; | ||
| 459 | kfree_skb(nskb); | ||
| 460 | return; | ||
| 437 | } | 461 | } |
| 438 | 462 | ||
| 439 | static inline int cgw_register_filter(struct net *net, struct cgw_job *gwj) | 463 | static inline int cgw_register_filter(struct net *net, struct cgw_job *gwj) |
