summaryrefslogtreecommitdiff
path: root/security/keys/big_key.c
diff options
context:
space:
mode:
authorAndré Fabian Silva Delgado <emulatorman@parabola.nu>2016-01-20 14:01:31 -0300
committerAndré Fabian Silva Delgado <emulatorman@parabola.nu>2016-01-20 14:01:31 -0300
commitb4b7ff4b08e691656c9d77c758fc355833128ac0 (patch)
tree82fcb00e6b918026dc9f2d1f05ed8eee83874cc0 /security/keys/big_key.c
parent35acfa0fc609f2a2cd95cef4a6a9c3a5c38f1778 (diff)
Linux-libre 4.4-gnupck-4.4-gnu
Diffstat (limited to 'security/keys/big_key.c')
-rw-r--r--security/keys/big_key.c47
1 files changed, 31 insertions, 16 deletions
diff --git a/security/keys/big_key.c b/security/keys/big_key.c
index f49a56bac..83dce8acf 100644
--- a/security/keys/big_key.c
+++ b/security/keys/big_key.c
@@ -21,6 +21,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
* least as large as the data.
@@ -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;
}