|
@@ -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) {
|
|
|
|
- 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_put(path);
|
|
path->mnt = NULL;
|
|
path->mnt = NULL;
|
|
path->dentry = NULL;
|
|
path->dentry = NULL;
|
|
} else {
|
|
} 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)
|
|
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;
|
|
}
|
|
}
|
|
|
|
|