mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 12:28:41 +08:00
Keyrings fixes
-----BEGIN PGP SIGNATURE----- iQIVAwUAWiqvvPSw1s6N8H32AQLq0Q/+LaD+nbuVGCnTSQ1h3QyU2xJrvhnjJseU CpsMctc4XT4iyI7VjhhVZQBQm7bnS3ZEFSz95aDpNsTA8z4VTF3loVvqaaRV2k3q dBciol9sqPbzSLLvS49lxoa4ZfxATvwvzhiVq5yi1XavWhl1svf42kH27J3PJ+DV IzzaARNZ4GmiJOx4TUfN7jypro6Vc0k6oILAKUjifJ9mCh9eYUoHILzzlOg+FqtY OIFcHdc7kbNDJwHaChZDxMK/jbp87feQ6z+H66zoIClV405g9MBIO21xVnikL1fK 4SHdfLPy4XVgLVYqseAMoAcm7ZIxF/WYBDpfdd77urCc5FPifILWDJ4sn4SPRTZT 2eE761RmyH3TB6Xe6TyCL7NjpFruI7X2hFExgDVYnbsAlPlMvHB2BvcBMaeFDTnn Gh7w+FX4LT9hC9hNyOEop5fB0Bi3A53/3W4vQWStTMNslDh7at9p1SJlcFf/Ix6M P1TcsaPR3P0juZ4Klku3JOIyU8e1ogji1W+vjGe/2fCSS5dTZnsF4wOd8dqCc/PB gZJk6MDt8CIm7amTEj50Pp+35MlOolnM+TC4DLZ9i8nZf73Ec9SIbuXfX3wKK1JX 5pde9oUlX3/QTQPso2Dt7Yzl5Vnhwro48Hf5IHV45wyp1stFggB0t4AmpAxA1g87 odyy5L1AESw= =Yz52 -----END PGP SIGNATURE----- Merge tag 'keys-fixes-20171208' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs into keys-for-linus Assorted fixes for keyrings, ASN.1, X.509 and PKCS#7.
This commit is contained in:
commit
4ded3bec65
@ -148,8 +148,10 @@ struct pkcs7_message *pkcs7_parse_message(const void *data, size_t datalen)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ret = pkcs7_check_authattrs(ctx->msg);
|
ret = pkcs7_check_authattrs(ctx->msg);
|
||||||
if (ret < 0)
|
if (ret < 0) {
|
||||||
|
msg = ERR_PTR(ret);
|
||||||
goto out;
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
msg = ctx->msg;
|
msg = ctx->msg;
|
||||||
ctx->msg = NULL;
|
ctx->msg = NULL;
|
||||||
|
@ -69,7 +69,7 @@ static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7,
|
|||||||
/* Self-signed certificates form roots of their own, and if we
|
/* Self-signed certificates form roots of their own, and if we
|
||||||
* don't know them, then we can't accept them.
|
* don't know them, then we can't accept them.
|
||||||
*/
|
*/
|
||||||
if (x509->next == x509) {
|
if (x509->signer == x509) {
|
||||||
kleave(" = -ENOKEY [unknown self-signed]");
|
kleave(" = -ENOKEY [unknown self-signed]");
|
||||||
return -ENOKEY;
|
return -ENOKEY;
|
||||||
}
|
}
|
||||||
|
@ -59,10 +59,7 @@ static int pkcs7_digest(struct pkcs7_message *pkcs7,
|
|||||||
desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
|
desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
|
||||||
|
|
||||||
/* Digest the message [RFC2315 9.3] */
|
/* Digest the message [RFC2315 9.3] */
|
||||||
ret = crypto_shash_init(desc);
|
ret = crypto_shash_digest(desc, pkcs7->data, pkcs7->data_len,
|
||||||
if (ret < 0)
|
|
||||||
goto error;
|
|
||||||
ret = crypto_shash_finup(desc, pkcs7->data, pkcs7->data_len,
|
|
||||||
sig->digest);
|
sig->digest);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto error;
|
goto error;
|
||||||
@ -150,7 +147,7 @@ static int pkcs7_find_key(struct pkcs7_message *pkcs7,
|
|||||||
pr_devel("Sig %u: Found cert serial match X.509[%u]\n",
|
pr_devel("Sig %u: Found cert serial match X.509[%u]\n",
|
||||||
sinfo->index, certix);
|
sinfo->index, certix);
|
||||||
|
|
||||||
if (x509->pub->pkey_algo != sinfo->sig->pkey_algo) {
|
if (strcmp(x509->pub->pkey_algo, sinfo->sig->pkey_algo) != 0) {
|
||||||
pr_warn("Sig %u: X.509 algo and PKCS#7 sig algo don't match\n",
|
pr_warn("Sig %u: X.509 algo and PKCS#7 sig algo don't match\n",
|
||||||
sinfo->index);
|
sinfo->index);
|
||||||
continue;
|
continue;
|
||||||
|
@ -73,7 +73,7 @@ int public_key_verify_signature(const struct public_key *pkey,
|
|||||||
char alg_name_buf[CRYPTO_MAX_ALG_NAME];
|
char alg_name_buf[CRYPTO_MAX_ALG_NAME];
|
||||||
void *output;
|
void *output;
|
||||||
unsigned int outlen;
|
unsigned int outlen;
|
||||||
int ret = -ENOMEM;
|
int ret;
|
||||||
|
|
||||||
pr_devel("==>%s()\n", __func__);
|
pr_devel("==>%s()\n", __func__);
|
||||||
|
|
||||||
@ -99,6 +99,7 @@ int public_key_verify_signature(const struct public_key *pkey,
|
|||||||
if (IS_ERR(tfm))
|
if (IS_ERR(tfm))
|
||||||
return PTR_ERR(tfm);
|
return PTR_ERR(tfm);
|
||||||
|
|
||||||
|
ret = -ENOMEM;
|
||||||
req = akcipher_request_alloc(tfm, GFP_KERNEL);
|
req = akcipher_request_alloc(tfm, GFP_KERNEL);
|
||||||
if (!req)
|
if (!req)
|
||||||
goto error_free_tfm;
|
goto error_free_tfm;
|
||||||
@ -127,7 +128,7 @@ int public_key_verify_signature(const struct public_key *pkey,
|
|||||||
* signature and returns that to us.
|
* signature and returns that to us.
|
||||||
*/
|
*/
|
||||||
ret = crypto_wait_req(crypto_akcipher_verify(req), &cwait);
|
ret = crypto_wait_req(crypto_akcipher_verify(req), &cwait);
|
||||||
if (ret < 0)
|
if (ret)
|
||||||
goto out_free_output;
|
goto out_free_output;
|
||||||
|
|
||||||
/* Do the actual verification step. */
|
/* Do the actual verification step. */
|
||||||
@ -142,6 +143,8 @@ error_free_req:
|
|||||||
error_free_tfm:
|
error_free_tfm:
|
||||||
crypto_free_akcipher(tfm);
|
crypto_free_akcipher(tfm);
|
||||||
pr_devel("<==%s() = %d\n", __func__, ret);
|
pr_devel("<==%s() = %d\n", __func__, ret);
|
||||||
|
if (WARN_ON_ONCE(ret > 0))
|
||||||
|
ret = -EINVAL;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(public_key_verify_signature);
|
EXPORT_SYMBOL_GPL(public_key_verify_signature);
|
||||||
|
@ -409,6 +409,8 @@ int x509_extract_key_data(void *context, size_t hdrlen,
|
|||||||
ctx->cert->pub->pkey_algo = "rsa";
|
ctx->cert->pub->pkey_algo = "rsa";
|
||||||
|
|
||||||
/* Discard the BIT STRING metadata */
|
/* Discard the BIT STRING metadata */
|
||||||
|
if (vlen < 1 || *(const u8 *)value != 0)
|
||||||
|
return -EBADMSG;
|
||||||
ctx->key = value + 1;
|
ctx->key = value + 1;
|
||||||
ctx->key_size = vlen - 1;
|
ctx->key_size = vlen - 1;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -79,11 +79,7 @@ int x509_get_sig_params(struct x509_certificate *cert)
|
|||||||
desc->tfm = tfm;
|
desc->tfm = tfm;
|
||||||
desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
|
desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
|
||||||
|
|
||||||
ret = crypto_shash_init(desc);
|
ret = crypto_shash_digest(desc, cert->tbs, cert->tbs_size, sig->digest);
|
||||||
if (ret < 0)
|
|
||||||
goto error_2;
|
|
||||||
might_sleep();
|
|
||||||
ret = crypto_shash_finup(desc, cert->tbs, cert->tbs_size, sig->digest);
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto error_2;
|
goto error_2;
|
||||||
|
|
||||||
@ -135,7 +131,7 @@ int x509_check_for_self_signed(struct x509_certificate *cert)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ret = -EKEYREJECTED;
|
ret = -EKEYREJECTED;
|
||||||
if (cert->pub->pkey_algo != cert->sig->pkey_algo)
|
if (strcmp(cert->pub->pkey_algo, cert->sig->pkey_algo) != 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
ret = public_key_verify_signature(cert->pub, cert->sig);
|
ret = public_key_verify_signature(cert->pub, cert->sig);
|
||||||
|
@ -313,42 +313,47 @@ next_op:
|
|||||||
|
|
||||||
/* Decide how to handle the operation */
|
/* Decide how to handle the operation */
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case ASN1_OP_MATCH_ANY_ACT:
|
|
||||||
case ASN1_OP_MATCH_ANY_ACT_OR_SKIP:
|
|
||||||
case ASN1_OP_COND_MATCH_ANY_ACT:
|
|
||||||
case ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP:
|
|
||||||
ret = actions[machine[pc + 1]](context, hdr, tag, data + dp, len);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
goto skip_data;
|
|
||||||
|
|
||||||
case ASN1_OP_MATCH_ACT:
|
|
||||||
case ASN1_OP_MATCH_ACT_OR_SKIP:
|
|
||||||
case ASN1_OP_COND_MATCH_ACT_OR_SKIP:
|
|
||||||
ret = actions[machine[pc + 2]](context, hdr, tag, data + dp, len);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
goto skip_data;
|
|
||||||
|
|
||||||
case ASN1_OP_MATCH:
|
case ASN1_OP_MATCH:
|
||||||
case ASN1_OP_MATCH_OR_SKIP:
|
case ASN1_OP_MATCH_OR_SKIP:
|
||||||
|
case ASN1_OP_MATCH_ACT:
|
||||||
|
case ASN1_OP_MATCH_ACT_OR_SKIP:
|
||||||
case ASN1_OP_MATCH_ANY:
|
case ASN1_OP_MATCH_ANY:
|
||||||
case ASN1_OP_MATCH_ANY_OR_SKIP:
|
case ASN1_OP_MATCH_ANY_OR_SKIP:
|
||||||
|
case ASN1_OP_MATCH_ANY_ACT:
|
||||||
|
case ASN1_OP_MATCH_ANY_ACT_OR_SKIP:
|
||||||
case ASN1_OP_COND_MATCH_OR_SKIP:
|
case ASN1_OP_COND_MATCH_OR_SKIP:
|
||||||
|
case ASN1_OP_COND_MATCH_ACT_OR_SKIP:
|
||||||
case ASN1_OP_COND_MATCH_ANY:
|
case ASN1_OP_COND_MATCH_ANY:
|
||||||
case ASN1_OP_COND_MATCH_ANY_OR_SKIP:
|
case ASN1_OP_COND_MATCH_ANY_OR_SKIP:
|
||||||
skip_data:
|
case ASN1_OP_COND_MATCH_ANY_ACT:
|
||||||
|
case ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP:
|
||||||
|
|
||||||
if (!(flags & FLAG_CONS)) {
|
if (!(flags & FLAG_CONS)) {
|
||||||
if (flags & FLAG_INDEFINITE_LENGTH) {
|
if (flags & FLAG_INDEFINITE_LENGTH) {
|
||||||
|
size_t tmp = dp;
|
||||||
|
|
||||||
ret = asn1_find_indefinite_length(
|
ret = asn1_find_indefinite_length(
|
||||||
data, datalen, &dp, &len, &errmsg);
|
data, datalen, &tmp, &len, &errmsg);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto error;
|
goto error;
|
||||||
} else {
|
|
||||||
dp += len;
|
|
||||||
}
|
}
|
||||||
pr_debug("- LEAF: %zu\n", len);
|
pr_debug("- LEAF: %zu\n", len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (op & ASN1_OP_MATCH__ACT) {
|
||||||
|
unsigned char act;
|
||||||
|
|
||||||
|
if (op & ASN1_OP_MATCH__ANY)
|
||||||
|
act = machine[pc + 1];
|
||||||
|
else
|
||||||
|
act = machine[pc + 2];
|
||||||
|
ret = actions[act](context, hdr, tag, data + dp, len);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(flags & FLAG_CONS))
|
||||||
|
dp += len;
|
||||||
pc += asn1_op_lengths[op];
|
pc += asn1_op_lengths[op];
|
||||||
goto next_op;
|
goto next_op;
|
||||||
|
|
||||||
@ -434,6 +439,8 @@ next_op:
|
|||||||
else
|
else
|
||||||
act = machine[pc + 1];
|
act = machine[pc + 1];
|
||||||
ret = actions[act](context, hdr, 0, data + tdp, len);
|
ret = actions[act](context, hdr, 0, data + tdp, len);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
pc += asn1_op_lengths[op];
|
pc += asn1_op_lengths[op];
|
||||||
goto next_op;
|
goto next_op;
|
||||||
|
@ -116,14 +116,14 @@ int sprint_oid(const void *data, size_t datasize, char *buffer, size_t bufsize)
|
|||||||
int count;
|
int count;
|
||||||
|
|
||||||
if (v >= end)
|
if (v >= end)
|
||||||
return -EBADMSG;
|
goto bad;
|
||||||
|
|
||||||
n = *v++;
|
n = *v++;
|
||||||
ret = count = snprintf(buffer, bufsize, "%u.%u", n / 40, n % 40);
|
ret = count = snprintf(buffer, bufsize, "%u.%u", n / 40, n % 40);
|
||||||
|
if (count >= bufsize)
|
||||||
|
return -ENOBUFS;
|
||||||
buffer += count;
|
buffer += count;
|
||||||
bufsize -= count;
|
bufsize -= count;
|
||||||
if (bufsize == 0)
|
|
||||||
return -ENOBUFS;
|
|
||||||
|
|
||||||
while (v < end) {
|
while (v < end) {
|
||||||
num = 0;
|
num = 0;
|
||||||
@ -134,20 +134,24 @@ int sprint_oid(const void *data, size_t datasize, char *buffer, size_t bufsize)
|
|||||||
num = n & 0x7f;
|
num = n & 0x7f;
|
||||||
do {
|
do {
|
||||||
if (v >= end)
|
if (v >= end)
|
||||||
return -EBADMSG;
|
goto bad;
|
||||||
n = *v++;
|
n = *v++;
|
||||||
num <<= 7;
|
num <<= 7;
|
||||||
num |= n & 0x7f;
|
num |= n & 0x7f;
|
||||||
} while (n & 0x80);
|
} while (n & 0x80);
|
||||||
}
|
}
|
||||||
ret += count = snprintf(buffer, bufsize, ".%lu", num);
|
ret += count = snprintf(buffer, bufsize, ".%lu", num);
|
||||||
buffer += count;
|
if (count >= bufsize)
|
||||||
if (bufsize <= count)
|
|
||||||
return -ENOBUFS;
|
return -ENOBUFS;
|
||||||
|
buffer += count;
|
||||||
bufsize -= count;
|
bufsize -= count;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
bad:
|
||||||
|
snprintf(buffer, bufsize, "(bad)");
|
||||||
|
return -EBADMSG;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(sprint_oid);
|
EXPORT_SYMBOL_GPL(sprint_oid);
|
||||||
|
|
||||||
|
@ -833,7 +833,6 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
|
|||||||
|
|
||||||
key_check(keyring);
|
key_check(keyring);
|
||||||
|
|
||||||
key_ref = ERR_PTR(-EPERM);
|
|
||||||
if (!(flags & KEY_ALLOC_BYPASS_RESTRICTION))
|
if (!(flags & KEY_ALLOC_BYPASS_RESTRICTION))
|
||||||
restrict_link = keyring->restrict_link;
|
restrict_link = keyring->restrict_link;
|
||||||
|
|
||||||
|
@ -1588,9 +1588,8 @@ error_keyring:
|
|||||||
* The caller must have Setattr permission to change keyring restrictions.
|
* The caller must have Setattr permission to change keyring restrictions.
|
||||||
*
|
*
|
||||||
* The requested type name may be a NULL pointer to reject all attempts
|
* The requested type name may be a NULL pointer to reject all attempts
|
||||||
* to link to the keyring. If _type is non-NULL, _restriction can be
|
* to link to the keyring. In this case, _restriction must also be NULL.
|
||||||
* NULL or a pointer to a string describing the restriction. If _type is
|
* Otherwise, both _type and _restriction must be non-NULL.
|
||||||
* NULL, _restriction must also be NULL.
|
|
||||||
*
|
*
|
||||||
* Returns 0 if successful.
|
* Returns 0 if successful.
|
||||||
*/
|
*/
|
||||||
@ -1598,7 +1597,6 @@ long keyctl_restrict_keyring(key_serial_t id, const char __user *_type,
|
|||||||
const char __user *_restriction)
|
const char __user *_restriction)
|
||||||
{
|
{
|
||||||
key_ref_t key_ref;
|
key_ref_t key_ref;
|
||||||
bool link_reject = !_type;
|
|
||||||
char type[32];
|
char type[32];
|
||||||
char *restriction = NULL;
|
char *restriction = NULL;
|
||||||
long ret;
|
long ret;
|
||||||
@ -1607,31 +1605,29 @@ long keyctl_restrict_keyring(key_serial_t id, const char __user *_type,
|
|||||||
if (IS_ERR(key_ref))
|
if (IS_ERR(key_ref))
|
||||||
return PTR_ERR(key_ref);
|
return PTR_ERR(key_ref);
|
||||||
|
|
||||||
|
ret = -EINVAL;
|
||||||
if (_type) {
|
if (_type) {
|
||||||
|
if (!_restriction)
|
||||||
|
goto error;
|
||||||
|
|
||||||
ret = key_get_type_from_user(type, _type, sizeof(type));
|
ret = key_get_type_from_user(type, _type, sizeof(type));
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
|
||||||
|
|
||||||
if (_restriction) {
|
|
||||||
if (!_type) {
|
|
||||||
ret = -EINVAL;
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
restriction = strndup_user(_restriction, PAGE_SIZE);
|
restriction = strndup_user(_restriction, PAGE_SIZE);
|
||||||
if (IS_ERR(restriction)) {
|
if (IS_ERR(restriction)) {
|
||||||
ret = PTR_ERR(restriction);
|
ret = PTR_ERR(restriction);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (_restriction)
|
||||||
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = keyring_restrict(key_ref, link_reject ? NULL : type, restriction);
|
ret = keyring_restrict(key_ref, _type ? type : NULL, restriction);
|
||||||
kfree(restriction);
|
kfree(restriction);
|
||||||
|
|
||||||
error:
|
error:
|
||||||
key_ref_put(key_ref);
|
key_ref_put(key_ref);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -251,11 +251,12 @@ static int construct_key(struct key *key, const void *callout_info,
|
|||||||
* The keyring selected is returned with an extra reference upon it which the
|
* The keyring selected is returned with an extra reference upon it which the
|
||||||
* caller must release.
|
* caller must release.
|
||||||
*/
|
*/
|
||||||
static void construct_get_dest_keyring(struct key **_dest_keyring)
|
static int construct_get_dest_keyring(struct key **_dest_keyring)
|
||||||
{
|
{
|
||||||
struct request_key_auth *rka;
|
struct request_key_auth *rka;
|
||||||
const struct cred *cred = current_cred();
|
const struct cred *cred = current_cred();
|
||||||
struct key *dest_keyring = *_dest_keyring, *authkey;
|
struct key *dest_keyring = *_dest_keyring, *authkey;
|
||||||
|
int ret;
|
||||||
|
|
||||||
kenter("%p", dest_keyring);
|
kenter("%p", dest_keyring);
|
||||||
|
|
||||||
@ -264,6 +265,8 @@ static void construct_get_dest_keyring(struct key **_dest_keyring)
|
|||||||
/* the caller supplied one */
|
/* the caller supplied one */
|
||||||
key_get(dest_keyring);
|
key_get(dest_keyring);
|
||||||
} else {
|
} else {
|
||||||
|
bool do_perm_check = true;
|
||||||
|
|
||||||
/* use a default keyring; falling through the cases until we
|
/* use a default keyring; falling through the cases until we
|
||||||
* find one that we actually have */
|
* find one that we actually have */
|
||||||
switch (cred->jit_keyring) {
|
switch (cred->jit_keyring) {
|
||||||
@ -278,9 +281,11 @@ static void construct_get_dest_keyring(struct key **_dest_keyring)
|
|||||||
dest_keyring =
|
dest_keyring =
|
||||||
key_get(rka->dest_keyring);
|
key_get(rka->dest_keyring);
|
||||||
up_read(&authkey->sem);
|
up_read(&authkey->sem);
|
||||||
if (dest_keyring)
|
if (dest_keyring) {
|
||||||
|
do_perm_check = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
case KEY_REQKEY_DEFL_THREAD_KEYRING:
|
case KEY_REQKEY_DEFL_THREAD_KEYRING:
|
||||||
dest_keyring = key_get(cred->thread_keyring);
|
dest_keyring = key_get(cred->thread_keyring);
|
||||||
@ -314,11 +319,29 @@ static void construct_get_dest_keyring(struct key **_dest_keyring)
|
|||||||
default:
|
default:
|
||||||
BUG();
|
BUG();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Require Write permission on the keyring. This is essential
|
||||||
|
* because the default keyring may be the session keyring, and
|
||||||
|
* joining a keyring only requires Search permission.
|
||||||
|
*
|
||||||
|
* However, this check is skipped for the "requestor keyring" so
|
||||||
|
* that /sbin/request-key can itself use request_key() to add
|
||||||
|
* keys to the original requestor's destination keyring.
|
||||||
|
*/
|
||||||
|
if (dest_keyring && do_perm_check) {
|
||||||
|
ret = key_permission(make_key_ref(dest_keyring, 1),
|
||||||
|
KEY_NEED_WRITE);
|
||||||
|
if (ret) {
|
||||||
|
key_put(dest_keyring);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*_dest_keyring = dest_keyring;
|
*_dest_keyring = dest_keyring;
|
||||||
kleave(" [dk %d]", key_serial(dest_keyring));
|
kleave(" [dk %d]", key_serial(dest_keyring));
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -444,11 +467,15 @@ static struct key *construct_key_and_link(struct keyring_search_context *ctx,
|
|||||||
if (ctx->index_key.type == &key_type_keyring)
|
if (ctx->index_key.type == &key_type_keyring)
|
||||||
return ERR_PTR(-EPERM);
|
return ERR_PTR(-EPERM);
|
||||||
|
|
||||||
user = key_user_lookup(current_fsuid());
|
ret = construct_get_dest_keyring(&dest_keyring);
|
||||||
if (!user)
|
if (ret)
|
||||||
return ERR_PTR(-ENOMEM);
|
goto error;
|
||||||
|
|
||||||
construct_get_dest_keyring(&dest_keyring);
|
user = key_user_lookup(current_fsuid());
|
||||||
|
if (!user) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
goto error_put_dest_keyring;
|
||||||
|
}
|
||||||
|
|
||||||
ret = construct_alloc_key(ctx, dest_keyring, flags, user, &key);
|
ret = construct_alloc_key(ctx, dest_keyring, flags, user, &key);
|
||||||
key_user_put(user);
|
key_user_put(user);
|
||||||
@ -463,7 +490,7 @@ static struct key *construct_key_and_link(struct keyring_search_context *ctx,
|
|||||||
} else if (ret == -EINPROGRESS) {
|
} else if (ret == -EINPROGRESS) {
|
||||||
ret = 0;
|
ret = 0;
|
||||||
} else {
|
} else {
|
||||||
goto couldnt_alloc_key;
|
goto error_put_dest_keyring;
|
||||||
}
|
}
|
||||||
|
|
||||||
key_put(dest_keyring);
|
key_put(dest_keyring);
|
||||||
@ -473,8 +500,9 @@ static struct key *construct_key_and_link(struct keyring_search_context *ctx,
|
|||||||
construction_failed:
|
construction_failed:
|
||||||
key_negate_and_link(key, key_negative_timeout, NULL, NULL);
|
key_negate_and_link(key, key_negative_timeout, NULL, NULL);
|
||||||
key_put(key);
|
key_put(key);
|
||||||
couldnt_alloc_key:
|
error_put_dest_keyring:
|
||||||
key_put(dest_keyring);
|
key_put(dest_keyring);
|
||||||
|
error:
|
||||||
kleave(" = %d", ret);
|
kleave(" = %d", ret);
|
||||||
return ERR_PTR(ret);
|
return ERR_PTR(ret);
|
||||||
}
|
}
|
||||||
@ -546,9 +574,7 @@ struct key *request_key_and_link(struct key_type *type,
|
|||||||
if (!IS_ERR(key_ref)) {
|
if (!IS_ERR(key_ref)) {
|
||||||
key = key_ref_to_ptr(key_ref);
|
key = key_ref_to_ptr(key_ref);
|
||||||
if (dest_keyring) {
|
if (dest_keyring) {
|
||||||
construct_get_dest_keyring(&dest_keyring);
|
|
||||||
ret = key_link(dest_keyring, key);
|
ret = key_link(dest_keyring, key);
|
||||||
key_put(dest_keyring);
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
key_put(key);
|
key_put(key);
|
||||||
key = ERR_PTR(ret);
|
key = ERR_PTR(ret);
|
||||||
|
Loading…
Reference in New Issue
Block a user