diff options
| -rw-r--r-- | net/key/af_key.c | 45 |
1 files changed, 35 insertions, 10 deletions
diff --git a/net/key/af_key.c b/net/key/af_key.c index 7e2e7188e7f4..e62e52e8f141 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c | |||
| @@ -437,6 +437,24 @@ static int verify_address_len(const void *p) | |||
| 437 | return 0; | 437 | return 0; |
| 438 | } | 438 | } |
| 439 | 439 | ||
| 440 | static inline int sadb_key_len(const struct sadb_key *key) | ||
| 441 | { | ||
| 442 | int key_bytes = DIV_ROUND_UP(key->sadb_key_bits, 8); | ||
| 443 | |||
| 444 | return DIV_ROUND_UP(sizeof(struct sadb_key) + key_bytes, | ||
| 445 | sizeof(uint64_t)); | ||
| 446 | } | ||
| 447 | |||
| 448 | static int verify_key_len(const void *p) | ||
| 449 | { | ||
| 450 | const struct sadb_key *key = p; | ||
| 451 | |||
| 452 | if (sadb_key_len(key) > key->sadb_key_len) | ||
| 453 | return -EINVAL; | ||
| 454 | |||
| 455 | return 0; | ||
| 456 | } | ||
| 457 | |||
| 440 | static inline int pfkey_sec_ctx_len(const struct sadb_x_sec_ctx *sec_ctx) | 458 | static inline int pfkey_sec_ctx_len(const struct sadb_x_sec_ctx *sec_ctx) |
| 441 | { | 459 | { |
| 442 | return DIV_ROUND_UP(sizeof(struct sadb_x_sec_ctx) + | 460 | return DIV_ROUND_UP(sizeof(struct sadb_x_sec_ctx) + |
| @@ -533,16 +551,25 @@ static int parse_exthdrs(struct sk_buff *skb, const struct sadb_msg *hdr, void * | |||
| 533 | return -EINVAL; | 551 | return -EINVAL; |
| 534 | if (ext_hdrs[ext_type-1] != NULL) | 552 | if (ext_hdrs[ext_type-1] != NULL) |
| 535 | return -EINVAL; | 553 | return -EINVAL; |
| 536 | if (ext_type == SADB_EXT_ADDRESS_SRC || | 554 | switch (ext_type) { |
| 537 | ext_type == SADB_EXT_ADDRESS_DST || | 555 | case SADB_EXT_ADDRESS_SRC: |
| 538 | ext_type == SADB_EXT_ADDRESS_PROXY || | 556 | case SADB_EXT_ADDRESS_DST: |
| 539 | ext_type == SADB_X_EXT_NAT_T_OA) { | 557 | case SADB_EXT_ADDRESS_PROXY: |
| 558 | case SADB_X_EXT_NAT_T_OA: | ||
| 540 | if (verify_address_len(p)) | 559 | if (verify_address_len(p)) |
| 541 | return -EINVAL; | 560 | return -EINVAL; |
| 542 | } | 561 | break; |
| 543 | if (ext_type == SADB_X_EXT_SEC_CTX) { | 562 | case SADB_X_EXT_SEC_CTX: |
| 544 | if (verify_sec_ctx_len(p)) | 563 | if (verify_sec_ctx_len(p)) |
| 545 | return -EINVAL; | 564 | return -EINVAL; |
| 565 | break; | ||
| 566 | case SADB_EXT_KEY_AUTH: | ||
| 567 | case SADB_EXT_KEY_ENCRYPT: | ||
| 568 | if (verify_key_len(p)) | ||
| 569 | return -EINVAL; | ||
| 570 | break; | ||
| 571 | default: | ||
| 572 | break; | ||
| 546 | } | 573 | } |
| 547 | ext_hdrs[ext_type-1] = (void *) p; | 574 | ext_hdrs[ext_type-1] = (void *) p; |
| 548 | } | 575 | } |
| @@ -1104,14 +1131,12 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net, | |||
| 1104 | key = ext_hdrs[SADB_EXT_KEY_AUTH - 1]; | 1131 | key = ext_hdrs[SADB_EXT_KEY_AUTH - 1]; |
| 1105 | if (key != NULL && | 1132 | if (key != NULL && |
| 1106 | sa->sadb_sa_auth != SADB_X_AALG_NULL && | 1133 | sa->sadb_sa_auth != SADB_X_AALG_NULL && |
| 1107 | ((key->sadb_key_bits+7) / 8 == 0 || | 1134 | key->sadb_key_bits == 0) |
| 1108 | (key->sadb_key_bits+7) / 8 > key->sadb_key_len * sizeof(uint64_t))) | ||
| 1109 | return ERR_PTR(-EINVAL); | 1135 | return ERR_PTR(-EINVAL); |
| 1110 | key = ext_hdrs[SADB_EXT_KEY_ENCRYPT-1]; | 1136 | key = ext_hdrs[SADB_EXT_KEY_ENCRYPT-1]; |
| 1111 | if (key != NULL && | 1137 | if (key != NULL && |
| 1112 | sa->sadb_sa_encrypt != SADB_EALG_NULL && | 1138 | sa->sadb_sa_encrypt != SADB_EALG_NULL && |
| 1113 | ((key->sadb_key_bits+7) / 8 == 0 || | 1139 | key->sadb_key_bits == 0) |
| 1114 | (key->sadb_key_bits+7) / 8 > key->sadb_key_len * sizeof(uint64_t))) | ||
| 1115 | return ERR_PTR(-EINVAL); | 1140 | return ERR_PTR(-EINVAL); |
| 1116 | 1141 | ||
| 1117 | x = xfrm_state_alloc(net); | 1142 | x = xfrm_state_alloc(net); |
