1
0
Fork 0

KEYS: Merge the type-specific data with the payload data

Merge the type-specific data with the payload data into one four-word chunk
as it seems pointless to keep them separate.

Use user_key_payload() for accessing the payloads of overloaded
user-defined keys.

Signed-off-by: David Howells <dhowells@redhat.com>
cc: linux-cifs@vger.kernel.org
cc: ecryptfs@vger.kernel.org
cc: linux-ext4@vger.kernel.org
cc: linux-f2fs-devel@lists.sourceforge.net
cc: linux-nfs@vger.kernel.org
cc: ceph-devel@vger.kernel.org
cc: linux-ima-devel@lists.sourceforge.net
steinar/wifi_calib_4_9_kernel
David Howells 2015-10-21 14:04:48 +01:00
parent 4adc605edc
commit 146aa8b145
49 changed files with 286 additions and 230 deletions

View File

@ -186,7 +186,7 @@ and looks like the following:
const struct public_key_signature *sig); const struct public_key_signature *sig);
}; };
Asymmetric keys point to this with their type_data[0] member. Asymmetric keys point to this with their payload[asym_subtype] member.
The owner and name fields should be set to the owning module and the name of The owner and name fields should be set to the owning module and the name of
the subtype. Currently, the name is only used for print statements. the subtype. Currently, the name is only used for print statements.
@ -269,8 +269,7 @@ mandatory:
struct key_preparsed_payload { struct key_preparsed_payload {
char *description; char *description;
void *type_data[2]; void *payload[4];
void *payload;
const void *data; const void *data;
size_t datalen; size_t datalen;
size_t quotalen; size_t quotalen;
@ -283,16 +282,18 @@ mandatory:
not theirs. not theirs.
If the parser is happy with the blob, it should propose a description for If the parser is happy with the blob, it should propose a description for
the key and attach it to ->description, ->type_data[0] should be set to the key and attach it to ->description, ->payload[asym_subtype] should be
point to the subtype to be used, ->payload should be set to point to the set to point to the subtype to be used, ->payload[asym_crypto] should be
initialised data for that subtype, ->type_data[1] should point to a hex set to point to the initialised data for that subtype,
fingerprint and quotalen should be updated to indicate how much quota this ->payload[asym_key_ids] should point to one or more hex fingerprints and
key should account for. quotalen should be updated to indicate how much quota this key should
account for.
When clearing up, the data attached to ->type_data[1] and ->description When clearing up, the data attached to ->payload[asym_key_ids] and
will be kfree()'d and the data attached to ->payload will be passed to the ->description will be kfree()'d and the data attached to
subtype's ->destroy() method to be disposed of. A module reference for ->payload[asm_crypto] will be passed to the subtype's ->destroy() method
the subtype pointed to by ->type_data[0] will be put. to be disposed of. A module reference for the subtype pointed to by
->payload[asym_subtype] will be put.
If the data format is not recognised, -EBADMSG should be returned. If it If the data format is not recognised, -EBADMSG should be returned. If it

View File

@ -1049,12 +1049,12 @@ search a specific keyring, so using keyrings in this way is of limited utility.
NOTES ON ACCESSING PAYLOAD CONTENTS NOTES ON ACCESSING PAYLOAD CONTENTS
=================================== ===================================
The simplest payload is just a number in key->payload.value. In this case, The simplest payload is just data stored in key->payload directly. In this
there's no need to indulge in RCU or locking when accessing the payload. case, there's no need to indulge in RCU or locking when accessing the payload.
More complex payload contents must be allocated and a pointer to them set in More complex payload contents must be allocated and pointers to them set in the
key->payload.data. One of the following ways must be selected to access the key->payload.data[] array. One of the following ways must be selected to
data: access the data:
(1) Unmodifiable key type. (1) Unmodifiable key type.
@ -1092,6 +1092,13 @@ data:
the payload. key->datalen cannot be relied upon to be consistent with the the payload. key->datalen cannot be relied upon to be consistent with the
payload just dereferenced if the key's semaphore is not held. payload just dereferenced if the key's semaphore is not held.
Note that key->payload.data[0] has a shadow that is marked for __rcu
usage. This is called key->payload.rcu_data0. The following accessors
wrap the RCU calls to this element:
rcu_assign_keypointer(struct key *key, void *data);
void *rcu_dereference_key(struct key *key);
=================== ===================
DEFINING A KEY TYPE DEFINING A KEY TYPE
@ -1143,8 +1150,7 @@ The structure has a number of fields, some of which are mandatory:
struct key_preparsed_payload { struct key_preparsed_payload {
char *description; char *description;
void *type_data[2]; union key_payload payload;
void *payload;
const void *data; const void *data;
size_t datalen; size_t datalen;
size_t quotalen; size_t quotalen;
@ -1160,10 +1166,9 @@ The structure has a number of fields, some of which are mandatory:
attached as a string to the description field. This will be used for the attached as a string to the description field. This will be used for the
key description if the caller of add_key() passes NULL or "". key description if the caller of add_key() passes NULL or "".
The method can attach anything it likes to type_data[] and payload. These The method can attach anything it likes to payload. This is merely passed
are merely passed along to the instantiate() or update() operations. If along to the instantiate() or update() operations. If set, the expiry
set, the expiry time will be applied to the key if it is instantiated from time will be applied to the key if it is instantiated from this data.
this data.
The method should return 0 if successful or a negative error code The method should return 0 if successful or a negative error code
otherwise. otherwise.
@ -1172,11 +1177,10 @@ The structure has a number of fields, some of which are mandatory:
(*) void (*free_preparse)(struct key_preparsed_payload *prep); (*) void (*free_preparse)(struct key_preparsed_payload *prep);
This method is only required if the preparse() method is provided, This method is only required if the preparse() method is provided,
otherwise it is unused. It cleans up anything attached to the otherwise it is unused. It cleans up anything attached to the description
description, type_data and payload fields of the key_preparsed_payload and payload fields of the key_preparsed_payload struct as filled in by the
struct as filled in by the preparse() method. It will always be called preparse() method. It will always be called after preparse() returns
after preparse() returns successfully, even if instantiate() or update() successfully, even if instantiate() or update() succeed.
succeed.
(*) int (*instantiate)(struct key *key, struct key_preparsed_payload *prep); (*) int (*instantiate)(struct key *key, struct key_preparsed_payload *prep);
@ -1197,6 +1201,11 @@ The structure has a number of fields, some of which are mandatory:
It is safe to sleep in this method. It is safe to sleep in this method.
generic_key_instantiate() is provided to simply copy the data from
prep->payload.data[] to key->payload.data[], with RCU-safe assignment on
the first element. It will then clear prep->payload.data[] so that the
free_preparse method doesn't release the data.
(*) int (*update)(struct key *key, const void *data, size_t datalen); (*) int (*update)(struct key *key, const void *data, size_t datalen);

View File

@ -14,8 +14,3 @@ extern struct asymmetric_key_id *asymmetric_key_hex_to_key_id(const char *id);
extern int __asymmetric_key_hex_to_key_id(const char *id, extern int __asymmetric_key_hex_to_key_id(const char *id,
struct asymmetric_key_id *match_id, struct asymmetric_key_id *match_id,
size_t hexlen); size_t hexlen);
static inline
const struct asymmetric_key_ids *asymmetric_key_ids(const struct key *key)
{
return key->type_data.p[1];
}

View File

@ -307,25 +307,34 @@ static int asymmetric_key_preparse(struct key_preparsed_payload *prep)
} }
/* /*
* Clean up the preparse data * Clean up the key ID list
*/ */
static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep) static void asymmetric_key_free_kids(struct asymmetric_key_ids *kids)
{ {
struct asymmetric_key_subtype *subtype = prep->type_data[0];
struct asymmetric_key_ids *kids = prep->type_data[1];
int i; int i;
pr_devel("==>%s()\n", __func__);
if (subtype) {
subtype->destroy(prep->payload[0]);
module_put(subtype->owner);
}
if (kids) { if (kids) {
for (i = 0; i < ARRAY_SIZE(kids->id); i++) for (i = 0; i < ARRAY_SIZE(kids->id); i++)
kfree(kids->id[i]); kfree(kids->id[i]);
kfree(kids); kfree(kids);
} }
}
/*
* Clean up the preparse data
*/
static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep)
{
struct asymmetric_key_subtype *subtype = prep->payload.data[asym_subtype];
struct asymmetric_key_ids *kids = prep->payload.data[asym_key_ids];
pr_devel("==>%s()\n", __func__);
if (subtype) {
subtype->destroy(prep->payload.data[asym_crypto]);
module_put(subtype->owner);
}
asymmetric_key_free_kids(kids);
kfree(prep->description); kfree(prep->description);
} }
@ -335,20 +344,19 @@ static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep)
static void asymmetric_key_destroy(struct key *key) static void asymmetric_key_destroy(struct key *key)
{ {
struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key); struct asymmetric_key_subtype *subtype = asymmetric_key_subtype(key);
struct asymmetric_key_ids *kids = key->type_data.p[1]; struct asymmetric_key_ids *kids = key->payload.data[asym_key_ids];
void *data = key->payload.data[asym_crypto];
key->payload.data[asym_crypto] = NULL;
key->payload.data[asym_subtype] = NULL;
key->payload.data[asym_key_ids] = NULL;
if (subtype) { if (subtype) {
subtype->destroy(key->payload.data); subtype->destroy(data);
module_put(subtype->owner); module_put(subtype->owner);
key->type_data.p[0] = NULL;
} }
if (kids) { asymmetric_key_free_kids(kids);
kfree(kids->id[0]);
kfree(kids->id[1]);
kfree(kids);
key->type_data.p[1] = NULL;
}
} }
struct key_type key_type_asymmetric = { struct key_type key_type_asymmetric = {

View File

@ -49,7 +49,7 @@ EXPORT_SYMBOL_GPL(pkey_id_type_name);
static void public_key_describe(const struct key *asymmetric_key, static void public_key_describe(const struct key *asymmetric_key,
struct seq_file *m) struct seq_file *m)
{ {
struct public_key *key = asymmetric_key->payload.data; struct public_key *key = asymmetric_key->payload.data[asym_crypto];
if (key) if (key)
seq_printf(m, "%s.%s", seq_printf(m, "%s.%s",
@ -112,7 +112,7 @@ EXPORT_SYMBOL_GPL(public_key_verify_signature);
static int public_key_verify_signature_2(const struct key *key, static int public_key_verify_signature_2(const struct key *key,
const struct public_key_signature *sig) const struct public_key_signature *sig)
{ {
const struct public_key *pk = key->payload.data; const struct public_key *pk = key->payload.data[asym_crypto];
return public_key_verify_signature(pk, sig); return public_key_verify_signature(pk, sig);
} }

View File

@ -37,7 +37,7 @@ int verify_signature(const struct key *key,
return -EINVAL; return -EINVAL;
subtype = asymmetric_key_subtype(key); subtype = asymmetric_key_subtype(key);
if (!subtype || if (!subtype ||
!key->payload.data) !key->payload.data[0])
return -EINVAL; return -EINVAL;
if (!subtype->verify_signature) if (!subtype->verify_signature)
return -ENOTSUPP; return -ENOTSUPP;

View File

@ -11,6 +11,7 @@
#include <linux/time.h> #include <linux/time.h>
#include <crypto/public_key.h> #include <crypto/public_key.h>
#include <keys/asymmetric-type.h>
struct x509_certificate { struct x509_certificate {
struct x509_certificate *next; struct x509_certificate *next;

View File

@ -266,7 +266,8 @@ static int x509_validate_trust(struct x509_certificate *cert,
if (!IS_ERR(key)) { if (!IS_ERR(key)) {
if (!use_builtin_keys if (!use_builtin_keys
|| test_bit(KEY_FLAG_BUILTIN, &key->flags)) || test_bit(KEY_FLAG_BUILTIN, &key->flags))
ret = x509_check_signature(key->payload.data, cert); ret = x509_check_signature(key->payload.data[asym_crypto],
cert);
key_put(key); key_put(key);
} }
return ret; return ret;
@ -352,9 +353,9 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
/* We're pinning the module by being linked against it */ /* We're pinning the module by being linked against it */
__module_get(public_key_subtype.owner); __module_get(public_key_subtype.owner);
prep->type_data[0] = &public_key_subtype; prep->payload.data[asym_subtype] = &public_key_subtype;
prep->type_data[1] = kids; prep->payload.data[asym_key_ids] = kids;
prep->payload[0] = cert->pub; prep->payload.data[asym_crypto] = cert->pub;
prep->description = desc; prep->description = desc;
prep->quotalen = 100; prep->quotalen = 100;

View File

@ -42,7 +42,7 @@ cifs_spnego_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
goto error; goto error;
/* attach the data */ /* attach the data */
key->payload.data = payload; key->payload.data[0] = payload;
ret = 0; ret = 0;
error: error:
@ -52,7 +52,7 @@ error:
static void static void
cifs_spnego_key_destroy(struct key *key) cifs_spnego_key_destroy(struct key *key)
{ {
kfree(key->payload.data); kfree(key->payload.data[0]);
} }
@ -167,7 +167,7 @@ cifs_get_spnego_key(struct cifs_ses *sesInfo)
#ifdef CONFIG_CIFS_DEBUG2 #ifdef CONFIG_CIFS_DEBUG2
if (cifsFYI && !IS_ERR(spnego_key)) { if (cifsFYI && !IS_ERR(spnego_key)) {
struct cifs_spnego_msg *msg = spnego_key->payload.data; struct cifs_spnego_msg *msg = spnego_key->payload.data[0];
cifs_dump_mem("SPNEGO reply blob:", msg->data, min(1024U, cifs_dump_mem("SPNEGO reply blob:", msg->data, min(1024U,
msg->secblob_len + msg->sesskey_len)); msg->secblob_len + msg->sesskey_len));
} }

View File

@ -58,16 +58,15 @@ cifs_idmap_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
* dereference payload.data! * dereference payload.data!
*/ */
if (prep->datalen <= sizeof(key->payload)) { if (prep->datalen <= sizeof(key->payload)) {
key->payload.value = 0; key->payload.data[0] = NULL;
memcpy(&key->payload.value, prep->data, prep->datalen); memcpy(&key->payload, prep->data, prep->datalen);
key->datalen = prep->datalen; } else {
return 0; payload = kmemdup(prep->data, prep->datalen, GFP_KERNEL);
if (!payload)
return -ENOMEM;
key->payload.data[0] = payload;
} }
payload = kmemdup(prep->data, prep->datalen, GFP_KERNEL);
if (!payload)
return -ENOMEM;
key->payload.data = payload;
key->datalen = prep->datalen; key->datalen = prep->datalen;
return 0; return 0;
} }
@ -76,7 +75,7 @@ static inline void
cifs_idmap_key_destroy(struct key *key) cifs_idmap_key_destroy(struct key *key)
{ {
if (key->datalen > sizeof(key->payload)) if (key->datalen > sizeof(key->payload))
kfree(key->payload.data); kfree(key->payload.data[0]);
} }
static struct key_type cifs_idmap_key_type = { static struct key_type cifs_idmap_key_type = {
@ -233,8 +232,8 @@ id_to_sid(unsigned int cid, uint sidtype, struct cifs_sid *ssid)
* it could be. * it could be.
*/ */
ksid = sidkey->datalen <= sizeof(sidkey->payload) ? ksid = sidkey->datalen <= sizeof(sidkey->payload) ?
(struct cifs_sid *)&sidkey->payload.value : (struct cifs_sid *)&sidkey->payload :
(struct cifs_sid *)sidkey->payload.data; (struct cifs_sid *)sidkey->payload.data[0];
ksid_size = CIFS_SID_BASE_SIZE + (ksid->num_subauth * sizeof(__le32)); ksid_size = CIFS_SID_BASE_SIZE + (ksid->num_subauth * sizeof(__le32));
if (ksid_size > sidkey->datalen) { if (ksid_size > sidkey->datalen) {
@ -307,14 +306,14 @@ sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
if (sidtype == SIDOWNER) { if (sidtype == SIDOWNER) {
kuid_t uid; kuid_t uid;
uid_t id; uid_t id;
memcpy(&id, &sidkey->payload.value, sizeof(uid_t)); memcpy(&id, &sidkey->payload.data[0], sizeof(uid_t));
uid = make_kuid(&init_user_ns, id); uid = make_kuid(&init_user_ns, id);
if (uid_valid(uid)) if (uid_valid(uid))
fuid = uid; fuid = uid;
} else { } else {
kgid_t gid; kgid_t gid;
gid_t id; gid_t id;
memcpy(&id, &sidkey->payload.value, sizeof(gid_t)); memcpy(&id, &sidkey->payload.data[0], sizeof(gid_t));
gid = make_kgid(&init_user_ns, id); gid = make_kgid(&init_user_ns, id);
if (gid_valid(gid)) if (gid_valid(gid))
fgid = gid; fgid = gid;

View File

@ -2325,13 +2325,14 @@ static int
cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses) cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
{ {
int rc = 0; int rc = 0;
char *desc, *delim, *payload; const char *delim, *payload;
char *desc;
ssize_t len; ssize_t len;
struct key *key; struct key *key;
struct TCP_Server_Info *server = ses->server; struct TCP_Server_Info *server = ses->server;
struct sockaddr_in *sa; struct sockaddr_in *sa;
struct sockaddr_in6 *sa6; struct sockaddr_in6 *sa6;
struct user_key_payload *upayload; const struct user_key_payload *upayload;
desc = kmalloc(CIFSCREDS_DESC_SIZE, GFP_KERNEL); desc = kmalloc(CIFSCREDS_DESC_SIZE, GFP_KERNEL);
if (!desc) if (!desc)
@ -2374,14 +2375,14 @@ cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
} }
down_read(&key->sem); down_read(&key->sem);
upayload = key->payload.data; upayload = user_key_payload(key);
if (IS_ERR_OR_NULL(upayload)) { if (IS_ERR_OR_NULL(upayload)) {
rc = upayload ? PTR_ERR(upayload) : -EINVAL; rc = upayload ? PTR_ERR(upayload) : -EINVAL;
goto out_key_put; goto out_key_put;
} }
/* find first : in payload */ /* find first : in payload */
payload = (char *)upayload->data; payload = upayload->data;
delim = strnchr(payload, upayload->datalen, ':'); delim = strnchr(payload, upayload->datalen, ':');
cifs_dbg(FYI, "payload=%s\n", payload); cifs_dbg(FYI, "payload=%s\n", payload);
if (!delim) { if (!delim) {

View File

@ -988,7 +988,7 @@ sess_auth_kerberos(struct sess_data *sess_data)
goto out; goto out;
} }
msg = spnego_key->payload.data; msg = spnego_key->payload.data[0];
/* /*
* check version field to make sure that cifs.upcall is * check version field to make sure that cifs.upcall is
* sending us a response in an expected form * sending us a response in an expected form

View File

@ -660,7 +660,7 @@ ssetup_ntlmssp_authenticate:
goto ssetup_exit; goto ssetup_exit;
} }
msg = spnego_key->payload.data; msg = spnego_key->payload.data[0];
/* /*
* check version field to make sure that cifs.upcall is * check version field to make sure that cifs.upcall is
* sending us a response in an expected form * sending us a response in an expected form

View File

@ -86,7 +86,7 @@ ecryptfs_get_encrypted_key_payload_data(struct key *key)
{ {
if (key->type == &key_type_encrypted) if (key->type == &key_type_encrypted)
return (struct ecryptfs_auth_tok *) return (struct ecryptfs_auth_tok *)
(&((struct encrypted_key_payload *)key->payload.data)->payload_data); (&((struct encrypted_key_payload *)key->payload.data[0])->payload_data);
else else
return NULL; return NULL;
} }
@ -117,8 +117,7 @@ ecryptfs_get_key_payload_data(struct key *key)
auth_tok = ecryptfs_get_encrypted_key_payload_data(key); auth_tok = ecryptfs_get_encrypted_key_payload_data(key);
if (!auth_tok) if (!auth_tok)
return (struct ecryptfs_auth_tok *) return (struct ecryptfs_auth_tok *)user_key_payload(key)->data;
(((struct user_key_payload *)key->payload.data)->data);
else else
return auth_tok; return auth_tok;
} }

View File

@ -121,7 +121,7 @@ int _ext4_get_encryption_info(struct inode *inode)
struct key *keyring_key = NULL; struct key *keyring_key = NULL;
struct ext4_encryption_key *master_key; struct ext4_encryption_key *master_key;
struct ext4_encryption_context ctx; struct ext4_encryption_context ctx;
struct user_key_payload *ukp; const struct user_key_payload *ukp;
struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
struct crypto_ablkcipher *ctfm; struct crypto_ablkcipher *ctfm;
const char *cipher_str; const char *cipher_str;
@ -209,7 +209,7 @@ retry:
} }
crypt_info->ci_keyring_key = keyring_key; crypt_info->ci_keyring_key = keyring_key;
BUG_ON(keyring_key->type != &key_type_logon); BUG_ON(keyring_key->type != &key_type_logon);
ukp = ((struct user_key_payload *)keyring_key->payload.data); ukp = user_key_payload(keyring_key);
if (ukp->datalen != sizeof(struct ext4_encryption_key)) { if (ukp->datalen != sizeof(struct ext4_encryption_key)) {
res = -EINVAL; res = -EINVAL;
goto out; goto out;

View File

@ -122,7 +122,7 @@ int _f2fs_get_encryption_info(struct inode *inode)
struct key *keyring_key = NULL; struct key *keyring_key = NULL;
struct f2fs_encryption_key *master_key; struct f2fs_encryption_key *master_key;
struct f2fs_encryption_context ctx; struct f2fs_encryption_context ctx;
struct user_key_payload *ukp; const struct user_key_payload *ukp;
struct crypto_ablkcipher *ctfm; struct crypto_ablkcipher *ctfm;
const char *cipher_str; const char *cipher_str;
char raw_key[F2FS_MAX_KEY_SIZE]; char raw_key[F2FS_MAX_KEY_SIZE];
@ -199,7 +199,7 @@ retry:
} }
crypt_info->ci_keyring_key = keyring_key; crypt_info->ci_keyring_key = keyring_key;
BUG_ON(keyring_key->type != &key_type_logon); BUG_ON(keyring_key->type != &key_type_logon);
ukp = ((struct user_key_payload *)keyring_key->payload.data); ukp = user_key_payload(keyring_key);
if (ukp->datalen != sizeof(struct f2fs_encryption_key)) { if (ukp->datalen != sizeof(struct f2fs_encryption_key)) {
res = -EINVAL; res = -EINVAL;
goto out; goto out;

View File

@ -316,7 +316,7 @@ static const struct seq_operations fscache_objlist_ops = {
static void fscache_objlist_config(struct fscache_objlist_data *data) static void fscache_objlist_config(struct fscache_objlist_data *data)
{ {
#ifdef CONFIG_KEYS #ifdef CONFIG_KEYS
struct user_key_payload *confkey; const struct user_key_payload *confkey;
unsigned long config; unsigned long config;
struct key *key; struct key *key;
const char *buf; const char *buf;
@ -329,7 +329,7 @@ static void fscache_objlist_config(struct fscache_objlist_data *data)
config = 0; config = 0;
rcu_read_lock(); rcu_read_lock();
confkey = key->payload.data; confkey = user_key_payload(key);
buf = confkey->data; buf = confkey->data;
for (len = confkey->datalen - 1; len >= 0; len--) { for (len = confkey->datalen - 1; len >= 0; len--) {

View File

@ -297,7 +297,7 @@ static ssize_t nfs_idmap_get_key(const char *name, size_t namelen,
{ {
const struct cred *saved_cred; const struct cred *saved_cred;
struct key *rkey; struct key *rkey;
struct user_key_payload *payload; const struct user_key_payload *payload;
ssize_t ret; ssize_t ret;
saved_cred = override_creds(id_resolver_cache); saved_cred = override_creds(id_resolver_cache);
@ -316,7 +316,7 @@ static ssize_t nfs_idmap_get_key(const char *name, size_t namelen,
if (ret < 0) if (ret < 0)
goto out_up; goto out_up;
payload = rcu_dereference(rkey->payload.rcudata); payload = user_key_payload(rkey);
if (IS_ERR_OR_NULL(payload)) { if (IS_ERR_OR_NULL(payload)) {
ret = PTR_ERR(payload); ret = PTR_ERR(payload);
goto out_up; goto out_up;

View File

@ -15,7 +15,6 @@
#define _LINUX_PUBLIC_KEY_H #define _LINUX_PUBLIC_KEY_H
#include <linux/mpi.h> #include <linux/mpi.h>
#include <keys/asymmetric-type.h>
#include <crypto/hash_info.h> #include <crypto/hash_info.h>
enum pkey_algo { enum pkey_algo {

View File

@ -49,7 +49,7 @@ struct asymmetric_key_subtype {
static inline static inline
struct asymmetric_key_subtype *asymmetric_key_subtype(const struct key *key) struct asymmetric_key_subtype *asymmetric_key_subtype(const struct key *key)
{ {
return key->type_data.p[0]; return key->payload.data[asym_subtype];
} }
#endif /* _KEYS_ASYMMETRIC_SUBTYPE_H */ #endif /* _KEYS_ASYMMETRIC_SUBTYPE_H */

View File

@ -18,6 +18,16 @@
extern struct key_type key_type_asymmetric; extern struct key_type key_type_asymmetric;
/*
* The key payload is four words. The asymmetric-type key uses them as
* follows:
*/
enum asymmetric_payload_bits {
asym_crypto,
asym_subtype,
asym_key_ids,
};
/* /*
* Identifiers for an asymmetric key ID. We have three ways of looking up a * Identifiers for an asymmetric key ID. We have three ways of looking up a
* key derived from an X.509 certificate: * key derived from an X.509 certificate:
@ -58,6 +68,11 @@ extern struct asymmetric_key_id *asymmetric_key_generate_id(const void *val_1,
size_t len_1, size_t len_1,
const void *val_2, const void *val_2,
size_t len_2); size_t len_2);
static inline
const struct asymmetric_key_ids *asymmetric_key_ids(const struct key *key)
{
return key->payload.data[asym_key_ids];
}
/* /*
* The payload is at the discretion of the subtype. * The payload is at the discretion of the subtype.

View File

@ -15,6 +15,8 @@
#include <linux/key.h> #include <linux/key.h>
#include <linux/rcupdate.h> #include <linux/rcupdate.h>
#ifdef CONFIG_KEYS
/*****************************************************************************/ /*****************************************************************************/
/* /*
* the payload for a key of type "user" or "logon" * the payload for a key of type "user" or "logon"
@ -46,5 +48,11 @@ extern void user_describe(const struct key *user, struct seq_file *m);
extern long user_read(const struct key *key, extern long user_read(const struct key *key,
char __user *buffer, size_t buflen); char __user *buffer, size_t buflen);
static inline const struct user_key_payload *user_key_payload(const struct key *key)
{
return (struct user_key_payload *)rcu_dereference_key(key);
}
#endif /* CONFIG_KEYS */
#endif /* _KEYS_USER_TYPE_H */ #endif /* _KEYS_USER_TYPE_H */

View File

@ -40,8 +40,7 @@ struct key_construction {
*/ */
struct key_preparsed_payload { struct key_preparsed_payload {
char *description; /* Proposed key description (or NULL) */ char *description; /* Proposed key description (or NULL) */
void *type_data[2]; /* Private key-type data */ union key_payload payload; /* Proposed payload */
void *payload[2]; /* Proposed payload */
const void *data; /* Raw data */ const void *data; /* Raw data */
size_t datalen; /* Raw datalen */ size_t datalen; /* Raw datalen */
size_t quotalen; /* Quota length for proposed payload */ size_t quotalen; /* Quota length for proposed payload */

View File

@ -89,6 +89,11 @@ struct keyring_index_key {
size_t desc_len; size_t desc_len;
}; };
union key_payload {
void __rcu *rcu_data0;
void *data[4];
};
/*****************************************************************************/ /*****************************************************************************/
/* /*
* key reference with possession attribute handling * key reference with possession attribute handling
@ -186,28 +191,18 @@ struct key {
}; };
}; };
/* type specific data
* - this is used by the keyring type to index the name
*/
union {
struct list_head link;
unsigned long x[2];
void *p[2];
int reject_error;
} type_data;
/* key data /* key data
* - this is used to hold the data actually used in cryptography or * - this is used to hold the data actually used in cryptography or
* whatever * whatever
*/ */
union { union {
union { union key_payload payload;
unsigned long value; struct {
void __rcu *rcudata; /* Keyring bits */
void *data; struct list_head name_link;
void *data2[2]; struct assoc_array keys;
} payload; };
struct assoc_array keys; int reject_error;
}; };
}; };
@ -336,12 +331,12 @@ static inline bool key_is_instantiated(const struct key *key)
} }
#define rcu_dereference_key(KEY) \ #define rcu_dereference_key(KEY) \
(rcu_dereference_protected((KEY)->payload.rcudata, \ (rcu_dereference_protected((KEY)->payload.rcu_data0, \
rwsem_is_locked(&((struct key *)(KEY))->sem))) rwsem_is_locked(&((struct key *)(KEY))->sem)))
#define rcu_assign_keypointer(KEY, PAYLOAD) \ #define rcu_assign_keypointer(KEY, PAYLOAD) \
do { \ do { \
rcu_assign_pointer((KEY)->payload.rcudata, (PAYLOAD)); \ rcu_assign_pointer((KEY)->payload.rcu_data0, (PAYLOAD)); \
} while (0) } while (0)
#ifdef CONFIG_SYSCTL #ifdef CONFIG_SYSCTL

View File

@ -10,6 +10,7 @@
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/errno.h>
#include <keys/system_keyring.h> #include <keys/system_keyring.h>
#include <crypto/public_key.h> #include <crypto/public_key.h>
#include "module-internal.h" #include "module-internal.h"

View File

@ -79,12 +79,13 @@ static int digsig_verify_rsa(struct key *key,
unsigned char *out1 = NULL; unsigned char *out1 = NULL;
const char *m; const char *m;
MPI in = NULL, res = NULL, pkey[2]; MPI in = NULL, res = NULL, pkey[2];
uint8_t *p, *datap, *endp; uint8_t *p, *datap;
struct user_key_payload *ukp; const uint8_t *endp;
const struct user_key_payload *ukp;
struct pubkey_hdr *pkh; struct pubkey_hdr *pkh;
down_read(&key->sem); down_read(&key->sem);
ukp = key->payload.data; ukp = user_key_payload(key);
if (ukp->datalen < sizeof(*pkh)) if (ukp->datalen < sizeof(*pkh))
goto err1; goto err1;

View File

@ -318,7 +318,7 @@ static int get_secret(struct ceph_crypto_key *dst, const char *name) {
goto out; goto out;
} }
ckey = ukey->payload.data; ckey = ukey->payload.data[0];
err = ceph_crypto_key_clone(dst, ckey); err = ceph_crypto_key_clone(dst, ckey);
if (err) if (err)
goto out_key; goto out_key;

View File

@ -537,7 +537,7 @@ static int ceph_key_preparse(struct key_preparsed_payload *prep)
if (ret < 0) if (ret < 0)
goto err_ckey; goto err_ckey;
prep->payload[0] = ckey; prep->payload.data[0] = ckey;
prep->quotalen = datalen; prep->quotalen = datalen;
return 0; return 0;
@ -549,14 +549,14 @@ err:
static void ceph_key_free_preparse(struct key_preparsed_payload *prep) static void ceph_key_free_preparse(struct key_preparsed_payload *prep)
{ {
struct ceph_crypto_key *ckey = prep->payload[0]; struct ceph_crypto_key *ckey = prep->payload.data[0];
ceph_crypto_key_destroy(ckey); ceph_crypto_key_destroy(ckey);
kfree(ckey); kfree(ckey);
} }
static void ceph_key_destroy(struct key *key) static void ceph_key_destroy(struct key *key)
{ {
struct ceph_crypto_key *ckey = key->payload.data; struct ceph_crypto_key *ckey = key->payload.data[0];
ceph_crypto_key_destroy(ckey); ceph_crypto_key_destroy(ckey);
kfree(ckey); kfree(ckey);

View File

@ -122,7 +122,7 @@ dns_resolver_preparse(struct key_preparsed_payload *prep)
goto bad_option_value; goto bad_option_value;
kdebug("dns error no. = %lu", derrno); kdebug("dns error no. = %lu", derrno);
prep->type_data[0] = ERR_PTR(-derrno); prep->payload.data[dns_key_error] = ERR_PTR(-derrno);
continue; continue;
} }
@ -137,8 +137,8 @@ dns_resolver_preparse(struct key_preparsed_payload *prep)
/* don't cache the result if we're caching an error saying there's no /* don't cache the result if we're caching an error saying there's no
* result */ * result */
if (prep->type_data[0]) { if (prep->payload.data[dns_key_error]) {
kleave(" = 0 [h_error %ld]", PTR_ERR(prep->type_data[0])); kleave(" = 0 [h_error %ld]", PTR_ERR(prep->payload.data[dns_key_error]));
return 0; return 0;
} }
@ -155,7 +155,7 @@ dns_resolver_preparse(struct key_preparsed_payload *prep)
memcpy(upayload->data, data, result_len); memcpy(upayload->data, data, result_len);
upayload->data[result_len] = '\0'; upayload->data[result_len] = '\0';
prep->payload[0] = upayload; prep->payload.data[dns_key_data] = upayload;
kleave(" = 0"); kleave(" = 0");
return 0; return 0;
} }
@ -167,7 +167,7 @@ static void dns_resolver_free_preparse(struct key_preparsed_payload *prep)
{ {
pr_devel("==>%s()\n", __func__); pr_devel("==>%s()\n", __func__);
kfree(prep->payload[0]); kfree(prep->payload.data[dns_key_data]);
} }
/* /*
@ -223,10 +223,10 @@ static int dns_resolver_match_preparse(struct key_match_data *match_data)
*/ */
static void dns_resolver_describe(const struct key *key, struct seq_file *m) static void dns_resolver_describe(const struct key *key, struct seq_file *m)
{ {
int err = key->type_data.x[0];
seq_puts(m, key->description); seq_puts(m, key->description);
if (key_is_instantiated(key)) { if (key_is_instantiated(key)) {
int err = PTR_ERR(key->payload.data[dns_key_error]);
if (err) if (err)
seq_printf(m, ": %d", err); seq_printf(m, ": %d", err);
else else
@ -241,8 +241,10 @@ static void dns_resolver_describe(const struct key *key, struct seq_file *m)
static long dns_resolver_read(const struct key *key, static long dns_resolver_read(const struct key *key,
char __user *buffer, size_t buflen) char __user *buffer, size_t buflen)
{ {
if (key->type_data.x[0]) int err = PTR_ERR(key->payload.data[dns_key_error]);
return key->type_data.x[0];
if (err)
return err;
return user_read(key, buffer, buflen); return user_read(key, buffer, buflen);
} }

View File

@ -70,7 +70,7 @@ int dns_query(const char *type, const char *name, size_t namelen,
const char *options, char **_result, time_t *_expiry) const char *options, char **_result, time_t *_expiry)
{ {
struct key *rkey; struct key *rkey;
struct user_key_payload *upayload; const struct user_key_payload *upayload;
const struct cred *saved_cred; const struct cred *saved_cred;
size_t typelen, desclen; size_t typelen, desclen;
char *desc, *cp; char *desc, *cp;
@ -137,12 +137,11 @@ int dns_query(const char *type, const char *name, size_t namelen,
goto put; goto put;
/* If the DNS server gave an error, return that to the caller */ /* If the DNS server gave an error, return that to the caller */
ret = rkey->type_data.x[0]; ret = PTR_ERR(rkey->payload.data[dns_key_error]);
if (ret) if (ret)
goto put; goto put;
upayload = rcu_dereference_protected(rkey->payload.data, upayload = user_key_payload(rkey);
lockdep_is_held(&rkey->sem));
len = upayload->datalen; len = upayload->datalen;
ret = -ENOMEM; ret = -ENOMEM;

View File

@ -22,6 +22,14 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/sched.h> #include <linux/sched.h>
/*
* Layout of key payload words.
*/
enum {
dns_key_data,
dns_key_error,
};
/* /*
* dns_key.c * dns_key.c
*/ */

View File

@ -305,7 +305,7 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock,
if (!key) if (!key)
key = rx->key; key = rx->key;
if (key && !key->payload.data) if (key && !key->payload.data[0])
key = NULL; /* a no-security key */ key = NULL; /* a no-security key */
bundle = rxrpc_get_bundle(rx, trans, key, service_id, gfp); bundle = rxrpc_get_bundle(rx, trans, key, service_id, gfp);

View File

@ -148,10 +148,10 @@ static int rxrpc_preparse_xdr_rxkad(struct key_preparsed_payload *prep,
token->kad->ticket[6], token->kad->ticket[7]); token->kad->ticket[6], token->kad->ticket[7]);
/* count the number of tokens attached */ /* count the number of tokens attached */
prep->type_data[0] = (void *)((unsigned long)prep->type_data[0] + 1); prep->payload.data[1] = (void *)((unsigned long)prep->payload.data[1] + 1);
/* attach the data */ /* attach the data */
for (pptoken = (struct rxrpc_key_token **)&prep->payload[0]; for (pptoken = (struct rxrpc_key_token **)&prep->payload.data[0];
*pptoken; *pptoken;
pptoken = &(*pptoken)->next) pptoken = &(*pptoken)->next)
continue; continue;
@ -522,7 +522,7 @@ static int rxrpc_preparse_xdr_rxk5(struct key_preparsed_payload *prep,
goto inval; goto inval;
/* attach the payload */ /* attach the payload */
for (pptoken = (struct rxrpc_key_token **)&prep->payload[0]; for (pptoken = (struct rxrpc_key_token **)&prep->payload.data[0];
*pptoken; *pptoken;
pptoken = &(*pptoken)->next) pptoken = &(*pptoken)->next)
continue; continue;
@ -764,10 +764,10 @@ static int rxrpc_preparse(struct key_preparsed_payload *prep)
memcpy(&token->kad->ticket, v1->ticket, v1->ticket_length); memcpy(&token->kad->ticket, v1->ticket, v1->ticket_length);
/* count the number of tokens attached */ /* count the number of tokens attached */
prep->type_data[0] = (void *)((unsigned long)prep->type_data[0] + 1); prep->payload.data[1] = (void *)((unsigned long)prep->payload.data[1] + 1);
/* attach the data */ /* attach the data */
pp = (struct rxrpc_key_token **)&prep->payload[0]; pp = (struct rxrpc_key_token **)&prep->payload.data[0];
while (*pp) while (*pp)
pp = &(*pp)->next; pp = &(*pp)->next;
*pp = token; *pp = token;
@ -814,7 +814,7 @@ static void rxrpc_free_token_list(struct rxrpc_key_token *token)
*/ */
static void rxrpc_free_preparse(struct key_preparsed_payload *prep) static void rxrpc_free_preparse(struct key_preparsed_payload *prep)
{ {
rxrpc_free_token_list(prep->payload[0]); rxrpc_free_token_list(prep->payload.data[0]);
} }
/* /*
@ -831,7 +831,7 @@ static int rxrpc_preparse_s(struct key_preparsed_payload *prep)
if (prep->datalen != 8) if (prep->datalen != 8)
return -EINVAL; return -EINVAL;
memcpy(&prep->type_data, prep->data, 8); memcpy(&prep->payload.data[2], prep->data, 8);
ci = crypto_alloc_blkcipher("pcbc(des)", 0, CRYPTO_ALG_ASYNC); ci = crypto_alloc_blkcipher("pcbc(des)", 0, CRYPTO_ALG_ASYNC);
if (IS_ERR(ci)) { if (IS_ERR(ci)) {
@ -842,7 +842,7 @@ static int rxrpc_preparse_s(struct key_preparsed_payload *prep)
if (crypto_blkcipher_setkey(ci, prep->data, 8) < 0) if (crypto_blkcipher_setkey(ci, prep->data, 8) < 0)
BUG(); BUG();
prep->payload[0] = ci; prep->payload.data[0] = ci;
_leave(" = 0"); _leave(" = 0");
return 0; return 0;
} }
@ -852,8 +852,8 @@ static int rxrpc_preparse_s(struct key_preparsed_payload *prep)
*/ */
static void rxrpc_free_preparse_s(struct key_preparsed_payload *prep) static void rxrpc_free_preparse_s(struct key_preparsed_payload *prep)
{ {
if (prep->payload[0]) if (prep->payload.data[0])
crypto_free_blkcipher(prep->payload[0]); crypto_free_blkcipher(prep->payload.data[0]);
} }
/* /*
@ -861,7 +861,7 @@ static void rxrpc_free_preparse_s(struct key_preparsed_payload *prep)
*/ */
static void rxrpc_destroy(struct key *key) static void rxrpc_destroy(struct key *key)
{ {
rxrpc_free_token_list(key->payload.data); rxrpc_free_token_list(key->payload.data[0]);
} }
/* /*
@ -869,9 +869,9 @@ static void rxrpc_destroy(struct key *key)
*/ */
static void rxrpc_destroy_s(struct key *key) static void rxrpc_destroy_s(struct key *key)
{ {
if (key->payload.data) { if (key->payload.data[0]) {
crypto_free_blkcipher(key->payload.data); crypto_free_blkcipher(key->payload.data[0]);
key->payload.data = NULL; key->payload.data[0] = NULL;
} }
} }
@ -1070,7 +1070,7 @@ static long rxrpc_read(const struct key *key,
size += 1 * 4; /* token count */ size += 1 * 4; /* token count */
ntoks = 0; ntoks = 0;
for (token = key->payload.data; token; token = token->next) { for (token = key->payload.data[0]; token; token = token->next) {
toksize = 4; /* sec index */ toksize = 4; /* sec index */
switch (token->security_index) { switch (token->security_index) {
@ -1163,7 +1163,7 @@ static long rxrpc_read(const struct key *key,
ENCODE(ntoks); ENCODE(ntoks);
tok = 0; tok = 0;
for (token = key->payload.data; token; token = token->next) { for (token = key->payload.data[0]; token; token = token->next) {
toksize = toksizes[tok++]; toksize = toksizes[tok++];
ENCODE(toksize); ENCODE(toksize);
oldxdr = xdr; oldxdr = xdr;

View File

@ -158,7 +158,7 @@ int rxrpc_client_sendmsg(struct rxrpc_sock *rx, struct rxrpc_transport *trans,
service_id = htons(srx->srx_service); service_id = htons(srx->srx_service);
} }
key = rx->key; key = rx->key;
if (key && !rx->key->payload.data) if (key && !rx->key->payload.data[0])
key = NULL; key = NULL;
bundle = rxrpc_get_bundle(rx, trans, key, service_id, bundle = rxrpc_get_bundle(rx, trans, key, service_id,
GFP_KERNEL); GFP_KERNEL);

View File

@ -137,9 +137,9 @@ int rxrpc_init_client_conn_security(struct rxrpc_connection *conn)
if (ret < 0) if (ret < 0)
return ret; return ret;
if (!key->payload.data) token = key->payload.data[0];
if (!token)
return -EKEYREJECTED; return -EKEYREJECTED;
token = key->payload.data;
sec = rxrpc_security_lookup(token->security_index); sec = rxrpc_security_lookup(token->security_index);
if (!sec) if (!sec)

View File

@ -67,7 +67,7 @@ static int rxkad_init_connection_security(struct rxrpc_connection *conn)
_enter("{%d},{%x}", conn->debug_id, key_serial(conn->key)); _enter("{%d},{%x}", conn->debug_id, key_serial(conn->key));
token = conn->key->payload.data; token = conn->key->payload.data[0];
conn->security_ix = token->security_index; conn->security_ix = token->security_index;
ci = crypto_alloc_blkcipher("pcbc(fcrypt)", 0, CRYPTO_ALG_ASYNC); ci = crypto_alloc_blkcipher("pcbc(fcrypt)", 0, CRYPTO_ALG_ASYNC);
@ -125,7 +125,7 @@ static void rxkad_prime_packet_security(struct rxrpc_connection *conn)
if (!conn->key) if (!conn->key)
return; return;
token = conn->key->payload.data; token = conn->key->payload.data[0];
memcpy(&iv, token->kad->session_key, sizeof(iv)); memcpy(&iv, token->kad->session_key, sizeof(iv));
desc.tfm = conn->cipher; desc.tfm = conn->cipher;
@ -221,7 +221,7 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call,
rxkhdr.checksum = 0; rxkhdr.checksum = 0;
/* encrypt from the session key */ /* encrypt from the session key */
token = call->conn->key->payload.data; token = call->conn->key->payload.data[0];
memcpy(&iv, token->kad->session_key, sizeof(iv)); memcpy(&iv, token->kad->session_key, sizeof(iv));
desc.tfm = call->conn->cipher; desc.tfm = call->conn->cipher;
desc.info = iv.x; desc.info = iv.x;
@ -433,7 +433,7 @@ static int rxkad_verify_packet_encrypt(const struct rxrpc_call *call,
skb_to_sgvec(skb, sg, 0, skb->len); skb_to_sgvec(skb, sg, 0, skb->len);
/* decrypt from the session key */ /* decrypt from the session key */
token = call->conn->key->payload.data; token = call->conn->key->payload.data[0];
memcpy(&iv, token->kad->session_key, sizeof(iv)); memcpy(&iv, token->kad->session_key, sizeof(iv));
desc.tfm = call->conn->cipher; desc.tfm = call->conn->cipher;
desc.info = iv.x; desc.info = iv.x;
@ -780,7 +780,7 @@ static int rxkad_respond_to_challenge(struct rxrpc_connection *conn,
if (conn->security_level < min_level) if (conn->security_level < min_level)
goto protocol_error; goto protocol_error;
token = conn->key->payload.data; token = conn->key->payload.data[0];
/* build the response packet */ /* build the response packet */
memset(&resp, 0, sizeof(resp)); memset(&resp, 0, sizeof(resp));
@ -848,12 +848,12 @@ static int rxkad_decrypt_ticket(struct rxrpc_connection *conn,
} }
} }
ASSERT(conn->server_key->payload.data != NULL); ASSERT(conn->server_key->payload.data[0] != NULL);
ASSERTCMP((unsigned long) ticket & 7UL, ==, 0); ASSERTCMP((unsigned long) ticket & 7UL, ==, 0);
memcpy(&iv, &conn->server_key->type_data, sizeof(iv)); memcpy(&iv, &conn->server_key->payload.data[2], sizeof(iv));
desc.tfm = conn->server_key->payload.data; desc.tfm = conn->server_key->payload.data[0];
desc.info = iv.x; desc.info = iv.x;
desc.flags = 0; desc.flags = 0;

View File

@ -247,7 +247,7 @@ int evm_init_key(void)
return -ENOENT; return -ENOENT;
down_read(&evm_key->sem); down_read(&evm_key->sem);
ekp = evm_key->payload.data; ekp = evm_key->payload.data[0];
if (ekp->decrypted_datalen > MAX_KEY_SIZE) { if (ekp->decrypted_datalen > MAX_KEY_SIZE) {
rc = -EINVAL; rc = -EINVAL;
goto out; goto out;

View File

@ -20,6 +20,16 @@
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
/*
* Layout of key payload words.
*/
enum {
big_key_data,
big_key_path,
big_key_path_2nd_part,
big_key_len,
};
/* /*
* If the data is under this limit, there's no point creating a shm file to * If the data is under this limit, there's no point creating a shm file to
* hold it as the permanently resident metadata for the shmem fs will be at * hold it as the permanently resident metadata for the shmem fs will be at
@ -47,7 +57,7 @@ struct key_type key_type_big_key = {
*/ */
int big_key_preparse(struct key_preparsed_payload *prep) int big_key_preparse(struct key_preparsed_payload *prep)
{ {
struct path *path = (struct path *)&prep->payload; struct path *path = (struct path *)&prep->payload.data[big_key_path];
struct file *file; struct file *file;
ssize_t written; ssize_t written;
size_t datalen = prep->datalen; size_t datalen = prep->datalen;
@ -60,7 +70,7 @@ int big_key_preparse(struct key_preparsed_payload *prep)
/* Set an arbitrary quota */ /* Set an arbitrary quota */
prep->quotalen = 16; prep->quotalen = 16;
prep->type_data[1] = (void *)(unsigned long)datalen; prep->payload.data[big_key_len] = (void *)(unsigned long)datalen;
if (datalen > BIG_KEY_FILE_THRESHOLD) { if (datalen > BIG_KEY_FILE_THRESHOLD) {
/* Create a shmem file to store the data in. This will permit the data /* Create a shmem file to store the data in. This will permit the data
@ -94,7 +104,8 @@ int big_key_preparse(struct key_preparsed_payload *prep)
if (!data) if (!data)
return -ENOMEM; return -ENOMEM;
prep->payload[0] = memcpy(data, prep->data, prep->datalen); prep->payload.data[big_key_data] = data;
memcpy(data, prep->data, prep->datalen);
} }
return 0; return 0;
@ -110,10 +121,10 @@ error:
void big_key_free_preparse(struct key_preparsed_payload *prep) void big_key_free_preparse(struct key_preparsed_payload *prep)
{ {
if (prep->datalen > BIG_KEY_FILE_THRESHOLD) { if (prep->datalen > BIG_KEY_FILE_THRESHOLD) {
struct path *path = (struct path *)&prep->payload; struct path *path = (struct path *)&prep->payload.data[big_key_path];
path_put(path); path_put(path);
} else { } else {
kfree(prep->payload[0]); kfree(prep->payload.data[big_key_data]);
} }
} }
@ -123,11 +134,12 @@ void big_key_free_preparse(struct key_preparsed_payload *prep)
*/ */
void big_key_revoke(struct key *key) void big_key_revoke(struct key *key)
{ {
struct path *path = (struct path *)&key->payload.data2; struct path *path = (struct path *)&key->payload.data[big_key_path];
/* clear the quota */ /* clear the quota */
key_payload_reserve(key, 0); key_payload_reserve(key, 0);
if (key_is_instantiated(key) && key->type_data.x[1] > BIG_KEY_FILE_THRESHOLD) if (key_is_instantiated(key) &&
(size_t)key->payload.data[big_key_len] > BIG_KEY_FILE_THRESHOLD)
vfs_truncate(path, 0); vfs_truncate(path, 0);
} }
@ -136,14 +148,16 @@ void big_key_revoke(struct key *key)
*/ */
void big_key_destroy(struct key *key) void big_key_destroy(struct key *key)
{ {
if (key->type_data.x[1] > BIG_KEY_FILE_THRESHOLD) { size_t datalen = (size_t)key->payload.data[big_key_len];
struct path *path = (struct path *)&key->payload.data2;
if (datalen) {
struct path *path = (struct path *)&key->payload.data[big_key_path];
path_put(path); path_put(path);
path->mnt = NULL; path->mnt = NULL;
path->dentry = NULL; path->dentry = NULL;
} else { } else {
kfree(key->payload.data); kfree(key->payload.data[big_key_data]);
key->payload.data = NULL; key->payload.data[big_key_data] = NULL;
} }
} }
@ -152,12 +166,12 @@ void big_key_destroy(struct key *key)
*/ */
void big_key_describe(const struct key *key, struct seq_file *m) void big_key_describe(const struct key *key, struct seq_file *m)
{ {
unsigned long datalen = key->type_data.x[1]; size_t datalen = (size_t)key->payload.data[big_key_len];
seq_puts(m, key->description); seq_puts(m, key->description);
if (key_is_instantiated(key)) if (key_is_instantiated(key))
seq_printf(m, ": %lu [%s]", seq_printf(m, ": %zu [%s]",
datalen, datalen,
datalen > BIG_KEY_FILE_THRESHOLD ? "file" : "buff"); datalen > BIG_KEY_FILE_THRESHOLD ? "file" : "buff");
} }
@ -168,14 +182,14 @@ void big_key_describe(const struct key *key, struct seq_file *m)
*/ */
long big_key_read(const struct key *key, char __user *buffer, size_t buflen) long big_key_read(const struct key *key, char __user *buffer, size_t buflen)
{ {
unsigned long datalen = key->type_data.x[1]; size_t datalen = (size_t)key->payload.data[big_key_len];
long ret; long ret;
if (!buffer || buflen < datalen) if (!buffer || buflen < datalen)
return datalen; return datalen;
if (datalen > BIG_KEY_FILE_THRESHOLD) { if (datalen > BIG_KEY_FILE_THRESHOLD) {
struct path *path = (struct path *)&key->payload.data2; struct path *path = (struct path *)&key->payload.data[big_key_path];
struct file *file; struct file *file;
loff_t pos; loff_t pos;
@ -190,7 +204,8 @@ long big_key_read(const struct key *key, char __user *buffer, size_t buflen)
ret = -EIO; ret = -EIO;
} else { } else {
ret = datalen; ret = datalen;
if (copy_to_user(buffer, key->payload.data, datalen) != 0) if (copy_to_user(buffer, key->payload.data[big_key_data],
datalen) != 0)
ret = -EFAULT; ret = -EFAULT;
} }

View File

@ -303,10 +303,10 @@ out:
* *
* Use a user provided key to encrypt/decrypt an encrypted-key. * Use a user provided key to encrypt/decrypt an encrypted-key.
*/ */
static struct key *request_user_key(const char *master_desc, u8 **master_key, static struct key *request_user_key(const char *master_desc, const u8 **master_key,
size_t *master_keylen) size_t *master_keylen)
{ {
struct user_key_payload *upayload; const struct user_key_payload *upayload;
struct key *ukey; struct key *ukey;
ukey = request_key(&key_type_user, master_desc, NULL); ukey = request_key(&key_type_user, master_desc, NULL);
@ -314,7 +314,7 @@ static struct key *request_user_key(const char *master_desc, u8 **master_key,
goto error; goto error;
down_read(&ukey->sem); down_read(&ukey->sem);
upayload = ukey->payload.data; upayload = user_key_payload(ukey);
*master_key = upayload->data; *master_key = upayload->data;
*master_keylen = upayload->datalen; *master_keylen = upayload->datalen;
error: error:
@ -426,7 +426,7 @@ static int init_blkcipher_desc(struct blkcipher_desc *desc, const u8 *key,
} }
static struct key *request_master_key(struct encrypted_key_payload *epayload, static struct key *request_master_key(struct encrypted_key_payload *epayload,
u8 **master_key, size_t *master_keylen) const u8 **master_key, size_t *master_keylen)
{ {
struct key *mkey = NULL; struct key *mkey = NULL;
@ -653,7 +653,7 @@ static int encrypted_key_decrypt(struct encrypted_key_payload *epayload,
{ {
struct key *mkey; struct key *mkey;
u8 derived_key[HASH_SIZE]; u8 derived_key[HASH_SIZE];
u8 *master_key; const u8 *master_key;
u8 *hmac; u8 *hmac;
const char *hex_encoded_data; const char *hex_encoded_data;
unsigned int encrypted_datalen; unsigned int encrypted_datalen;
@ -837,7 +837,7 @@ static void encrypted_rcu_free(struct rcu_head *rcu)
*/ */
static int encrypted_update(struct key *key, struct key_preparsed_payload *prep) static int encrypted_update(struct key *key, struct key_preparsed_payload *prep)
{ {
struct encrypted_key_payload *epayload = key->payload.data; struct encrypted_key_payload *epayload = key->payload.data[0];
struct encrypted_key_payload *new_epayload; struct encrypted_key_payload *new_epayload;
char *buf; char *buf;
char *new_master_desc = NULL; char *new_master_desc = NULL;
@ -896,7 +896,7 @@ static long encrypted_read(const struct key *key, char __user *buffer,
{ {
struct encrypted_key_payload *epayload; struct encrypted_key_payload *epayload;
struct key *mkey; struct key *mkey;
u8 *master_key; const u8 *master_key;
size_t master_keylen; size_t master_keylen;
char derived_key[HASH_SIZE]; char derived_key[HASH_SIZE];
char *ascii_buf; char *ascii_buf;
@ -957,13 +957,13 @@ out:
*/ */
static void encrypted_destroy(struct key *key) static void encrypted_destroy(struct key *key)
{ {
struct encrypted_key_payload *epayload = key->payload.data; struct encrypted_key_payload *epayload = key->payload.data[0];
if (!epayload) if (!epayload)
return; return;
memset(epayload->decrypted_data, 0, epayload->decrypted_datalen); memset(epayload->decrypted_data, 0, epayload->decrypted_datalen);
kfree(key->payload.data); kfree(key->payload.data[0]);
} }
struct key_type key_type_encrypted = { struct key_type key_type_encrypted = {

View File

@ -5,10 +5,10 @@
#if defined(CONFIG_TRUSTED_KEYS) || \ #if defined(CONFIG_TRUSTED_KEYS) || \
(defined(CONFIG_TRUSTED_KEYS_MODULE) && defined(CONFIG_ENCRYPTED_KEYS_MODULE)) (defined(CONFIG_TRUSTED_KEYS_MODULE) && defined(CONFIG_ENCRYPTED_KEYS_MODULE))
extern struct key *request_trusted_key(const char *trusted_desc, extern struct key *request_trusted_key(const char *trusted_desc,
u8 **master_key, size_t *master_keylen); const u8 **master_key, size_t *master_keylen);
#else #else
static inline struct key *request_trusted_key(const char *trusted_desc, static inline struct key *request_trusted_key(const char *trusted_desc,
u8 **master_key, const u8 **master_key,
size_t *master_keylen) size_t *master_keylen)
{ {
return ERR_PTR(-EOPNOTSUPP); return ERR_PTR(-EOPNOTSUPP);

View File

@ -29,7 +29,7 @@
* data, trusted key type data is not visible decrypted from userspace. * data, trusted key type data is not visible decrypted from userspace.
*/ */
struct key *request_trusted_key(const char *trusted_desc, struct key *request_trusted_key(const char *trusted_desc,
u8 **master_key, size_t *master_keylen) const u8 **master_key, size_t *master_keylen)
{ {
struct trusted_key_payload *tpayload; struct trusted_key_payload *tpayload;
struct key *tkey; struct key *tkey;
@ -39,7 +39,7 @@ struct key *request_trusted_key(const char *trusted_desc,
goto error; goto error;
down_read(&tkey->sem); down_read(&tkey->sem);
tpayload = tkey->payload.data; tpayload = tkey->payload.data[0];
*master_key = tpayload->key; *master_key = tpayload->key;
*master_keylen = tpayload->key_len; *master_keylen = tpayload->key_len;
error: error:

View File

@ -554,7 +554,7 @@ int key_reject_and_link(struct key *key,
if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) { if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) {
/* mark the key as being negatively instantiated */ /* mark the key as being negatively instantiated */
atomic_inc(&key->user->nikeys); atomic_inc(&key->user->nikeys);
key->type_data.reject_error = -error; key->reject_error = -error;
smp_wmb(); smp_wmb();
set_bit(KEY_FLAG_NEGATIVE, &key->flags); set_bit(KEY_FLAG_NEGATIVE, &key->flags);
set_bit(KEY_FLAG_INSTANTIATED, &key->flags); set_bit(KEY_FLAG_INSTANTIATED, &key->flags);
@ -1046,14 +1046,14 @@ int generic_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
ret = key_payload_reserve(key, prep->quotalen); ret = key_payload_reserve(key, prep->quotalen);
if (ret == 0) { if (ret == 0) {
key->type_data.p[0] = prep->type_data[0]; rcu_assign_keypointer(key, prep->payload.data[0]);
key->type_data.p[1] = prep->type_data[1]; key->payload.data[1] = prep->payload.data[1];
rcu_assign_keypointer(key, prep->payload[0]); key->payload.data[2] = prep->payload.data[2];
key->payload.data2[1] = prep->payload[1]; key->payload.data[3] = prep->payload.data[3];
prep->type_data[0] = NULL; prep->payload.data[0] = NULL;
prep->type_data[1] = NULL; prep->payload.data[1] = NULL;
prep->payload[0] = NULL; prep->payload.data[2] = NULL;
prep->payload[1] = NULL; prep->payload.data[3] = NULL;
} }
pr_devel("<==%s() = %d\n", __func__, ret); pr_devel("<==%s() = %d\n", __func__, ret);
return ret; return ret;

View File

@ -1027,7 +1027,7 @@ long keyctl_instantiate_key_common(key_serial_t id,
if (!instkey) if (!instkey)
goto error; goto error;
rka = instkey->payload.data; rka = instkey->payload.data[0];
if (rka->target_key->serial != id) if (rka->target_key->serial != id)
goto error; goto error;
@ -1194,7 +1194,7 @@ long keyctl_reject_key(key_serial_t id, unsigned timeout, unsigned error,
if (!instkey) if (!instkey)
goto error; goto error;
rka = instkey->payload.data; rka = instkey->payload.data[0];
if (rka->target_key->serial != id) if (rka->target_key->serial != id)
goto error; goto error;

View File

@ -118,7 +118,7 @@ static void keyring_publish_name(struct key *keyring)
if (!keyring_name_hash[bucket].next) if (!keyring_name_hash[bucket].next)
INIT_LIST_HEAD(&keyring_name_hash[bucket]); INIT_LIST_HEAD(&keyring_name_hash[bucket]);
list_add_tail(&keyring->type_data.link, list_add_tail(&keyring->name_link,
&keyring_name_hash[bucket]); &keyring_name_hash[bucket]);
write_unlock(&keyring_name_lock); write_unlock(&keyring_name_lock);
@ -387,9 +387,9 @@ static void keyring_destroy(struct key *keyring)
if (keyring->description) { if (keyring->description) {
write_lock(&keyring_name_lock); write_lock(&keyring_name_lock);
if (keyring->type_data.link.next != NULL && if (keyring->name_link.next != NULL &&
!list_empty(&keyring->type_data.link)) !list_empty(&keyring->name_link))
list_del(&keyring->type_data.link); list_del(&keyring->name_link);
write_unlock(&keyring_name_lock); write_unlock(&keyring_name_lock);
} }
@ -572,7 +572,7 @@ static int keyring_search_iterator(const void *object, void *iterator_data)
/* we set a different error code if we pass a negative key */ /* we set a different error code if we pass a negative key */
if (kflags & (1 << KEY_FLAG_NEGATIVE)) { if (kflags & (1 << KEY_FLAG_NEGATIVE)) {
smp_rmb(); smp_rmb();
ctx->result = ERR_PTR(key->type_data.reject_error); ctx->result = ERR_PTR(key->reject_error);
kleave(" = %d [neg]", ctx->skipped_ret); kleave(" = %d [neg]", ctx->skipped_ret);
goto skipped; goto skipped;
} }
@ -990,7 +990,7 @@ struct key *find_keyring_by_name(const char *name, bool skip_perm_check)
* that's readable and that hasn't been revoked */ * that's readable and that hasn't been revoked */
list_for_each_entry(keyring, list_for_each_entry(keyring,
&keyring_name_hash[bucket], &keyring_name_hash[bucket],
type_data.link name_link
) { ) {
if (!kuid_has_mapping(current_user_ns(), keyring->user->uid)) if (!kuid_has_mapping(current_user_ns(), keyring->user->uid))
continue; continue;

View File

@ -457,7 +457,7 @@ key_ref_t search_process_keyrings(struct keyring_search_context *ctx)
down_read(&cred->request_key_auth->sem); down_read(&cred->request_key_auth->sem);
if (key_validate(ctx->cred->request_key_auth) == 0) { if (key_validate(ctx->cred->request_key_auth) == 0) {
rka = ctx->cred->request_key_auth->payload.data; rka = ctx->cred->request_key_auth->payload.data[0];
ctx->cred = rka->cred; ctx->cred = rka->cred;
key_ref = search_process_keyrings(ctx); key_ref = search_process_keyrings(ctx);
@ -647,7 +647,7 @@ try_again:
key_ref = ERR_PTR(-EKEYREVOKED); key_ref = ERR_PTR(-EKEYREVOKED);
key = NULL; key = NULL;
} else { } else {
rka = ctx.cred->request_key_auth->payload.data; rka = ctx.cred->request_key_auth->payload.data[0];
key = rka->dest_keyring; key = rka->dest_keyring;
__key_get(key); __key_get(key);
} }

View File

@ -271,7 +271,7 @@ static void construct_get_dest_keyring(struct key **_dest_keyring)
if (cred->request_key_auth) { if (cred->request_key_auth) {
authkey = cred->request_key_auth; authkey = cred->request_key_auth;
down_read(&authkey->sem); down_read(&authkey->sem);
rka = authkey->payload.data; rka = authkey->payload.data[0];
if (!test_bit(KEY_FLAG_REVOKED, if (!test_bit(KEY_FLAG_REVOKED,
&authkey->flags)) &authkey->flags))
dest_keyring = dest_keyring =
@ -593,7 +593,7 @@ int wait_for_key_construction(struct key *key, bool intr)
return -ERESTARTSYS; return -ERESTARTSYS;
if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) { if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) {
smp_rmb(); smp_rmb();
return key->type_data.reject_error; return key->reject_error;
} }
return key_validate(key); return key_validate(key);
} }

View File

@ -59,7 +59,7 @@ static void request_key_auth_free_preparse(struct key_preparsed_payload *prep)
static int request_key_auth_instantiate(struct key *key, static int request_key_auth_instantiate(struct key *key,
struct key_preparsed_payload *prep) struct key_preparsed_payload *prep)
{ {
key->payload.data = (struct request_key_auth *)prep->data; key->payload.data[0] = (struct request_key_auth *)prep->data;
return 0; return 0;
} }
@ -69,7 +69,7 @@ static int request_key_auth_instantiate(struct key *key,
static void request_key_auth_describe(const struct key *key, static void request_key_auth_describe(const struct key *key,
struct seq_file *m) struct seq_file *m)
{ {
struct request_key_auth *rka = key->payload.data; struct request_key_auth *rka = key->payload.data[0];
seq_puts(m, "key:"); seq_puts(m, "key:");
seq_puts(m, key->description); seq_puts(m, key->description);
@ -84,7 +84,7 @@ static void request_key_auth_describe(const struct key *key,
static long request_key_auth_read(const struct key *key, static long request_key_auth_read(const struct key *key,
char __user *buffer, size_t buflen) char __user *buffer, size_t buflen)
{ {
struct request_key_auth *rka = key->payload.data; struct request_key_auth *rka = key->payload.data[0];
size_t datalen; size_t datalen;
long ret; long ret;
@ -110,7 +110,7 @@ static long request_key_auth_read(const struct key *key,
*/ */
static void request_key_auth_revoke(struct key *key) static void request_key_auth_revoke(struct key *key)
{ {
struct request_key_auth *rka = key->payload.data; struct request_key_auth *rka = key->payload.data[0];
kenter("{%d}", key->serial); kenter("{%d}", key->serial);
@ -125,7 +125,7 @@ static void request_key_auth_revoke(struct key *key)
*/ */
static void request_key_auth_destroy(struct key *key) static void request_key_auth_destroy(struct key *key)
{ {
struct request_key_auth *rka = key->payload.data; struct request_key_auth *rka = key->payload.data[0];
kenter("{%d}", key->serial); kenter("{%d}", key->serial);
@ -179,7 +179,7 @@ struct key *request_key_auth_new(struct key *target, const void *callout_info,
if (test_bit(KEY_FLAG_REVOKED, &cred->request_key_auth->flags)) if (test_bit(KEY_FLAG_REVOKED, &cred->request_key_auth->flags))
goto auth_key_revoked; goto auth_key_revoked;
irka = cred->request_key_auth->payload.data; irka = cred->request_key_auth->payload.data[0];
rka->cred = get_cred(irka->cred); rka->cred = get_cred(irka->cred);
rka->pid = irka->pid; rka->pid = irka->pid;

View File

@ -1007,7 +1007,7 @@ static void trusted_rcu_free(struct rcu_head *rcu)
*/ */
static int trusted_update(struct key *key, struct key_preparsed_payload *prep) static int trusted_update(struct key *key, struct key_preparsed_payload *prep)
{ {
struct trusted_key_payload *p = key->payload.data; struct trusted_key_payload *p = key->payload.data[0];
struct trusted_key_payload *new_p; struct trusted_key_payload *new_p;
struct trusted_key_options *new_o; struct trusted_key_options *new_o;
size_t datalen = prep->datalen; size_t datalen = prep->datalen;
@ -1114,12 +1114,12 @@ static long trusted_read(const struct key *key, char __user *buffer,
*/ */
static void trusted_destroy(struct key *key) static void trusted_destroy(struct key *key)
{ {
struct trusted_key_payload *p = key->payload.data; struct trusted_key_payload *p = key->payload.data[0];
if (!p) if (!p)
return; return;
memset(p->key, 0, p->key_len); memset(p->key, 0, p->key_len);
kfree(key->payload.data); kfree(key->payload.data[0]);
} }
struct key_type key_type_trusted = { struct key_type key_type_trusted = {

View File

@ -74,7 +74,7 @@ int user_preparse(struct key_preparsed_payload *prep)
/* attach the data */ /* attach the data */
prep->quotalen = datalen; prep->quotalen = datalen;
prep->payload[0] = upayload; prep->payload.data[0] = upayload;
upayload->datalen = datalen; upayload->datalen = datalen;
memcpy(upayload->data, prep->data, datalen); memcpy(upayload->data, prep->data, datalen);
return 0; return 0;
@ -86,7 +86,7 @@ EXPORT_SYMBOL_GPL(user_preparse);
*/ */
void user_free_preparse(struct key_preparsed_payload *prep) void user_free_preparse(struct key_preparsed_payload *prep)
{ {
kfree(prep->payload[0]); kfree(prep->payload.data[0]);
} }
EXPORT_SYMBOL_GPL(user_free_preparse); EXPORT_SYMBOL_GPL(user_free_preparse);
@ -120,7 +120,7 @@ int user_update(struct key *key, struct key_preparsed_payload *prep)
if (ret == 0) { if (ret == 0) {
/* attach the new data, displacing the old */ /* attach the new data, displacing the old */
zap = key->payload.data; zap = key->payload.data[0];
rcu_assign_keypointer(key, upayload); rcu_assign_keypointer(key, upayload);
key->expiry = 0; key->expiry = 0;
} }
@ -140,7 +140,7 @@ EXPORT_SYMBOL_GPL(user_update);
*/ */
void user_revoke(struct key *key) void user_revoke(struct key *key)
{ {
struct user_key_payload *upayload = key->payload.data; struct user_key_payload *upayload = key->payload.data[0];
/* clear the quota */ /* clear the quota */
key_payload_reserve(key, 0); key_payload_reserve(key, 0);
@ -158,7 +158,7 @@ EXPORT_SYMBOL(user_revoke);
*/ */
void user_destroy(struct key *key) void user_destroy(struct key *key)
{ {
struct user_key_payload *upayload = key->payload.data; struct user_key_payload *upayload = key->payload.data[0];
kfree(upayload); kfree(upayload);
} }
@ -183,10 +183,10 @@ EXPORT_SYMBOL_GPL(user_describe);
*/ */
long user_read(const struct key *key, char __user *buffer, size_t buflen) long user_read(const struct key *key, char __user *buffer, size_t buflen)
{ {
struct user_key_payload *upayload; const struct user_key_payload *upayload;
long ret; long ret;
upayload = rcu_dereference_key(key); upayload = user_key_payload(key);
ret = upayload->datalen; ret = upayload->datalen;
/* we can return the data as is */ /* we can return the data as is */