mirror of
https://github.com/torvalds/linux.git
synced 2024-11-23 12:42:02 +00:00
Merge tag 'keys-next-20151021' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs into next
This commit is contained in:
commit
ba94c3ff20
@ -186,7 +186,7 @@ and looks like the following:
|
||||
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 subtype. Currently, the name is only used for print statements.
|
||||
@ -269,8 +269,7 @@ mandatory:
|
||||
|
||||
struct key_preparsed_payload {
|
||||
char *description;
|
||||
void *type_data[2];
|
||||
void *payload;
|
||||
void *payload[4];
|
||||
const void *data;
|
||||
size_t datalen;
|
||||
size_t quotalen;
|
||||
@ -283,16 +282,18 @@ mandatory:
|
||||
not theirs.
|
||||
|
||||
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
|
||||
point to the subtype to be used, ->payload should be set to point to the
|
||||
initialised data for that subtype, ->type_data[1] should point to a hex
|
||||
fingerprint and quotalen should be updated to indicate how much quota this
|
||||
key should account for.
|
||||
the key and attach it to ->description, ->payload[asym_subtype] should be
|
||||
set to point to the subtype to be used, ->payload[asym_crypto] should be
|
||||
set to point to the initialised data for that subtype,
|
||||
->payload[asym_key_ids] should point to one or more hex fingerprints and
|
||||
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
|
||||
will be kfree()'d and the data attached to ->payload will be passed to the
|
||||
subtype's ->destroy() method to be disposed of. A module reference for
|
||||
the subtype pointed to by ->type_data[0] will be put.
|
||||
When clearing up, the data attached to ->payload[asym_key_ids] and
|
||||
->description will be kfree()'d and the data attached to
|
||||
->payload[asm_crypto] will be passed to the subtype's ->destroy() method
|
||||
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
|
||||
|
@ -1049,12 +1049,12 @@ search a specific keyring, so using keyrings in this way is of limited utility.
|
||||
NOTES ON ACCESSING PAYLOAD CONTENTS
|
||||
===================================
|
||||
|
||||
The simplest payload is just a number in key->payload.value. In this case,
|
||||
there's no need to indulge in RCU or locking when accessing the payload.
|
||||
The simplest payload is just data stored in key->payload directly. In this
|
||||
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
|
||||
key->payload.data. One of the following ways must be selected to access the
|
||||
data:
|
||||
More complex payload contents must be allocated and pointers to them set in the
|
||||
key->payload.data[] array. One of the following ways must be selected to
|
||||
access the data:
|
||||
|
||||
(1) Unmodifiable key type.
|
||||
|
||||
@ -1092,6 +1092,13 @@ data:
|
||||
the payload. key->datalen cannot be relied upon to be consistent with the
|
||||
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
|
||||
@ -1143,8 +1150,7 @@ The structure has a number of fields, some of which are mandatory:
|
||||
|
||||
struct key_preparsed_payload {
|
||||
char *description;
|
||||
void *type_data[2];
|
||||
void *payload;
|
||||
union key_payload payload;
|
||||
const void *data;
|
||||
size_t datalen;
|
||||
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
|
||||
key description if the caller of add_key() passes NULL or "".
|
||||
|
||||
The method can attach anything it likes to type_data[] and payload. These
|
||||
are merely passed along to the instantiate() or update() operations. If
|
||||
set, the expiry time will be applied to the key if it is instantiated from
|
||||
this data.
|
||||
The method can attach anything it likes to payload. This is merely passed
|
||||
along to the instantiate() or update() operations. If set, the expiry
|
||||
time will be applied to the key if it is instantiated from this data.
|
||||
|
||||
The method should return 0 if successful or a negative error code
|
||||
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);
|
||||
|
||||
This method is only required if the preparse() method is provided,
|
||||
otherwise it is unused. It cleans up anything attached to the
|
||||
description, type_data and payload fields of the key_preparsed_payload
|
||||
struct as filled in by the preparse() method. It will always be called
|
||||
after preparse() returns successfully, even if instantiate() or update()
|
||||
succeed.
|
||||
otherwise it is unused. It cleans up anything attached to the description
|
||||
and payload fields of the key_preparsed_payload struct as filled in by the
|
||||
preparse() method. It will always be called after preparse() returns
|
||||
successfully, even if instantiate() or update() succeed.
|
||||
|
||||
|
||||
(*) 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.
|
||||
|
||||
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);
|
||||
|
||||
|
4
certs/.gitignore
vendored
Normal file
4
certs/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
#
|
||||
# Generated files
|
||||
#
|
||||
x509_certificate_list
|
@ -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,
|
||||
struct asymmetric_key_id *match_id,
|
||||
size_t hexlen);
|
||||
static inline
|
||||
const struct asymmetric_key_ids *asymmetric_key_ids(const struct key *key)
|
||||
{
|
||||
return key->type_data.p[1];
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
pr_devel("==>%s()\n", __func__);
|
||||
|
||||
if (subtype) {
|
||||
subtype->destroy(prep->payload[0]);
|
||||
module_put(subtype->owner);
|
||||
}
|
||||
if (kids) {
|
||||
for (i = 0; i < ARRAY_SIZE(kids->id); i++)
|
||||
kfree(kids->id[i]);
|
||||
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);
|
||||
}
|
||||
|
||||
@ -335,20 +344,19 @@ static void asymmetric_key_free_preparse(struct key_preparsed_payload *prep)
|
||||
static void asymmetric_key_destroy(struct key *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) {
|
||||
subtype->destroy(key->payload.data);
|
||||
subtype->destroy(data);
|
||||
module_put(subtype->owner);
|
||||
key->type_data.p[0] = NULL;
|
||||
}
|
||||
|
||||
if (kids) {
|
||||
kfree(kids->id[0]);
|
||||
kfree(kids->id[1]);
|
||||
kfree(kids);
|
||||
key->type_data.p[1] = NULL;
|
||||
}
|
||||
asymmetric_key_free_kids(kids);
|
||||
}
|
||||
|
||||
struct key_type key_type_asymmetric = {
|
||||
|
@ -49,7 +49,7 @@ EXPORT_SYMBOL_GPL(pkey_id_type_name);
|
||||
static void public_key_describe(const struct key *asymmetric_key,
|
||||
struct seq_file *m)
|
||||
{
|
||||
struct public_key *key = asymmetric_key->payload.data;
|
||||
struct public_key *key = asymmetric_key->payload.data[asym_crypto];
|
||||
|
||||
if (key)
|
||||
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,
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,7 @@ int verify_signature(const struct key *key,
|
||||
return -EINVAL;
|
||||
subtype = asymmetric_key_subtype(key);
|
||||
if (!subtype ||
|
||||
!key->payload.data)
|
||||
!key->payload.data[0])
|
||||
return -EINVAL;
|
||||
if (!subtype->verify_signature)
|
||||
return -ENOTSUPP;
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include <linux/time.h>
|
||||
#include <crypto/public_key.h>
|
||||
#include <keys/asymmetric-type.h>
|
||||
|
||||
struct x509_certificate {
|
||||
struct x509_certificate *next;
|
||||
|
@ -266,7 +266,8 @@ static int x509_validate_trust(struct x509_certificate *cert,
|
||||
if (!IS_ERR(key)) {
|
||||
if (!use_builtin_keys
|
||||
|| 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);
|
||||
}
|
||||
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 */
|
||||
__module_get(public_key_subtype.owner);
|
||||
prep->type_data[0] = &public_key_subtype;
|
||||
prep->type_data[1] = kids;
|
||||
prep->payload[0] = cert->pub;
|
||||
prep->payload.data[asym_subtype] = &public_key_subtype;
|
||||
prep->payload.data[asym_key_ids] = kids;
|
||||
prep->payload.data[asym_crypto] = cert->pub;
|
||||
prep->description = desc;
|
||||
prep->quotalen = 100;
|
||||
|
||||
|
@ -42,7 +42,7 @@ cifs_spnego_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
|
||||
goto error;
|
||||
|
||||
/* attach the data */
|
||||
key->payload.data = payload;
|
||||
key->payload.data[0] = payload;
|
||||
ret = 0;
|
||||
|
||||
error:
|
||||
@ -52,7 +52,7 @@ error:
|
||||
static void
|
||||
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
|
||||
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,
|
||||
msg->secblob_len + msg->sesskey_len));
|
||||
}
|
||||
|
@ -58,16 +58,15 @@ cifs_idmap_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
|
||||
* dereference payload.data!
|
||||
*/
|
||||
if (prep->datalen <= sizeof(key->payload)) {
|
||||
key->payload.value = 0;
|
||||
memcpy(&key->payload.value, prep->data, prep->datalen);
|
||||
key->datalen = prep->datalen;
|
||||
return 0;
|
||||
key->payload.data[0] = NULL;
|
||||
memcpy(&key->payload, prep->data, prep->datalen);
|
||||
} else {
|
||||
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;
|
||||
return 0;
|
||||
}
|
||||
@ -76,7 +75,7 @@ static inline void
|
||||
cifs_idmap_key_destroy(struct key *key)
|
||||
{
|
||||
if (key->datalen > sizeof(key->payload))
|
||||
kfree(key->payload.data);
|
||||
kfree(key->payload.data[0]);
|
||||
}
|
||||
|
||||
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.
|
||||
*/
|
||||
ksid = sidkey->datalen <= sizeof(sidkey->payload) ?
|
||||
(struct cifs_sid *)&sidkey->payload.value :
|
||||
(struct cifs_sid *)sidkey->payload.data;
|
||||
(struct cifs_sid *)&sidkey->payload :
|
||||
(struct cifs_sid *)sidkey->payload.data[0];
|
||||
|
||||
ksid_size = CIFS_SID_BASE_SIZE + (ksid->num_subauth * sizeof(__le32));
|
||||
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) {
|
||||
kuid_t uid;
|
||||
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);
|
||||
if (uid_valid(uid))
|
||||
fuid = uid;
|
||||
} else {
|
||||
kgid_t gid;
|
||||
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);
|
||||
if (gid_valid(gid))
|
||||
fgid = gid;
|
||||
|
@ -2325,13 +2325,14 @@ static int
|
||||
cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
|
||||
{
|
||||
int rc = 0;
|
||||
char *desc, *delim, *payload;
|
||||
const char *delim, *payload;
|
||||
char *desc;
|
||||
ssize_t len;
|
||||
struct key *key;
|
||||
struct TCP_Server_Info *server = ses->server;
|
||||
struct sockaddr_in *sa;
|
||||
struct sockaddr_in6 *sa6;
|
||||
struct user_key_payload *upayload;
|
||||
const struct user_key_payload *upayload;
|
||||
|
||||
desc = kmalloc(CIFSCREDS_DESC_SIZE, GFP_KERNEL);
|
||||
if (!desc)
|
||||
@ -2374,14 +2375,14 @@ cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses)
|
||||
}
|
||||
|
||||
down_read(&key->sem);
|
||||
upayload = key->payload.data;
|
||||
upayload = user_key_payload(key);
|
||||
if (IS_ERR_OR_NULL(upayload)) {
|
||||
rc = upayload ? PTR_ERR(upayload) : -EINVAL;
|
||||
goto out_key_put;
|
||||
}
|
||||
|
||||
/* find first : in payload */
|
||||
payload = (char *)upayload->data;
|
||||
payload = upayload->data;
|
||||
delim = strnchr(payload, upayload->datalen, ':');
|
||||
cifs_dbg(FYI, "payload=%s\n", payload);
|
||||
if (!delim) {
|
||||
|
@ -988,7 +988,7 @@ sess_auth_kerberos(struct sess_data *sess_data)
|
||||
goto out;
|
||||
}
|
||||
|
||||
msg = spnego_key->payload.data;
|
||||
msg = spnego_key->payload.data[0];
|
||||
/*
|
||||
* check version field to make sure that cifs.upcall is
|
||||
* sending us a response in an expected form
|
||||
|
@ -660,7 +660,7 @@ ssetup_ntlmssp_authenticate:
|
||||
goto ssetup_exit;
|
||||
}
|
||||
|
||||
msg = spnego_key->payload.data;
|
||||
msg = spnego_key->payload.data[0];
|
||||
/*
|
||||
* check version field to make sure that cifs.upcall is
|
||||
* sending us a response in an expected form
|
||||
|
@ -86,7 +86,7 @@ ecryptfs_get_encrypted_key_payload_data(struct key *key)
|
||||
{
|
||||
if (key->type == &key_type_encrypted)
|
||||
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
|
||||
return NULL;
|
||||
}
|
||||
@ -117,8 +117,7 @@ ecryptfs_get_key_payload_data(struct key *key)
|
||||
|
||||
auth_tok = ecryptfs_get_encrypted_key_payload_data(key);
|
||||
if (!auth_tok)
|
||||
return (struct ecryptfs_auth_tok *)
|
||||
(((struct user_key_payload *)key->payload.data)->data);
|
||||
return (struct ecryptfs_auth_tok *)user_key_payload(key)->data;
|
||||
else
|
||||
return auth_tok;
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ int _ext4_get_encryption_info(struct inode *inode)
|
||||
struct key *keyring_key = NULL;
|
||||
struct ext4_encryption_key *master_key;
|
||||
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 crypto_ablkcipher *ctfm;
|
||||
const char *cipher_str;
|
||||
@ -209,7 +209,7 @@ retry:
|
||||
}
|
||||
crypt_info->ci_keyring_key = keyring_key;
|
||||
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)) {
|
||||
res = -EINVAL;
|
||||
goto out;
|
||||
|
@ -122,7 +122,7 @@ int _f2fs_get_encryption_info(struct inode *inode)
|
||||
struct key *keyring_key = NULL;
|
||||
struct f2fs_encryption_key *master_key;
|
||||
struct f2fs_encryption_context ctx;
|
||||
struct user_key_payload *ukp;
|
||||
const struct user_key_payload *ukp;
|
||||
struct crypto_ablkcipher *ctfm;
|
||||
const char *cipher_str;
|
||||
char raw_key[F2FS_MAX_KEY_SIZE];
|
||||
@ -199,7 +199,7 @@ retry:
|
||||
}
|
||||
crypt_info->ci_keyring_key = keyring_key;
|
||||
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)) {
|
||||
res = -EINVAL;
|
||||
goto out;
|
||||
|
@ -316,7 +316,7 @@ static const struct seq_operations fscache_objlist_ops = {
|
||||
static void fscache_objlist_config(struct fscache_objlist_data *data)
|
||||
{
|
||||
#ifdef CONFIG_KEYS
|
||||
struct user_key_payload *confkey;
|
||||
const struct user_key_payload *confkey;
|
||||
unsigned long config;
|
||||
struct key *key;
|
||||
const char *buf;
|
||||
@ -329,7 +329,7 @@ static void fscache_objlist_config(struct fscache_objlist_data *data)
|
||||
config = 0;
|
||||
rcu_read_lock();
|
||||
|
||||
confkey = key->payload.data;
|
||||
confkey = user_key_payload(key);
|
||||
buf = confkey->data;
|
||||
|
||||
for (len = confkey->datalen - 1; len >= 0; len--) {
|
||||
|
@ -297,7 +297,7 @@ static ssize_t nfs_idmap_get_key(const char *name, size_t namelen,
|
||||
{
|
||||
const struct cred *saved_cred;
|
||||
struct key *rkey;
|
||||
struct user_key_payload *payload;
|
||||
const struct user_key_payload *payload;
|
||||
ssize_t ret;
|
||||
|
||||
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)
|
||||
goto out_up;
|
||||
|
||||
payload = rcu_dereference(rkey->payload.rcudata);
|
||||
payload = user_key_payload(rkey);
|
||||
if (IS_ERR_OR_NULL(payload)) {
|
||||
ret = PTR_ERR(payload);
|
||||
goto out_up;
|
||||
|
@ -15,7 +15,6 @@
|
||||
#define _LINUX_PUBLIC_KEY_H
|
||||
|
||||
#include <linux/mpi.h>
|
||||
#include <keys/asymmetric-type.h>
|
||||
#include <crypto/hash_info.h>
|
||||
|
||||
enum pkey_algo {
|
||||
|
@ -49,7 +49,7 @@ struct asymmetric_key_subtype {
|
||||
static inline
|
||||
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 */
|
||||
|
@ -18,6 +18,16 @@
|
||||
|
||||
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
|
||||
* 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,
|
||||
const void *val_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.
|
||||
|
@ -15,6 +15,8 @@
|
||||
#include <linux/key.h>
|
||||
#include <linux/rcupdate.h>
|
||||
|
||||
#ifdef CONFIG_KEYS
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* 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,
|
||||
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 */
|
||||
|
@ -40,8 +40,7 @@ struct key_construction {
|
||||
*/
|
||||
struct key_preparsed_payload {
|
||||
char *description; /* Proposed key description (or NULL) */
|
||||
void *type_data[2]; /* Private key-type data */
|
||||
void *payload[2]; /* Proposed payload */
|
||||
union key_payload payload; /* Proposed payload */
|
||||
const void *data; /* Raw data */
|
||||
size_t datalen; /* Raw datalen */
|
||||
size_t quotalen; /* Quota length for proposed payload */
|
||||
|
@ -89,6 +89,11 @@ struct keyring_index_key {
|
||||
size_t desc_len;
|
||||
};
|
||||
|
||||
union key_payload {
|
||||
void __rcu *rcu_data0;
|
||||
void *data[4];
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* 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
|
||||
* - this is used to hold the data actually used in cryptography or
|
||||
* whatever
|
||||
*/
|
||||
union {
|
||||
union {
|
||||
unsigned long value;
|
||||
void __rcu *rcudata;
|
||||
void *data;
|
||||
void *data2[2];
|
||||
} payload;
|
||||
struct assoc_array keys;
|
||||
union key_payload payload;
|
||||
struct {
|
||||
/* Keyring bits */
|
||||
struct list_head name_link;
|
||||
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) \
|
||||
(rcu_dereference_protected((KEY)->payload.rcudata, \
|
||||
(rcu_dereference_protected((KEY)->payload.rcu_data0, \
|
||||
rwsem_is_locked(&((struct key *)(KEY))->sem)))
|
||||
|
||||
#define rcu_assign_keypointer(KEY, PAYLOAD) \
|
||||
do { \
|
||||
rcu_assign_pointer((KEY)->payload.rcudata, (PAYLOAD)); \
|
||||
rcu_assign_pointer((KEY)->payload.rcu_data0, (PAYLOAD)); \
|
||||
} while (0)
|
||||
|
||||
#ifdef CONFIG_SYSCTL
|
||||
|
1
kernel/.gitignore
vendored
1
kernel/.gitignore
vendored
@ -5,4 +5,3 @@ config_data.h
|
||||
config_data.gz
|
||||
timeconst.h
|
||||
hz.bc
|
||||
x509_certificate_list
|
||||
|
@ -10,6 +10,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <keys/system_keyring.h>
|
||||
#include <crypto/public_key.h>
|
||||
#include "module-internal.h"
|
||||
|
@ -79,12 +79,13 @@ static int digsig_verify_rsa(struct key *key,
|
||||
unsigned char *out1 = NULL;
|
||||
const char *m;
|
||||
MPI in = NULL, res = NULL, pkey[2];
|
||||
uint8_t *p, *datap, *endp;
|
||||
struct user_key_payload *ukp;
|
||||
uint8_t *p, *datap;
|
||||
const uint8_t *endp;
|
||||
const struct user_key_payload *ukp;
|
||||
struct pubkey_hdr *pkh;
|
||||
|
||||
down_read(&key->sem);
|
||||
ukp = key->payload.data;
|
||||
ukp = user_key_payload(key);
|
||||
|
||||
if (ukp->datalen < sizeof(*pkh))
|
||||
goto err1;
|
||||
|
@ -318,7 +318,7 @@ static int get_secret(struct ceph_crypto_key *dst, const char *name) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
ckey = ukey->payload.data;
|
||||
ckey = ukey->payload.data[0];
|
||||
err = ceph_crypto_key_clone(dst, ckey);
|
||||
if (err)
|
||||
goto out_key;
|
||||
|
@ -537,7 +537,7 @@ static int ceph_key_preparse(struct key_preparsed_payload *prep)
|
||||
if (ret < 0)
|
||||
goto err_ckey;
|
||||
|
||||
prep->payload[0] = ckey;
|
||||
prep->payload.data[0] = ckey;
|
||||
prep->quotalen = datalen;
|
||||
return 0;
|
||||
|
||||
@ -549,14 +549,14 @@ err:
|
||||
|
||||
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);
|
||||
kfree(ckey);
|
||||
}
|
||||
|
||||
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);
|
||||
kfree(ckey);
|
||||
|
@ -122,7 +122,7 @@ dns_resolver_preparse(struct key_preparsed_payload *prep)
|
||||
goto bad_option_value;
|
||||
|
||||
kdebug("dns error no. = %lu", derrno);
|
||||
prep->type_data[0] = ERR_PTR(-derrno);
|
||||
prep->payload.data[dns_key_error] = ERR_PTR(-derrno);
|
||||
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
|
||||
* result */
|
||||
if (prep->type_data[0]) {
|
||||
kleave(" = 0 [h_error %ld]", PTR_ERR(prep->type_data[0]));
|
||||
if (prep->payload.data[dns_key_error]) {
|
||||
kleave(" = 0 [h_error %ld]", PTR_ERR(prep->payload.data[dns_key_error]));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -155,7 +155,7 @@ dns_resolver_preparse(struct key_preparsed_payload *prep)
|
||||
memcpy(upayload->data, data, result_len);
|
||||
upayload->data[result_len] = '\0';
|
||||
|
||||
prep->payload[0] = upayload;
|
||||
prep->payload.data[dns_key_data] = upayload;
|
||||
kleave(" = 0");
|
||||
return 0;
|
||||
}
|
||||
@ -167,7 +167,7 @@ static void dns_resolver_free_preparse(struct key_preparsed_payload *prep)
|
||||
{
|
||||
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)
|
||||
{
|
||||
int err = key->type_data.x[0];
|
||||
|
||||
seq_puts(m, key->description);
|
||||
if (key_is_instantiated(key)) {
|
||||
int err = PTR_ERR(key->payload.data[dns_key_error]);
|
||||
|
||||
if (err)
|
||||
seq_printf(m, ": %d", err);
|
||||
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,
|
||||
char __user *buffer, size_t buflen)
|
||||
{
|
||||
if (key->type_data.x[0])
|
||||
return key->type_data.x[0];
|
||||
int err = PTR_ERR(key->payload.data[dns_key_error]);
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return user_read(key, buffer, buflen);
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ int dns_query(const char *type, const char *name, size_t namelen,
|
||||
const char *options, char **_result, time_t *_expiry)
|
||||
{
|
||||
struct key *rkey;
|
||||
struct user_key_payload *upayload;
|
||||
const struct user_key_payload *upayload;
|
||||
const struct cred *saved_cred;
|
||||
size_t typelen, desclen;
|
||||
char *desc, *cp;
|
||||
@ -137,12 +137,11 @@ int dns_query(const char *type, const char *name, size_t namelen,
|
||||
goto put;
|
||||
|
||||
/* 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)
|
||||
goto put;
|
||||
|
||||
upayload = rcu_dereference_protected(rkey->payload.data,
|
||||
lockdep_is_held(&rkey->sem));
|
||||
upayload = user_key_payload(rkey);
|
||||
len = upayload->datalen;
|
||||
|
||||
ret = -ENOMEM;
|
||||
|
@ -22,6 +22,14 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
/*
|
||||
* Layout of key payload words.
|
||||
*/
|
||||
enum {
|
||||
dns_key_data,
|
||||
dns_key_error,
|
||||
};
|
||||
|
||||
/*
|
||||
* dns_key.c
|
||||
*/
|
||||
|
@ -305,7 +305,7 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock,
|
||||
|
||||
if (!key)
|
||||
key = rx->key;
|
||||
if (key && !key->payload.data)
|
||||
if (key && !key->payload.data[0])
|
||||
key = NULL; /* a no-security key */
|
||||
|
||||
bundle = rxrpc_get_bundle(rx, trans, key, service_id, gfp);
|
||||
|
@ -148,10 +148,10 @@ static int rxrpc_preparse_xdr_rxkad(struct key_preparsed_payload *prep,
|
||||
token->kad->ticket[6], token->kad->ticket[7]);
|
||||
|
||||
/* 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 */
|
||||
for (pptoken = (struct rxrpc_key_token **)&prep->payload[0];
|
||||
for (pptoken = (struct rxrpc_key_token **)&prep->payload.data[0];
|
||||
*pptoken;
|
||||
pptoken = &(*pptoken)->next)
|
||||
continue;
|
||||
@ -522,7 +522,7 @@ static int rxrpc_preparse_xdr_rxk5(struct key_preparsed_payload *prep,
|
||||
goto inval;
|
||||
|
||||
/* 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)->next)
|
||||
continue;
|
||||
@ -764,10 +764,10 @@ static int rxrpc_preparse(struct key_preparsed_payload *prep)
|
||||
memcpy(&token->kad->ticket, v1->ticket, v1->ticket_length);
|
||||
|
||||
/* 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 */
|
||||
pp = (struct rxrpc_key_token **)&prep->payload[0];
|
||||
pp = (struct rxrpc_key_token **)&prep->payload.data[0];
|
||||
while (*pp)
|
||||
pp = &(*pp)->next;
|
||||
*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)
|
||||
{
|
||||
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)
|
||||
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);
|
||||
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)
|
||||
BUG();
|
||||
|
||||
prep->payload[0] = ci;
|
||||
prep->payload.data[0] = ci;
|
||||
_leave(" = 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)
|
||||
{
|
||||
if (prep->payload[0])
|
||||
crypto_free_blkcipher(prep->payload[0]);
|
||||
if (prep->payload.data[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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (key->payload.data) {
|
||||
crypto_free_blkcipher(key->payload.data);
|
||||
key->payload.data = NULL;
|
||||
if (key->payload.data[0]) {
|
||||
crypto_free_blkcipher(key->payload.data[0]);
|
||||
key->payload.data[0] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1070,7 +1070,7 @@ static long rxrpc_read(const struct key *key,
|
||||
size += 1 * 4; /* token count */
|
||||
|
||||
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 */
|
||||
|
||||
switch (token->security_index) {
|
||||
@ -1163,7 +1163,7 @@ static long rxrpc_read(const struct key *key,
|
||||
ENCODE(ntoks);
|
||||
|
||||
tok = 0;
|
||||
for (token = key->payload.data; token; token = token->next) {
|
||||
for (token = key->payload.data[0]; token; token = token->next) {
|
||||
toksize = toksizes[tok++];
|
||||
ENCODE(toksize);
|
||||
oldxdr = xdr;
|
||||
|
@ -158,7 +158,7 @@ int rxrpc_client_sendmsg(struct rxrpc_sock *rx, struct rxrpc_transport *trans,
|
||||
service_id = htons(srx->srx_service);
|
||||
}
|
||||
key = rx->key;
|
||||
if (key && !rx->key->payload.data)
|
||||
if (key && !rx->key->payload.data[0])
|
||||
key = NULL;
|
||||
bundle = rxrpc_get_bundle(rx, trans, key, service_id,
|
||||
GFP_KERNEL);
|
||||
|
@ -137,9 +137,9 @@ int rxrpc_init_client_conn_security(struct rxrpc_connection *conn)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (!key->payload.data)
|
||||
token = key->payload.data[0];
|
||||
if (!token)
|
||||
return -EKEYREJECTED;
|
||||
token = key->payload.data;
|
||||
|
||||
sec = rxrpc_security_lookup(token->security_index);
|
||||
if (!sec)
|
||||
|
@ -67,7 +67,7 @@ static int rxkad_init_connection_security(struct rxrpc_connection *conn)
|
||||
|
||||
_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;
|
||||
|
||||
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)
|
||||
return;
|
||||
|
||||
token = conn->key->payload.data;
|
||||
token = conn->key->payload.data[0];
|
||||
memcpy(&iv, token->kad->session_key, sizeof(iv));
|
||||
|
||||
desc.tfm = conn->cipher;
|
||||
@ -221,7 +221,7 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call,
|
||||
rxkhdr.checksum = 0;
|
||||
|
||||
/* 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));
|
||||
desc.tfm = call->conn->cipher;
|
||||
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);
|
||||
|
||||
/* 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));
|
||||
desc.tfm = call->conn->cipher;
|
||||
desc.info = iv.x;
|
||||
@ -780,7 +780,7 @@ static int rxkad_respond_to_challenge(struct rxrpc_connection *conn,
|
||||
if (conn->security_level < min_level)
|
||||
goto protocol_error;
|
||||
|
||||
token = conn->key->payload.data;
|
||||
token = conn->key->payload.data[0];
|
||||
|
||||
/* build the response packet */
|
||||
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);
|
||||
|
||||
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.flags = 0;
|
||||
|
||||
|
136
scripts/extract-module-sig.pl
Executable file
136
scripts/extract-module-sig.pl
Executable file
@ -0,0 +1,136 @@
|
||||
#!/usr/bin/perl -w
|
||||
#
|
||||
# extract-mod-sig <part> <module-file>
|
||||
#
|
||||
# Reads the module file and writes out some or all of the signature
|
||||
# section to stdout. Part is the bit to be written and is one of:
|
||||
#
|
||||
# -0: The unsigned module, no signature data at all
|
||||
# -a: All of the signature data, including magic number
|
||||
# -d: Just the descriptor values as a sequence of numbers
|
||||
# -n: Just the signer's name
|
||||
# -k: Just the key ID
|
||||
# -s: Just the crypto signature or PKCS#7 message
|
||||
#
|
||||
use strict;
|
||||
|
||||
die "Format: $0 -[0adnks] module-file >out\n"
|
||||
if ($#ARGV != 1);
|
||||
|
||||
my $part = $ARGV[0];
|
||||
my $modfile = $ARGV[1];
|
||||
|
||||
my $magic_number = "~Module signature appended~\n";
|
||||
|
||||
#
|
||||
# Read the module contents
|
||||
#
|
||||
open FD, "<$modfile" || die $modfile;
|
||||
binmode(FD);
|
||||
my @st = stat(FD);
|
||||
die "$modfile" unless (@st);
|
||||
my $buf = "";
|
||||
my $len = sysread(FD, $buf, $st[7]);
|
||||
die "$modfile" unless (defined($len));
|
||||
die "Short read on $modfile\n" unless ($len == $st[7]);
|
||||
close(FD) || die $modfile;
|
||||
|
||||
print STDERR "Read ", $len, " bytes from module file\n";
|
||||
|
||||
die "The file is too short to have a sig magic number and descriptor\n"
|
||||
if ($len < 12 + length($magic_number));
|
||||
|
||||
#
|
||||
# Check for the magic number and extract the information block
|
||||
#
|
||||
my $p = $len - length($magic_number);
|
||||
my $raw_magic = substr($buf, $p);
|
||||
|
||||
die "Magic number not found at $len\n"
|
||||
if ($raw_magic ne $magic_number);
|
||||
print STDERR "Found magic number at $len\n";
|
||||
|
||||
$p -= 12;
|
||||
my $raw_info = substr($buf, $p, 12);
|
||||
|
||||
my @info = unpack("CCCCCxxxN", $raw_info);
|
||||
my ($algo, $hash, $id_type, $name_len, $kid_len, $sig_len) = @info;
|
||||
|
||||
if ($id_type == 0) {
|
||||
print STDERR "Found PGP key identifier\n";
|
||||
} elsif ($id_type == 1) {
|
||||
print STDERR "Found X.509 cert identifier\n";
|
||||
} elsif ($id_type == 2) {
|
||||
print STDERR "Found PKCS#7/CMS encapsulation\n";
|
||||
} else {
|
||||
print STDERR "Found unsupported identifier type $id_type\n";
|
||||
}
|
||||
|
||||
#
|
||||
# Extract the three pieces of info data
|
||||
#
|
||||
die "Insufficient name+kid+sig data in file\n"
|
||||
unless ($p >= $name_len + $kid_len + $sig_len);
|
||||
|
||||
$p -= $sig_len;
|
||||
my $raw_sig = substr($buf, $p, $sig_len);
|
||||
$p -= $kid_len;
|
||||
my $raw_kid = substr($buf, $p, $kid_len);
|
||||
$p -= $name_len;
|
||||
my $raw_name = substr($buf, $p, $name_len);
|
||||
|
||||
my $module_len = $p;
|
||||
|
||||
if ($sig_len > 0) {
|
||||
print STDERR "Found $sig_len bytes of signature [";
|
||||
my $n = $sig_len > 16 ? 16 : $sig_len;
|
||||
foreach my $i (unpack("C" x $n, substr($raw_sig, 0, $n))) {
|
||||
printf STDERR "%02x", $i;
|
||||
}
|
||||
print STDERR "]\n";
|
||||
}
|
||||
|
||||
if ($kid_len > 0) {
|
||||
print STDERR "Found $kid_len bytes of key identifier [";
|
||||
my $n = $kid_len > 16 ? 16 : $kid_len;
|
||||
foreach my $i (unpack("C" x $n, substr($raw_kid, 0, $n))) {
|
||||
printf STDERR "%02x", $i;
|
||||
}
|
||||
print STDERR "]\n";
|
||||
}
|
||||
|
||||
if ($name_len > 0) {
|
||||
print STDERR "Found $name_len bytes of signer's name [$raw_name]\n";
|
||||
}
|
||||
|
||||
#
|
||||
# Produce the requested output
|
||||
#
|
||||
if ($part eq "-0") {
|
||||
# The unsigned module, no signature data at all
|
||||
binmode(STDOUT);
|
||||
print substr($buf, 0, $module_len);
|
||||
} elsif ($part eq "-a") {
|
||||
# All of the signature data, including magic number
|
||||
binmode(STDOUT);
|
||||
print substr($buf, $module_len);
|
||||
} elsif ($part eq "-d") {
|
||||
# Just the descriptor values as a sequence of numbers
|
||||
print join(" ", @info), "\n";
|
||||
} elsif ($part eq "-n") {
|
||||
# Just the signer's name
|
||||
print STDERR "No signer's name for PKCS#7 message type sig\n"
|
||||
if ($id_type == 2);
|
||||
binmode(STDOUT);
|
||||
print $raw_name;
|
||||
} elsif ($part eq "-k") {
|
||||
# Just the key identifier
|
||||
print STDERR "No key ID for PKCS#7 message type sig\n"
|
||||
if ($id_type == 2);
|
||||
binmode(STDOUT);
|
||||
print $raw_kid;
|
||||
} elsif ($part eq "-s") {
|
||||
# Just the crypto signature or PKCS#7 message
|
||||
binmode(STDOUT);
|
||||
print $raw_sig;
|
||||
}
|
144
scripts/extract-sys-certs.pl
Executable file
144
scripts/extract-sys-certs.pl
Executable file
@ -0,0 +1,144 @@
|
||||
#!/usr/bin/perl -w
|
||||
#
|
||||
use strict;
|
||||
use Math::BigInt;
|
||||
use Fcntl "SEEK_SET";
|
||||
|
||||
die "Format: $0 [-s <systemmap-file>] <vmlinux-file> <keyring-file>\n"
|
||||
if ($#ARGV != 1 && $#ARGV != 3 ||
|
||||
$#ARGV == 3 && $ARGV[0] ne "-s");
|
||||
|
||||
my $sysmap = "";
|
||||
if ($#ARGV == 3) {
|
||||
shift;
|
||||
$sysmap = $ARGV[0];
|
||||
shift;
|
||||
}
|
||||
|
||||
my $vmlinux = $ARGV[0];
|
||||
my $keyring = $ARGV[1];
|
||||
|
||||
#
|
||||
# Parse the vmlinux section table
|
||||
#
|
||||
open FD, "objdump -h $vmlinux |" || die $vmlinux;
|
||||
my @lines = <FD>;
|
||||
close(FD) || die $vmlinux;
|
||||
|
||||
my @sections = ();
|
||||
|
||||
foreach my $line (@lines) {
|
||||
chomp($line);
|
||||
if ($line =~ /\s*([0-9]+)\s+(\S+)\s+([0-9a-f]+)\s+([0-9a-f]+)\s+([0-9a-f]+)\s+([0-9a-f]+)\s+2[*][*]([0-9]+)/
|
||||
) {
|
||||
my $seg = $1;
|
||||
my $name = $2;
|
||||
my $len = Math::BigInt->new("0x" . $3);
|
||||
my $vma = Math::BigInt->new("0x" . $4);
|
||||
my $lma = Math::BigInt->new("0x" . $5);
|
||||
my $foff = Math::BigInt->new("0x" . $6);
|
||||
my $align = 2 ** $7;
|
||||
|
||||
push @sections, { name => $name,
|
||||
vma => $vma,
|
||||
len => $len,
|
||||
foff => $foff };
|
||||
}
|
||||
}
|
||||
|
||||
print "Have $#sections sections\n";
|
||||
|
||||
#
|
||||
# Try and parse the vmlinux symbol table. If the vmlinux file has been created
|
||||
# from a vmlinuz file with extract-vmlinux then the symbol table will be empty.
|
||||
#
|
||||
open FD, "nm $vmlinux 2>/dev/null |" || die $vmlinux;
|
||||
@lines = <FD>;
|
||||
close(FD) || die $vmlinux;
|
||||
|
||||
my %symbols = ();
|
||||
my $nr_symbols = 0;
|
||||
|
||||
sub parse_symbols(@) {
|
||||
foreach my $line (@_) {
|
||||
chomp($line);
|
||||
if ($line =~ /([0-9a-f]+)\s([a-zA-Z])\s(\S+)/
|
||||
) {
|
||||
my $addr = "0x" . $1;
|
||||
my $type = $2;
|
||||
my $name = $3;
|
||||
|
||||
$symbols{$name} = $addr;
|
||||
$nr_symbols++;
|
||||
}
|
||||
}
|
||||
}
|
||||
parse_symbols(@lines);
|
||||
|
||||
if ($nr_symbols == 0 && $sysmap ne "") {
|
||||
print "No symbols in vmlinux, trying $sysmap\n";
|
||||
|
||||
open FD, "<$sysmap" || die $sysmap;
|
||||
@lines = <FD>;
|
||||
close(FD) || die $sysmap;
|
||||
parse_symbols(@lines);
|
||||
}
|
||||
|
||||
die "No symbols available\n"
|
||||
if ($nr_symbols == 0);
|
||||
|
||||
print "Have $nr_symbols symbols\n";
|
||||
|
||||
die "Can't find system certificate list"
|
||||
unless (exists($symbols{"__cert_list_start"}) &&
|
||||
exists($symbols{"__cert_list_end"}));
|
||||
|
||||
my $start = Math::BigInt->new($symbols{"__cert_list_start"});
|
||||
my $end = Math::BigInt->new($symbols{"__cert_list_end"});
|
||||
my $size = $end - $start;
|
||||
|
||||
printf "Have %u bytes of certs at VMA 0x%x\n", $size, $start;
|
||||
|
||||
my $s = undef;
|
||||
foreach my $sec (@sections) {
|
||||
my $s_name = $sec->{name};
|
||||
my $s_vma = $sec->{vma};
|
||||
my $s_len = $sec->{len};
|
||||
my $s_foff = $sec->{foff};
|
||||
my $s_vend = $s_vma + $s_len;
|
||||
|
||||
next unless ($start >= $s_vma);
|
||||
next if ($start >= $s_vend);
|
||||
|
||||
die "Cert object partially overflows section $s_name\n"
|
||||
if ($end > $s_vend);
|
||||
|
||||
die "Cert object in multiple sections: ", $s_name, " and ", $s->{name}, "\n"
|
||||
if ($s);
|
||||
$s = $sec;
|
||||
}
|
||||
|
||||
die "Cert object not inside a section\n"
|
||||
unless ($s);
|
||||
|
||||
print "Certificate list in section ", $s->{name}, "\n";
|
||||
|
||||
my $foff = $start - $s->{vma} + $s->{foff};
|
||||
|
||||
printf "Certificate list at file offset 0x%x\n", $foff;
|
||||
|
||||
open FD, "<$vmlinux" || die $vmlinux;
|
||||
binmode(FD);
|
||||
die $vmlinux if (!defined(sysseek(FD, $foff, SEEK_SET)));
|
||||
my $buf = "";
|
||||
my $len = sysread(FD, $buf, $size);
|
||||
die "$vmlinux" if (!defined($len));
|
||||
die "Short read on $vmlinux\n" if ($len != $size);
|
||||
close(FD) || die $vmlinux;
|
||||
|
||||
open FD, ">$keyring" || die $keyring;
|
||||
binmode(FD);
|
||||
$len = syswrite(FD, $buf, $size);
|
||||
die "$keyring" if (!defined($len));
|
||||
die "Short write on $keyring\n" if ($len != $size);
|
||||
close(FD) || die $keyring;
|
@ -247,7 +247,7 @@ int evm_init_key(void)
|
||||
return -ENOENT;
|
||||
|
||||
down_read(&evm_key->sem);
|
||||
ekp = evm_key->payload.data;
|
||||
ekp = evm_key->payload.data[0];
|
||||
if (ekp->decrypted_datalen > MAX_KEY_SIZE) {
|
||||
rc = -EINVAL;
|
||||
goto out;
|
||||
|
@ -20,6 +20,16 @@
|
||||
|
||||
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
|
||||
* 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)
|
||||
{
|
||||
struct path *path = (struct path *)&prep->payload;
|
||||
struct path *path = (struct path *)&prep->payload.data[big_key_path];
|
||||
struct file *file;
|
||||
ssize_t written;
|
||||
size_t datalen = prep->datalen;
|
||||
@ -60,7 +70,7 @@ int big_key_preparse(struct key_preparsed_payload *prep)
|
||||
/* Set an arbitrary quota */
|
||||
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) {
|
||||
/* 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)
|
||||
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;
|
||||
|
||||
@ -110,10 +121,10 @@ error:
|
||||
void big_key_free_preparse(struct key_preparsed_payload *prep)
|
||||
{
|
||||
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);
|
||||
} 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)
|
||||
{
|
||||
struct path *path = (struct path *)&key->payload.data2;
|
||||
struct path *path = (struct path *)&key->payload.data[big_key_path];
|
||||
|
||||
/* clear the quota */
|
||||
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);
|
||||
}
|
||||
|
||||
@ -136,14 +148,16 @@ void big_key_revoke(struct key *key)
|
||||
*/
|
||||
void big_key_destroy(struct key *key)
|
||||
{
|
||||
if (key->type_data.x[1] > BIG_KEY_FILE_THRESHOLD) {
|
||||
struct path *path = (struct path *)&key->payload.data2;
|
||||
size_t datalen = (size_t)key->payload.data[big_key_len];
|
||||
|
||||
if (datalen) {
|
||||
struct path *path = (struct path *)&key->payload.data[big_key_path];
|
||||
path_put(path);
|
||||
path->mnt = NULL;
|
||||
path->dentry = NULL;
|
||||
} else {
|
||||
kfree(key->payload.data);
|
||||
key->payload.data = NULL;
|
||||
kfree(key->payload.data[big_key_data]);
|
||||
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)
|
||||
{
|
||||
unsigned long datalen = key->type_data.x[1];
|
||||
size_t datalen = (size_t)key->payload.data[big_key_len];
|
||||
|
||||
seq_puts(m, key->description);
|
||||
|
||||
if (key_is_instantiated(key))
|
||||
seq_printf(m, ": %lu [%s]",
|
||||
seq_printf(m, ": %zu [%s]",
|
||||
datalen,
|
||||
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)
|
||||
{
|
||||
unsigned long datalen = key->type_data.x[1];
|
||||
size_t datalen = (size_t)key->payload.data[big_key_len];
|
||||
long ret;
|
||||
|
||||
if (!buffer || buflen < datalen)
|
||||
return datalen;
|
||||
|
||||
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;
|
||||
loff_t pos;
|
||||
|
||||
@ -190,7 +204,8 @@ long big_key_read(const struct key *key, char __user *buffer, size_t buflen)
|
||||
ret = -EIO;
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -303,10 +303,10 @@ out:
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
struct user_key_payload *upayload;
|
||||
const struct user_key_payload *upayload;
|
||||
struct key *ukey;
|
||||
|
||||
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;
|
||||
|
||||
down_read(&ukey->sem);
|
||||
upayload = ukey->payload.data;
|
||||
upayload = user_key_payload(ukey);
|
||||
*master_key = upayload->data;
|
||||
*master_keylen = upayload->datalen;
|
||||
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,
|
||||
u8 **master_key, size_t *master_keylen)
|
||||
const u8 **master_key, size_t *master_keylen)
|
||||
{
|
||||
struct key *mkey = NULL;
|
||||
|
||||
@ -653,7 +653,7 @@ static int encrypted_key_decrypt(struct encrypted_key_payload *epayload,
|
||||
{
|
||||
struct key *mkey;
|
||||
u8 derived_key[HASH_SIZE];
|
||||
u8 *master_key;
|
||||
const u8 *master_key;
|
||||
u8 *hmac;
|
||||
const char *hex_encoded_data;
|
||||
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)
|
||||
{
|
||||
struct encrypted_key_payload *epayload = key->payload.data;
|
||||
struct encrypted_key_payload *epayload = key->payload.data[0];
|
||||
struct encrypted_key_payload *new_epayload;
|
||||
char *buf;
|
||||
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 key *mkey;
|
||||
u8 *master_key;
|
||||
const u8 *master_key;
|
||||
size_t master_keylen;
|
||||
char derived_key[HASH_SIZE];
|
||||
char *ascii_buf;
|
||||
@ -957,13 +957,13 @@ out:
|
||||
*/
|
||||
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)
|
||||
return;
|
||||
|
||||
memset(epayload->decrypted_data, 0, epayload->decrypted_datalen);
|
||||
kfree(key->payload.data);
|
||||
kfree(key->payload.data[0]);
|
||||
}
|
||||
|
||||
struct key_type key_type_encrypted = {
|
||||
|
@ -5,10 +5,10 @@
|
||||
#if defined(CONFIG_TRUSTED_KEYS) || \
|
||||
(defined(CONFIG_TRUSTED_KEYS_MODULE) && defined(CONFIG_ENCRYPTED_KEYS_MODULE))
|
||||
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
|
||||
static inline struct key *request_trusted_key(const char *trusted_desc,
|
||||
u8 **master_key,
|
||||
const u8 **master_key,
|
||||
size_t *master_keylen)
|
||||
{
|
||||
return ERR_PTR(-EOPNOTSUPP);
|
||||
|
@ -29,7 +29,7 @@
|
||||
* data, trusted key type data is not visible decrypted from userspace.
|
||||
*/
|
||||
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 key *tkey;
|
||||
@ -39,7 +39,7 @@ struct key *request_trusted_key(const char *trusted_desc,
|
||||
goto error;
|
||||
|
||||
down_read(&tkey->sem);
|
||||
tpayload = tkey->payload.data;
|
||||
tpayload = tkey->payload.data[0];
|
||||
*master_key = tpayload->key;
|
||||
*master_keylen = tpayload->key_len;
|
||||
error:
|
||||
|
@ -278,7 +278,7 @@ struct key *key_alloc(struct key_type *type, const char *desc,
|
||||
|
||||
key->index_key.desc_len = desclen;
|
||||
key->index_key.description = kmemdup(desc, desclen + 1, GFP_KERNEL);
|
||||
if (!key->description)
|
||||
if (!key->index_key.description)
|
||||
goto no_memory_3;
|
||||
|
||||
atomic_set(&key->usage, 1);
|
||||
@ -554,7 +554,7 @@ int key_reject_and_link(struct key *key,
|
||||
if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) {
|
||||
/* mark the key as being negatively instantiated */
|
||||
atomic_inc(&key->user->nikeys);
|
||||
key->type_data.reject_error = -error;
|
||||
key->reject_error = -error;
|
||||
smp_wmb();
|
||||
set_bit(KEY_FLAG_NEGATIVE, &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);
|
||||
if (ret == 0) {
|
||||
key->type_data.p[0] = prep->type_data[0];
|
||||
key->type_data.p[1] = prep->type_data[1];
|
||||
rcu_assign_keypointer(key, prep->payload[0]);
|
||||
key->payload.data2[1] = prep->payload[1];
|
||||
prep->type_data[0] = NULL;
|
||||
prep->type_data[1] = NULL;
|
||||
prep->payload[0] = NULL;
|
||||
prep->payload[1] = NULL;
|
||||
rcu_assign_keypointer(key, prep->payload.data[0]);
|
||||
key->payload.data[1] = prep->payload.data[1];
|
||||
key->payload.data[2] = prep->payload.data[2];
|
||||
key->payload.data[3] = prep->payload.data[3];
|
||||
prep->payload.data[0] = NULL;
|
||||
prep->payload.data[1] = NULL;
|
||||
prep->payload.data[2] = NULL;
|
||||
prep->payload.data[3] = NULL;
|
||||
}
|
||||
pr_devel("<==%s() = %d\n", __func__, ret);
|
||||
return ret;
|
||||
|
@ -67,7 +67,6 @@ SYSCALL_DEFINE5(add_key, const char __user *, _type,
|
||||
char type[32], *description;
|
||||
void *payload;
|
||||
long ret;
|
||||
bool vm;
|
||||
|
||||
ret = -EINVAL;
|
||||
if (plen > 1024 * 1024 - 1)
|
||||
@ -98,14 +97,12 @@ SYSCALL_DEFINE5(add_key, const char __user *, _type,
|
||||
/* pull the payload in if one was supplied */
|
||||
payload = NULL;
|
||||
|
||||
vm = false;
|
||||
if (_payload) {
|
||||
ret = -ENOMEM;
|
||||
payload = kmalloc(plen, GFP_KERNEL | __GFP_NOWARN);
|
||||
if (!payload) {
|
||||
if (plen <= PAGE_SIZE)
|
||||
goto error2;
|
||||
vm = true;
|
||||
payload = vmalloc(plen);
|
||||
if (!payload)
|
||||
goto error2;
|
||||
@ -138,10 +135,7 @@ SYSCALL_DEFINE5(add_key, const char __user *, _type,
|
||||
|
||||
key_ref_put(keyring_ref);
|
||||
error3:
|
||||
if (!vm)
|
||||
kfree(payload);
|
||||
else
|
||||
vfree(payload);
|
||||
kvfree(payload);
|
||||
error2:
|
||||
kfree(description);
|
||||
error:
|
||||
@ -1033,7 +1027,7 @@ long keyctl_instantiate_key_common(key_serial_t id,
|
||||
if (!instkey)
|
||||
goto error;
|
||||
|
||||
rka = instkey->payload.data;
|
||||
rka = instkey->payload.data[0];
|
||||
if (rka->target_key->serial != id)
|
||||
goto error;
|
||||
|
||||
@ -1200,7 +1194,7 @@ long keyctl_reject_key(key_serial_t id, unsigned timeout, unsigned error,
|
||||
if (!instkey)
|
||||
goto error;
|
||||
|
||||
rka = instkey->payload.data;
|
||||
rka = instkey->payload.data[0];
|
||||
if (rka->target_key->serial != id)
|
||||
goto error;
|
||||
|
||||
|
@ -118,7 +118,7 @@ static void keyring_publish_name(struct key *keyring)
|
||||
if (!keyring_name_hash[bucket].next)
|
||||
INIT_LIST_HEAD(&keyring_name_hash[bucket]);
|
||||
|
||||
list_add_tail(&keyring->type_data.link,
|
||||
list_add_tail(&keyring->name_link,
|
||||
&keyring_name_hash[bucket]);
|
||||
|
||||
write_unlock(&keyring_name_lock);
|
||||
@ -387,9 +387,9 @@ static void keyring_destroy(struct key *keyring)
|
||||
if (keyring->description) {
|
||||
write_lock(&keyring_name_lock);
|
||||
|
||||
if (keyring->type_data.link.next != NULL &&
|
||||
!list_empty(&keyring->type_data.link))
|
||||
list_del(&keyring->type_data.link);
|
||||
if (keyring->name_link.next != NULL &&
|
||||
!list_empty(&keyring->name_link))
|
||||
list_del(&keyring->name_link);
|
||||
|
||||
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 */
|
||||
if (kflags & (1 << KEY_FLAG_NEGATIVE)) {
|
||||
smp_rmb();
|
||||
ctx->result = ERR_PTR(key->type_data.reject_error);
|
||||
ctx->result = ERR_PTR(key->reject_error);
|
||||
kleave(" = %d [neg]", ctx->skipped_ret);
|
||||
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 */
|
||||
list_for_each_entry(keyring,
|
||||
&keyring_name_hash[bucket],
|
||||
type_data.link
|
||||
name_link
|
||||
) {
|
||||
if (!kuid_has_mapping(current_user_ns(), keyring->user->uid))
|
||||
continue;
|
||||
|
@ -457,7 +457,7 @@ key_ref_t search_process_keyrings(struct keyring_search_context *ctx)
|
||||
down_read(&cred->request_key_auth->sem);
|
||||
|
||||
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;
|
||||
key_ref = search_process_keyrings(ctx);
|
||||
@ -647,7 +647,7 @@ try_again:
|
||||
key_ref = ERR_PTR(-EKEYREVOKED);
|
||||
key = NULL;
|
||||
} else {
|
||||
rka = ctx.cred->request_key_auth->payload.data;
|
||||
rka = ctx.cred->request_key_auth->payload.data[0];
|
||||
key = rka->dest_keyring;
|
||||
__key_get(key);
|
||||
}
|
||||
|
@ -271,7 +271,7 @@ static void construct_get_dest_keyring(struct key **_dest_keyring)
|
||||
if (cred->request_key_auth) {
|
||||
authkey = cred->request_key_auth;
|
||||
down_read(&authkey->sem);
|
||||
rka = authkey->payload.data;
|
||||
rka = authkey->payload.data[0];
|
||||
if (!test_bit(KEY_FLAG_REVOKED,
|
||||
&authkey->flags))
|
||||
dest_keyring =
|
||||
@ -593,7 +593,7 @@ int wait_for_key_construction(struct key *key, bool intr)
|
||||
return -ERESTARTSYS;
|
||||
if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) {
|
||||
smp_rmb();
|
||||
return key->type_data.reject_error;
|
||||
return key->reject_error;
|
||||
}
|
||||
return key_validate(key);
|
||||
}
|
||||
|
@ -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,
|
||||
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;
|
||||
}
|
||||
|
||||
@ -69,7 +69,7 @@ static int request_key_auth_instantiate(struct key *key,
|
||||
static void request_key_auth_describe(const struct key *key,
|
||||
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->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,
|
||||
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;
|
||||
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)
|
||||
{
|
||||
struct request_key_auth *rka = key->payload.data;
|
||||
struct request_key_auth *rka = key->payload.data[0];
|
||||
|
||||
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)
|
||||
{
|
||||
struct request_key_auth *rka = key->payload.data;
|
||||
struct request_key_auth *rka = key->payload.data[0];
|
||||
|
||||
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))
|
||||
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->pid = irka->pid;
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
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_options *new_o;
|
||||
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)
|
||||
{
|
||||
struct trusted_key_payload *p = key->payload.data;
|
||||
struct trusted_key_payload *p = key->payload.data[0];
|
||||
|
||||
if (!p)
|
||||
return;
|
||||
memset(p->key, 0, p->key_len);
|
||||
kfree(key->payload.data);
|
||||
kfree(key->payload.data[0]);
|
||||
}
|
||||
|
||||
struct key_type key_type_trusted = {
|
||||
|
@ -74,7 +74,7 @@ int user_preparse(struct key_preparsed_payload *prep)
|
||||
|
||||
/* attach the data */
|
||||
prep->quotalen = datalen;
|
||||
prep->payload[0] = upayload;
|
||||
prep->payload.data[0] = upayload;
|
||||
upayload->datalen = datalen;
|
||||
memcpy(upayload->data, prep->data, datalen);
|
||||
return 0;
|
||||
@ -86,7 +86,7 @@ EXPORT_SYMBOL_GPL(user_preparse);
|
||||
*/
|
||||
void user_free_preparse(struct key_preparsed_payload *prep)
|
||||
{
|
||||
kfree(prep->payload[0]);
|
||||
kfree(prep->payload.data[0]);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(user_free_preparse);
|
||||
|
||||
@ -120,7 +120,7 @@ int user_update(struct key *key, struct key_preparsed_payload *prep)
|
||||
|
||||
if (ret == 0) {
|
||||
/* attach the new data, displacing the old */
|
||||
zap = key->payload.data;
|
||||
zap = key->payload.data[0];
|
||||
rcu_assign_keypointer(key, upayload);
|
||||
key->expiry = 0;
|
||||
}
|
||||
@ -140,7 +140,7 @@ EXPORT_SYMBOL_GPL(user_update);
|
||||
*/
|
||||
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 */
|
||||
key_payload_reserve(key, 0);
|
||||
@ -158,7 +158,7 @@ EXPORT_SYMBOL(user_revoke);
|
||||
*/
|
||||
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);
|
||||
}
|
||||
@ -183,10 +183,10 @@ EXPORT_SYMBOL_GPL(user_describe);
|
||||
*/
|
||||
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;
|
||||
|
||||
upayload = rcu_dereference_key(key);
|
||||
upayload = user_key_payload(key);
|
||||
ret = upayload->datalen;
|
||||
|
||||
/* we can return the data as is */
|
||||
|
Loading…
Reference in New Issue
Block a user