/* Large capacity key type
 *
 * Copyright (C) 2013 Red Hat, Inc. All Rights Reserved.
 * Written by David Howells (dhowells@redhat.com)
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public Licence
 * as published by the Free Software Foundation; either version
 * 2 of the Licence, or (at your option) any later version.
 */

#include <linux/module.h>
#include <linux/init.h>
#include <linux/seq_file.h>
#include <linux/file.h>
#include <linux/shmem_fs.h>
#include <linux/err.h>
#include <keys/user-type.h>
#include <keys/big_key-type.h>

MODULE_LICENSE("GPL");

/*
 * 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.
 */
#define BIG_KEY_FILE_THRESHOLD (sizeof(struct inode) + sizeof(struct dentry))

/*
 * big_key defined keys take an arbitrary string as the description and an
 * arbitrary blob of data as the payload
 */
struct key_type key_type_big_key = {
	.name			= "big_key",
	.def_lookup_type	= KEYRING_SEARCH_LOOKUP_DIRECT,
	.instantiate		= big_key_instantiate,
	.match			= user_match,
	.revoke			= big_key_revoke,
	.destroy		= big_key_destroy,
	.describe		= big_key_describe,
	.read			= big_key_read,
};

/*
 * Instantiate a big key
 */
int big_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
{
	struct path *path = (struct path *)&key->payload.data2;
	struct file *file;
	ssize_t written;
	size_t datalen = prep->datalen;
	int ret;

	ret = -EINVAL;
	if (datalen <= 0 || datalen > 1024 * 1024 || !prep->data)
		goto error;

	/* Set an arbitrary quota */
	ret = key_payload_reserve(key, 16);
	if (ret < 0)
		goto error;

	key->type_data.x[1] = datalen;

	if (datalen > BIG_KEY_FILE_THRESHOLD) {
		/* Create a shmem file to store the data in.  This will permit the data
		 * to be swapped out if needed.
		 *
		 * TODO: Encrypt the stored data with a temporary key.
		 */
		file = shmem_kernel_file_setup("", datalen, 0);
		if (IS_ERR(file)) {
			ret = PTR_ERR(file);
			goto err_quota;
		}

		written = kernel_write(file, prep->data, prep->datalen, 0);
		if (written != datalen) {
			ret = written;
			if (written >= 0)
				ret = -ENOMEM;
			goto err_fput;
		}

		/* Pin the mount and dentry to the key so that we can open it again
		 * later
		 */
		*path = file->f_path;
		path_get(path);
		fput(file);
	} else {
		/* Just store the data in a buffer */
		void *data = kmalloc(datalen, GFP_KERNEL);
		if (!data) {
			ret = -ENOMEM;
			goto err_quota;
		}

		key->payload.data = memcpy(data, prep->data, prep->datalen);
	}
	return 0;

err_fput:
	fput(file);
err_quota:
	key_payload_reserve(key, 0);
error:
	return ret;
}

/*
 * dispose of the links from a revoked keyring
 * - called with the key sem write-locked
 */
void big_key_revoke(struct key *key)
{
	struct path *path = (struct path *)&key->payload.data2;

	/* clear the quota */
	key_payload_reserve(key, 0);
	if (key_is_instantiated(key) && key->type_data.x[1] > BIG_KEY_FILE_THRESHOLD)
		vfs_truncate(path, 0);
}

/*
 * dispose of the data dangling from the corpse of a big_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;
		path_put(path);
		path->mnt = NULL;
		path->dentry = NULL;
	} else {
		kfree(key->payload.data);
		key->payload.data = NULL;
	}
}

/*
 * describe the big_key key
 */
void big_key_describe(const struct key *key, struct seq_file *m)
{
	unsigned long datalen = key->type_data.x[1];

	seq_puts(m, key->description);

	if (key_is_instantiated(key))
		seq_printf(m, ": %lu [%s]",
			   datalen,
			   datalen > BIG_KEY_FILE_THRESHOLD ? "file" : "buff");
}

/*
 * read the key data
 * - the key's semaphore is read-locked
 */
long big_key_read(const struct key *key, char __user *buffer, size_t buflen)
{
	unsigned long datalen = key->type_data.x[1];
	long ret;

	if (!buffer || buflen < datalen)
		return datalen;

	if (datalen > BIG_KEY_FILE_THRESHOLD) {
		struct path *path = (struct path *)&key->payload.data2;
		struct file *file;
		loff_t pos;

		file = dentry_open(path, O_RDONLY, current_cred());
		if (IS_ERR(file))
			return PTR_ERR(file);

		pos = 0;
		ret = vfs_read(file, buffer, datalen, &pos);
		fput(file);
		if (ret >= 0 && ret != datalen)
			ret = -EIO;
	} else {
		ret = datalen;
		if (copy_to_user(buffer, key->payload.data, datalen) != 0)
			ret = -EFAULT;
	}

	return ret;
}

/*
 * Module stuff
 */
static int __init big_key_init(void)
{
	return register_key_type(&key_type_big_key);
}

static void __exit big_key_cleanup(void)
{
	unregister_key_type(&key_type_big_key);
}

module_init(big_key_init);
module_exit(big_key_cleanup);
