Assorted fixes for keyrings, ASN.1, X.509 and PKCS#7.
Unified · Split
| @@ -148,8 +148,10 @@ struct pkcs7_message *pkcs7_parse_message(const void *data, size_t datalen) · 147 unmodified lines | |||
| 148 | } | 148 | } |
| 149 | 149 | ||
| 150 | ret = pkcs7_check_authattrs(ctx->msg); | 150 | ret = pkcs7_check_authattrs(ctx->msg); |
| 151 | if (ret < 0) | 151 | if (ret < 0) { |
| 152 | msg = ERR_PTR(ret); | ||
| 152 | goto out; | 153 | goto out; |
| 154 | } | ||
| 153 | 155 | ||
| 154 | msg = ctx->msg; | 156 | msg = ctx->msg; |
| 155 | ctx->msg = NULL; | 157 | ctx->msg = NULL; |
| @@ -69,7 +69,7 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7, · 68 unmodified lines | |||
| 69 | /* Self-signed certificates form roots of their own, and if we | 69 | /* Self-signed certificates form roots of their own, and if we |
| 70 | * don't know them, then we can't accept them. | 70 | * don't know them, then we can't accept them. |
| 71 | */ | 71 | */ |
| 72 | if (x509->next == x509) { | 72 | if (x509->signer == x509) { |
| 73 | kleave(" = -ENOKEY [unknown self-signed]"); | 73 | kleave(" = -ENOKEY [unknown self-signed]"); |
| 74 | return -ENOKEY; | 74 | return -ENOKEY; |
| 75 | } | 75 | } |
| @@ -59,11 +59,8 @@ static int pkcs7_digest(struct pkcs7_message *pkcs7, · 58 unmodified lines | |||
| 59 | desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; | 59 | desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; |
| 60 | 60 | ||
| 61 | /* Digest the message [RFC2315 9.3] */ | 61 | /* Digest the message [RFC2315 9.3] */ |
| 62 | ret = crypto_shash_init(desc); | 62 | ret = crypto_shash_digest(desc, pkcs7->data, pkcs7->data_len, |
| 63 | if (ret < 0) | 63 | sig->digest); |
| 64 | goto error; | ||
| 65 | ret = crypto_shash_finup(desc, pkcs7->data, pkcs7->data_len, | ||
| 66 | sig->digest); | ||
| 67 | if (ret < 0) | 64 | if (ret < 0) |
| 68 | goto error; | 65 | goto error; |
| 69 | pr_devel("MsgDigest = [%*ph]\n", 8, sig->digest); | 66 | pr_devel("MsgDigest = [%*ph]\n", 8, sig->digest); |
| @@ -150,7 +147,7 @@ static int pkcs7_find_key(struct pkcs7_message *pkcs7, · 80 unmodified lines | |||
| 150 | pr_devel("Sig %u: Found cert serial match X.509[%u]\n", | 147 | pr_devel("Sig %u: Found cert serial match X.509[%u]\n", |
| 151 | sinfo->index, certix); | 148 | sinfo->index, certix); |
| 152 | 149 | ||
| 153 | if (x509->pub->pkey_algo != sinfo->sig->pkey_algo) { | 150 | if (strcmp(x509->pub->pkey_algo, sinfo->sig->pkey_algo) != 0) { |
| 154 | pr_warn("Sig %u: X.509 algo and PKCS#7 sig algo don't match\n", | 151 | pr_warn("Sig %u: X.509 algo and PKCS#7 sig algo don't match\n", |
| 155 | sinfo->index); | 152 | sinfo->index); |
| 156 | continue; | 153 | continue; |
| @@ -73,7 +73,7 @@ int public_key_verify_signature(const struct public_key *pkey, · 72 unmodified lines | |||
| 73 | char alg_name_buf[CRYPTO_MAX_ALG_NAME]; | 73 | char alg_name_buf[CRYPTO_MAX_ALG_NAME]; |
| 74 | void *output; | 74 | void *output; |
| 75 | unsigned int outlen; | 75 | unsigned int outlen; |
| 76 | int ret = -ENOMEM; | 76 | int ret; |
| 77 | 77 | ||
| 78 | pr_devel("==>%s()\n", __func__); | 78 | pr_devel("==>%s()\n", __func__); |
| 79 | 79 | ||
| @@ -99,6 +99,7 @@ int public_key_verify_signature(const struct public_key *pkey, · 19 unmodified lines | |||
| 99 | if (IS_ERR(tfm)) | 99 | if (IS_ERR(tfm)) |
| 100 | return PTR_ERR(tfm); | 100 | return PTR_ERR(tfm); |
| 101 | 101 | ||
| 102 | ret = -ENOMEM; | ||
| 102 | req = akcipher_request_alloc(tfm, GFP_KERNEL); | 103 | req = akcipher_request_alloc(tfm, GFP_KERNEL); |
| 103 | if (!req) | 104 | if (!req) |
| 104 | goto error_free_tfm; | 105 | goto error_free_tfm; |
| @@ -127,7 +128,7 @@ int public_key_verify_signature(const struct public_key *pkey, · 22 unmodified lines | |||
| 127 | * signature and returns that to us. | 128 | * signature and returns that to us. |
| 128 | */ | 129 | */ |
| 129 | ret = crypto_wait_req(crypto_akcipher_verify(req), &cwait); | 130 | ret = crypto_wait_req(crypto_akcipher_verify(req), &cwait); |
| 130 | if (ret < 0) | 131 | if (ret) |
| 131 | goto out_free_output; | 132 | goto out_free_output; |
| 132 | 133 | ||
| 133 | /* Do the actual verification step. */ | 134 | /* Do the actual verification step. */ |
| @@ -142,6 +143,8 @@ error_free_req: · 8 unmodified lines | |||
| 142 | error_free_tfm: | 143 | error_free_tfm: |
| 143 | crypto_free_akcipher(tfm); | 144 | crypto_free_akcipher(tfm); |
| 144 | pr_devel("<==%s() = %d\n", __func__, ret); | 145 | pr_devel("<==%s() = %d\n", __func__, ret); |
| 146 | if (WARN_ON_ONCE(ret > 0)) | ||
| 147 | ret = -EINVAL; | ||
| 145 | return ret; | 148 | return ret; |
| 146 | } | 149 | } |
| 147 | EXPORT_SYMBOL_GPL(public_key_verify_signature); | 150 | EXPORT_SYMBOL_GPL(public_key_verify_signature); |
| @@ -409,6 +409,8 @@ int x509_extract_key_data(void *context, size_t hdrlen, · 408 unmodified lines | |||
| 409 | ctx->cert->pub->pkey_algo = "rsa"; | 409 | ctx->cert->pub->pkey_algo = "rsa"; |
| 410 | 410 | ||
| 411 | /* Discard the BIT STRING metadata */ | 411 | /* Discard the BIT STRING metadata */ |
| 412 | if (vlen < 1 || *(const u8 *)value != 0) | ||
| 413 | return -EBADMSG; | ||
| 412 | ctx->key = value + 1; | 414 | ctx->key = value + 1; |
| 413 | ctx->key_size = vlen - 1; | 415 | ctx->key_size = vlen - 1; |
| 414 | return 0; | 416 | return 0; |
| @@ -79,11 +79,7 @@ int x509_get_sig_params(struct x509_certificate *cert) · 78 unmodified lines | |||
| 79 | desc->tfm = tfm; | 79 | desc->tfm = tfm; |
| 80 | desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; | 80 | desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; |
| 81 | 81 | ||
| 82 | ret = crypto_shash_init(desc); | 82 | ret = crypto_shash_digest(desc, cert->tbs, cert->tbs_size, sig->digest); |
| 83 | if (ret < 0) | ||
| 84 | goto error_2; | ||
| 85 | might_sleep(); | ||
| 86 | ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, sig->digest); | ||
| 87 | if (ret < 0) | 83 | if (ret < 0) |
| 88 | goto error_2; | 84 | goto error_2; |
| 89 | 85 | ||
| @@ -135,7 +131,7 @@ int x509_check_for_self_signed(struct x509_certificate *cert) · 45 unmodified lines | |||
| 135 | } | 131 | } |
| 136 | 132 | ||
| 137 | ret = -EKEYREJECTED; | 133 | ret = -EKEYREJECTED; |
| 138 | if (cert->pub->pkey_algo != cert->sig->pkey_algo) | 134 | if (strcmp(cert->pub->pkey_algo, cert->sig->pkey_algo) != 0) |
| 139 | goto out; | 135 | goto out; |
| 140 | 136 | ||
| 141 | ret = public_key_verify_signature(cert->pub, cert->sig); | 137 | ret = public_key_verify_signature(cert->pub, cert->sig); |
| @@ -313,42 +313,47 @@ next_op: · 312 unmodified lines | |||
| 313 | 313 | ||
| 314 | /* Decide how to handle the operation */ | 314 | /* Decide how to handle the operation */ |
| 315 | switch (op) { | 315 | switch (op) { |
| 316 | case ASN1_OP_MATCH_ANY_ACT: | ||
| 317 | case ASN1_OP_MATCH_ANY_ACT_OR_SKIP: | ||
| 318 | case ASN1_OP_COND_MATCH_ANY_ACT: | ||
| 319 | case ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP: | ||
| 320 | ret = actions[machine[pc + 1]](context, hdr, tag, data + dp, len); | ||
| 321 | if (ret < 0) | ||
| 322 | return ret; | ||
| 323 | goto skip_data; | ||
| 324 | |||
| 325 | case ASN1_OP_MATCH_ACT: | ||
| 326 | case ASN1_OP_MATCH_ACT_OR_SKIP: | ||
| 327 | case ASN1_OP_COND_MATCH_ACT_OR_SKIP: | ||
| 328 | ret = actions[machine[pc + 2]](context, hdr, tag, data + dp, len); | ||
| 329 | if (ret < 0) | ||
| 330 | return ret; | ||
| 331 | goto skip_data; | ||
| 332 | |||
| 333 | case ASN1_OP_MATCH: | 316 | case ASN1_OP_MATCH: |
| 334 | case ASN1_OP_MATCH_OR_SKIP: | 317 | case ASN1_OP_MATCH_OR_SKIP: |
| 318 | case ASN1_OP_MATCH_ACT: | ||
| 319 | case ASN1_OP_MATCH_ACT_OR_SKIP: | ||
| 335 | case ASN1_OP_MATCH_ANY: | 320 | case ASN1_OP_MATCH_ANY: |
| 336 | case ASN1_OP_MATCH_ANY_OR_SKIP: | 321 | case ASN1_OP_MATCH_ANY_OR_SKIP: |
| 322 | case ASN1_OP_MATCH_ANY_ACT: | ||
| 323 | case ASN1_OP_MATCH_ANY_ACT_OR_SKIP: | ||
| 337 | case ASN1_OP_COND_MATCH_OR_SKIP: | 324 | case ASN1_OP_COND_MATCH_OR_SKIP: |
| 325 | case ASN1_OP_COND_MATCH_ACT_OR_SKIP: | ||
| 338 | case ASN1_OP_COND_MATCH_ANY: | 326 | case ASN1_OP_COND_MATCH_ANY: |
| 339 | case ASN1_OP_COND_MATCH_ANY_OR_SKIP: | 327 | case ASN1_OP_COND_MATCH_ANY_OR_SKIP: |
| 340 | skip_data: | 328 | case ASN1_OP_COND_MATCH_ANY_ACT: |
| 329 | case ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP: | ||
| 330 | |||
| 341 | if (!(flags & FLAG_CONS)) { | 331 | if (!(flags & FLAG_CONS)) { |
| 342 | if (flags & FLAG_INDEFINITE_LENGTH) { | 332 | if (flags & FLAG_INDEFINITE_LENGTH) { |
| 333 | size_t tmp = dp; | ||
| 334 | |||
| 343 | ret = asn1_find_indefinite_length( | 335 | ret = asn1_find_indefinite_length( |
| 344 | data, datalen, &dp, &len, &errmsg); | 336 | data, datalen, &tmp, &len, &errmsg); |
| 345 | if (ret < 0) | 337 | if (ret < 0) |
| 346 | goto error; | 338 | goto error; |
| 347 | } else { | ||
| 348 | dp += len; | ||
| 349 | } | 339 | } |
| 350 | pr_debug("- LEAF: %zu\n", len); | 340 | pr_debug("- LEAF: %zu\n", len); |
| 351 | } | 341 | } |
| 342 | |||
| 343 | if (op & ASN1_OP_MATCH__ACT) { | ||
| 344 | unsigned char act; | ||
| 345 | |||
| 346 | if (op & ASN1_OP_MATCH__ANY) | ||
| 347 | act = machine[pc + 1]; | ||
| 348 | else | ||
| 349 | act = machine[pc + 2]; | ||
| 350 | ret = actions[act](context, hdr, tag, data + dp, len); | ||
| 351 | if (ret < 0) | ||
| 352 | return ret; | ||
| 353 | } | ||
| 354 | |||
| 355 | if (!(flags & FLAG_CONS)) | ||
| 356 | dp += len; | ||
| 352 | pc += asn1_op_lengths[op]; | 357 | pc += asn1_op_lengths[op]; |
| 353 | goto next_op; | 358 | goto next_op; |
| 354 | 359 | ||
| @@ -434,6 +439,8 @@ next_op: · 79 unmodified lines | |||
| 434 | else | 439 | else |
| 435 | act = machine[pc + 1]; | 440 | act = machine[pc + 1]; |
| 436 | ret = actions[act](context, hdr, 0, data + tdp, len); | 441 | ret = actions[act](context, hdr, 0, data + tdp, len); |
| 442 | if (ret < 0) | ||
| 443 | return ret; | ||
| 437 | } | 444 | } |
| 438 | pc += asn1_op_lengths[op]; | 445 | pc += asn1_op_lengths[op]; |
| 439 | goto next_op; | 446 | goto next_op; |
| @@ -116,14 +116,14 @@ int sprint_oid(const void *data, size_t datasize, char *buffer, size_t bufsize) · 115 unmodified lines | |||
| 116 | int count; | 116 | int count; |
| 117 | 117 | ||
| 118 | if (v >= end) | 118 | if (v >= end) |
| 119 | return -EBADMSG; | 119 | goto bad; |
| 120 | 120 | ||
| 121 | n = *v++; | 121 | n = *v++; |
| 122 | ret = count = snprintf(buffer, bufsize, "%u.%u", n / 40, n % 40); | 122 | ret = count = snprintf(buffer, bufsize, "%u.%u", n / 40, n % 40); |
| 123 | if (count >= bufsize) | ||
| 124 | return -ENOBUFS; | ||
| 123 | buffer += count; | 125 | buffer += count; |
| 124 | bufsize -= count; | 126 | bufsize -= count; |
| 125 | if (bufsize == 0) | ||
| 126 | return -ENOBUFS; | ||
| 127 | 127 | ||
| 128 | while (v < end) { | 128 | while (v < end) { |
| 129 | num = 0; | 129 | num = 0; |
| @@ -134,20 +134,24 @@ int sprint_oid(const void *data, size_t datasize, char *buffer, size_t bufsize) · 4 unmodified lines | |||
| 134 | num = n & 0x7f; | 134 | num = n & 0x7f; |
| 135 | do { | 135 | do { |
| 136 | if (v >= end) | 136 | if (v >= end) |
| 137 | return -EBADMSG; | 137 | goto bad; |
| 138 | n = *v++; | 138 | n = *v++; |
| 139 | num <<= 7; | 139 | num <<= 7; |
| 140 | num |= n & 0x7f; | 140 | num |= n & 0x7f; |
| 141 | } while (n & 0x80); | 141 | } while (n & 0x80); |
| 142 | } | 142 | } |
| 143 | ret += count = snprintf(buffer, bufsize, ".%lu", num); | 143 | ret += count = snprintf(buffer, bufsize, ".%lu", num); |
| 144 | buffer += count; | 144 | if (count >= bufsize) |
| 145 | if (bufsize <= count) | ||
| 146 | return -ENOBUFS; | 145 | return -ENOBUFS; |
| 146 | buffer += count; | ||
| 147 | bufsize -= count; | 147 | bufsize -= count; |
| 148 | } | 148 | } |
| 149 | 149 | ||
| 150 | return ret; | 150 | return ret; |
| 151 | |||
| 152 | bad: | ||
| 153 | snprintf(buffer, bufsize, "(bad)"); | ||
| 154 | return -EBADMSG; | ||
| 151 | } | 155 | } |
| 152 | EXPORT_SYMBOL_GPL(sprint_oid); | 156 | EXPORT_SYMBOL_GPL(sprint_oid); |
| 153 | 157 | ||
| @@ -833,7 +833,6 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, · 832 unmodified lines | |||
| 833 | 833 | ||
| 834 | key_check(keyring); | 834 | key_check(keyring); |
| 835 | 835 | ||
| 836 | key_ref = ERR_PTR(-EPERM); | ||
| 837 | if (!(flags & KEY_ALLOC_BYPASS_RESTRICTION)) | 836 | if (!(flags & KEY_ALLOC_BYPASS_RESTRICTION)) |
| 838 | restrict_link = keyring->restrict_link; | 837 | restrict_link = keyring->restrict_link; |
| 839 | 838 | ||
| @@ -1588,9 +1588,8 @@ error_keyring: · 1587 unmodified lines | |||
| 1588 | * The caller must have Setattr permission to change keyring restrictions. | 1588 | * The caller must have Setattr permission to change keyring restrictions. |
| 1589 | * | 1589 | * |
| 1590 | * The requested type name may be a NULL pointer to reject all attempts | 1590 | * The requested type name may be a NULL pointer to reject all attempts |
| 1591 | * to link to the keyring. If _type is non-NULL, _restriction can be | 1591 | * to link to the keyring. In this case, _restriction must also be NULL. |
| 1592 | * NULL or a pointer to a string describing the restriction. If _type is | 1592 | * Otherwise, both _type and _restriction must be non-NULL. |
| 1593 | * NULL, _restriction must also be NULL. | ||
| 1594 | * | 1593 | * |
| 1595 | * Returns 0 if successful. | 1594 | * Returns 0 if successful. |
| 1596 | */ | 1595 | */ |
| @@ -1598,7 +1597,6 @@ long keyctl_restrict_keyring(key_serial_t id, const char __user *_type, · 1 unmodified line | |||
| 1598 | const char __user *_restriction) | 1597 | const char __user *_restriction) |
| 1599 | { | 1598 | { |
| 1600 | key_ref_t key_ref; | 1599 | key_ref_t key_ref; |
| 1601 | bool link_reject = !_type; | ||
| 1602 | char type[32]; | 1600 | char type[32]; |
| 1603 | char *restriction = NULL; | 1601 | char *restriction = NULL; |
| 1604 | long ret; | 1602 | long ret; |
| @@ -1607,31 +1605,29 @@ long keyctl_restrict_keyring(key_serial_t id, const char __user *_type, · 2 unmodified lines | |||
| 1607 | if (IS_ERR(key_ref)) | 1605 | if (IS_ERR(key_ref)) |
| 1608 | return PTR_ERR(key_ref); | 1606 | return PTR_ERR(key_ref); |
| 1609 | 1607 | ||
| 1608 | ret = -EINVAL; | ||
| 1610 | if (_type) { | 1609 | if (_type) { |
| 1611 | ret = key_get_type_from_user(type, _type, sizeof(type)); | 1610 | if (!_restriction) |
| 1612 | if (ret < 0) | ||
| 1613 | goto error; | 1611 | goto error; |
| 1614 | } | ||
| 1615 | 1612 | ||
| 1616 | if (_restriction) { | 1613 | ret = key_get_type_from_user(type, _type, sizeof(type)); |
| 1617 | if (!_type) { | 1614 | if (ret < 0) |
| 1618 | ret = -EINVAL; | ||
| 1619 | goto error; | 1615 | goto error; |
| 1620 | } | ||
| 1621 | 1616 | ||
| 1622 | restriction = strndup_user(_restriction, PAGE_SIZE); | 1617 | restriction = strndup_user(_restriction, PAGE_SIZE); |
| 1623 | if (IS_ERR(restriction)) { | 1618 | if (IS_ERR(restriction)) { |
| 1624 | ret = PTR_ERR(restriction); | 1619 | ret = PTR_ERR(restriction); |
| 1625 | goto error; | 1620 | goto error; |
| 1626 | } | 1621 | } |
| 1622 | } else { | ||
| 1623 | if (_restriction) | ||
| 1624 | goto error; | ||
| 1627 | } | 1625 | } |
| 1628 | 1626 | ||
| 1629 | ret = keyring_restrict(key_ref, link_reject ? NULL : type, restriction); | 1627 | ret = keyring_restrict(key_ref, _type ? type : NULL, restriction); |
| 1630 | kfree(restriction); | 1628 | kfree(restriction); |
| 1631 | |||
| 1632 | error: | 1629 | error: |
| 1633 | key_ref_put(key_ref); | 1630 | key_ref_put(key_ref); |
| 1634 | |||
| 1635 | return ret; | 1631 | return ret; |
| 1636 | } | 1632 | } |
| 1637 | 1633 | ||
| @@ -251,11 +251,12 @@ static int construct_key(struct key *key, const void *callout_info, · 250 unmodified lines | |||
| 251 | * The keyring selected is returned with an extra reference upon it which the | 251 | * The keyring selected is returned with an extra reference upon it which the |
| 252 | * caller must release. | 252 | * caller must release. |
| 253 | */ | 253 | */ |
| 254 | static void construct_get_dest_keyring(struct key **_dest_keyring) | 254 | static int construct_get_dest_keyring(struct key **_dest_keyring) |
| 255 | { | 255 | { |
| 256 | struct request_key_auth *rka; | 256 | struct request_key_auth *rka; |
| 257 | const struct cred *cred = current_cred(); | 257 | const struct cred *cred = current_cred(); |
| 258 | struct key *dest_keyring = *_dest_keyring, *authkey; | 258 | struct key *dest_keyring = *_dest_keyring, *authkey; |
| 259 | int ret; | ||
| 259 | 260 | ||
| 260 | kenter("%p", dest_keyring); | 261 | kenter("%p", dest_keyring); |
| 261 | 262 | ||
| @@ -264,6 +265,8 @@ static void construct_get_dest_keyring(struct key **_dest_keyring) · 2 unmodified lines | |||
| 264 | /* the caller supplied one */ | 265 | /* the caller supplied one */ |
| 265 | key_get(dest_keyring); | 266 | key_get(dest_keyring); |
| 266 | } else { | 267 | } else { |
| 268 | bool do_perm_check = true; | ||
| 269 | |||
| 267 | /* use a default keyring; falling through the cases until we | 270 | /* use a default keyring; falling through the cases until we |
| 268 | * find one that we actually have */ | 271 | * find one that we actually have */ |
| 269 | switch (cred->jit_keyring) { | 272 | switch (cred->jit_keyring) { |
| @@ -278,8 +281,10 @@ static void construct_get_dest_keyring(struct key **_dest_keyring) · 8 unmodified lines | |||
| 278 | dest_keyring = | 281 | dest_keyring = |
| 279 | key_get(rka->dest_keyring); | 282 | key_get(rka->dest_keyring); |
| 280 | up_read(&authkey->sem); | 283 | up_read(&authkey->sem); |
| 281 | if (dest_keyring) | 284 | if (dest_keyring) { |
| 285 | do_perm_check = false; | ||
| 282 | break; | 286 | break; |
| 287 | } | ||
| 283 | } | 288 | } |
| 284 | 289 | ||
| 285 | case KEY_REQKEY_DEFL_THREAD_KEYRING: | 290 | case KEY_REQKEY_DEFL_THREAD_KEYRING: |
| @@ -314,11 +319,29 @@ static void construct_get_dest_keyring(struct key **_dest_keyring) · 28 unmodified lines | |||
| 314 | default: | 319 | default: |
| 315 | BUG(); | 320 | BUG(); |
| 316 | } | 321 | } |
| 322 | |||
| 323 | /* | ||
| 324 | * Require Write permission on the keyring. This is essential | ||
| 325 | * because the default keyring may be the session keyring, and | ||
| 326 | * joining a keyring only requires Search permission. | ||
| 327 | * | ||
| 328 | * However, this check is skipped for the "requestor keyring" so | ||
| 329 | * that /sbin/request-key can itself use request_key() to add | ||
| 330 | * keys to the original requestor's destination keyring. | ||
| 331 | */ | ||
| 332 | if (dest_keyring && do_perm_check) { | ||
| 333 | ret = key_permission(make_key_ref(dest_keyring, 1), | ||
| 334 | KEY_NEED_WRITE); | ||
| 335 | if (ret) { | ||
| 336 | key_put(dest_keyring); | ||
| 337 | return ret; | ||
| 338 | } | ||
| 339 | } | ||
| 317 | } | 340 | } |
| 318 | 341 | ||
| 319 | *_dest_keyring = dest_keyring; | 342 | *_dest_keyring = dest_keyring; |
| 320 | kleave(" [dk %d]", key_serial(dest_keyring)); | 343 | kleave(" [dk %d]", key_serial(dest_keyring)); |
| 321 | return; | 344 | return 0; |
| 322 | } | 345 | } |
| 323 | 346 | ||
| 324 | /* | 347 | /* |
| @@ -444,11 +467,15 @@ static struct key *construct_key_and_link(struct keyring_search_context *ctx, · 119 unmodified lines | |||
| 444 | if (ctx->index_key.type == &key_type_keyring) | 467 | if (ctx->index_key.type == &key_type_keyring) |
| 445 | return ERR_PTR(-EPERM); | 468 | return ERR_PTR(-EPERM); |
| 446 | 469 | ||
| 447 | user = key_user_lookup(current_fsuid()); | 470 | ret = construct_get_dest_keyring(&dest_keyring); |
| 448 | if (!user) | 471 | if (ret) |
| 449 | return ERR_PTR(-ENOMEM); | 472 | goto error; |
| 450 | 473 | ||
| 451 | construct_get_dest_keyring(&dest_keyring); | 474 | user = key_user_lookup(current_fsuid()); |
| 475 | if (!user) { | ||
| 476 | ret = -ENOMEM; | ||
| 477 | goto error_put_dest_keyring; | ||
| 478 | } | ||
| 452 | 479 | ||
| 453 | ret = construct_alloc_key(ctx, dest_keyring, flags, user, &key); | 480 | ret = construct_alloc_key(ctx, dest_keyring, flags, user, &key); |
| 454 | key_user_put(user); | 481 | key_user_put(user); |
| @@ -463,7 +490,7 @@ static struct key *construct_key_and_link(struct keyring_search_context *ctx, · 8 unmodified lines | |||
| 463 | } else if (ret == -EINPROGRESS) { | 490 | } else if (ret == -EINPROGRESS) { |
| 464 | ret = 0; | 491 | ret = 0; |
| 465 | } else { | 492 | } else { |
| 466 | goto couldnt_alloc_key; | 493 | goto error_put_dest_keyring; |
| 467 | } | 494 | } |
| 468 | 495 | ||
| 469 | key_put(dest_keyring); | 496 | key_put(dest_keyring); |
| @@ -473,8 +500,9 @@ static struct key *construct_key_and_link(struct keyring_search_context *ctx, · 3 unmodified lines | |||
| 473 | construction_failed: | 500 | construction_failed: |
| 474 | key_negate_and_link(key, key_negative_timeout, NULL, NULL); | 501 | key_negate_and_link(key, key_negative_timeout, NULL, NULL); |
| 475 | key_put(key); | 502 | key_put(key); |
| 476 | couldnt_alloc_key: | 503 | error_put_dest_keyring: |
| 477 | key_put(dest_keyring); | 504 | key_put(dest_keyring); |
| 505 | error: | ||
| 478 | kleave(" = %d", ret); | 506 | kleave(" = %d", ret); |
| 479 | return ERR_PTR(ret); | 507 | return ERR_PTR(ret); |
| 480 | } | 508 | } |
| @@ -546,9 +574,7 @@ struct key *request_key_and_link(struct key_type *type, · 65 unmodified lines | |||
| 546 | if (!IS_ERR(key_ref)) { | 574 | if (!IS_ERR(key_ref)) { |
| 547 | key = key_ref_to_ptr(key_ref); | 575 | key = key_ref_to_ptr(key_ref); |
| 548 | if (dest_keyring) { | 576 | if (dest_keyring) { |
| 549 | construct_get_dest_keyring(&dest_keyring); | ||
| 550 | ret = key_link(dest_keyring, key); | 577 | ret = key_link(dest_keyring, key); |
| 551 | key_put(dest_keyring); | ||
| 552 | if (ret < 0) { | 578 | if (ret < 0) { |
| 553 | key_put(key); | 579 | key_put(key); |
| 554 | key = ERR_PTR(ret); | 580 | key = ERR_PTR(ret); |