Commit dddfa461 authored by Michael Halcrow's avatar Michael Halcrow Committed by Linus Torvalds

[PATCH] eCryptfs: Public key; packet management

Public key support code.  This reads and writes packets in the header that
contain public key encrypted file keys.  It calls the messaging code in the
previous patch to send and receive encryption and decryption request
packets from the userspace daemon.

[akpm@osdl.org: cleab fix]
Signed-off-by: default avatarMichael Halcrow <mhalcrow@us.ibm.com>
Cc: David Howells <dhowells@redhat.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 88b4a07e
......@@ -4,4 +4,4 @@
obj-$(CONFIG_ECRYPT_FS) += ecryptfs.o
ecryptfs-objs := dentry.o file.o inode.o main.o super.o mmap.o crypto.o keystore.o debug.o
ecryptfs-objs := dentry.o file.o inode.o main.o super.o mmap.o crypto.o keystore.o messaging.o netlink.o debug.o
......@@ -33,6 +33,7 @@
#include <linux/fs_stack.h>
#include <linux/namei.h>
#include <linux/scatterlist.h>
#include <linux/hash.h>
/* Version verification for shared data structures w/ userspace */
#define ECRYPTFS_VERSION_MAJOR 0x00
......@@ -47,7 +48,8 @@
#define ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH 0x00000004
#define ECRYPTFS_VERSIONING_POLICY 0x00000008
#define ECRYPTFS_VERSIONING_MASK (ECRYPTFS_VERSIONING_PASSPHRASE \
| ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH)
| ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH \
| ECRYPTFS_VERSIONING_PUBKEY)
#define ECRYPTFS_MAX_PASSWORD_LENGTH 64
#define ECRYPTFS_MAX_PASSPHRASE_BYTES ECRYPTFS_MAX_PASSWORD_LENGTH
......@@ -558,7 +560,8 @@ int ecryptfs_close_lower_file(struct file *lower_file);
int ecryptfs_process_helo(unsigned int transport, uid_t uid, pid_t pid);
int ecryptfs_process_quit(uid_t uid, pid_t pid);
int ecryptfs_process_response(struct ecryptfs_message *msg, pid_t pid, u32 seq);
int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t uid,
pid_t pid, u32 seq);
int ecryptfs_send_message(unsigned int transport, char *data, int data_len,
struct ecryptfs_msg_ctx **msg_ctx);
int ecryptfs_wait_for_response(struct ecryptfs_msg_ctx *msg_ctx,
......
This diff is collapsed.
......@@ -6,6 +6,7 @@
* Copyright (C) 2004-2006 International Business Machines Corp.
* Author(s): Michael A. Halcrow <mahalcro@us.ibm.com>
* Michael C. Thompson <mcthomps@us.ibm.com>
* Tyler Hicks <tyhicks@ou.edu>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
......@@ -48,6 +49,43 @@ MODULE_PARM_DESC(ecryptfs_verbosity,
"Initial verbosity level (0 or 1; defaults to "
"0, which is Quiet)");
/**
* Module parameter that defines the number of netlink message buffer
* elements
*/
unsigned int ecryptfs_message_buf_len = ECRYPTFS_DEFAULT_MSG_CTX_ELEMS;
module_param(ecryptfs_message_buf_len, uint, 0);
MODULE_PARM_DESC(ecryptfs_message_buf_len,
"Number of message buffer elements");
/**
* Module parameter that defines the maximum guaranteed amount of time to wait
* for a response through netlink. The actual sleep time will be, more than
* likely, a small amount greater than this specified value, but only less if
* the netlink message successfully arrives.
*/
signed long ecryptfs_message_wait_timeout = ECRYPTFS_MAX_MSG_CTX_TTL / HZ;
module_param(ecryptfs_message_wait_timeout, long, 0);
MODULE_PARM_DESC(ecryptfs_message_wait_timeout,
"Maximum number of seconds that an operation will "
"sleep while waiting for a message response from "
"userspace");
/**
* Module parameter that is an estimate of the maximum number of users
* that will be concurrently using eCryptfs. Set this to the right
* value to balance performance and memory use.
*/
unsigned int ecryptfs_number_of_users = ECRYPTFS_DEFAULT_NUM_USERS;
module_param(ecryptfs_number_of_users, uint, 0);
MODULE_PARM_DESC(ecryptfs_number_of_users, "An estimate of the number of "
"concurrent users of eCryptfs");
unsigned int ecryptfs_transport = ECRYPTFS_DEFAULT_TRANSPORT;
void __ecryptfs_printk(const char *fmt, ...)
{
va_list args;
......@@ -347,9 +385,10 @@ static int ecryptfs_parse_options(struct super_block *sb, char *options)
rc = -EINVAL;
goto out;
}
if (auth_tok->token_type != ECRYPTFS_PASSWORD) {
if (auth_tok->token_type != ECRYPTFS_PASSWORD
&& auth_tok->token_type != ECRYPTFS_PRIVATE_KEY) {
ecryptfs_printk(KERN_ERR, "Invalid auth_tok structure "
"returned from key\n");
"returned from key query\n");
rc = -EINVAL;
goto out;
}
......@@ -794,6 +833,11 @@ static int __init ecryptfs_init(void)
ecryptfs_free_kmem_caches();
goto out;
}
rc = ecryptfs_init_messaging(ecryptfs_transport);
if (rc) {
ecryptfs_printk(KERN_ERR, "Failure occured while attempting to "
"initialize the eCryptfs netlink socket\n");
}
out:
return rc;
}
......@@ -805,6 +849,7 @@ static void __exit ecryptfs_exit(void)
sysfs_remove_file(&ecryptfs_subsys.kset.kobj,
&sysfs_attr_version_str.attr);
subsystem_unregister(&ecryptfs_subsys);
ecryptfs_release_messaging(ecryptfs_transport);
unregister_filesystem(&ecryptfs_fs_type);
ecryptfs_free_kmem_caches();
}
......
......@@ -243,7 +243,8 @@ int ecryptfs_process_quit(uid_t uid, pid_t pid)
* userspace. Returns zero upon delivery to desired context element;
* non-zero upon delivery failure or error.
*/
int ecryptfs_process_response(struct ecryptfs_message *msg, pid_t pid, u32 seq)
int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t uid,
pid_t pid, u32 seq)
{
struct ecryptfs_daemon_id *id;
struct ecryptfs_msg_ctx *msg_ctx;
......@@ -268,6 +269,13 @@ int ecryptfs_process_response(struct ecryptfs_message *msg, pid_t pid, u32 seq)
msg_ctx->task->euid, pid);
goto wake_up;
}
if (msg_ctx->task->euid != uid) {
rc = -EBADMSG;
ecryptfs_printk(KERN_WARNING, "Received message from user "
"[%d]; expected message from user [%d]\n",
uid, msg_ctx->task->euid);
goto unlock;
}
if (id->pid != pid) {
rc = -EBADMSG;
ecryptfs_printk(KERN_ERR, "User [%d] received a "
......
......@@ -528,90 +528,6 @@ int ecryptfs_copy_page_to_lower(struct page *page, struct inode *lower_inode,
return rc;
}
static int
process_new_file(struct ecryptfs_crypt_stat *crypt_stat,
struct file *file, struct inode *inode)
{
struct page *header_page;
const struct address_space_operations *lower_a_ops;
struct inode *lower_inode;
struct file *lower_file;
char *header_virt;
int rc = 0;
int current_header_page = 0;
int header_pages;
int more_header_data_to_be_written = 1;
lower_inode = ecryptfs_inode_to_lower(inode);
lower_file = ecryptfs_file_to_lower(file);
lower_a_ops = lower_inode->i_mapping->a_ops;
header_pages = ((crypt_stat->header_extent_size
* crypt_stat->num_header_extents_at_front)
/ PAGE_CACHE_SIZE);
BUG_ON(header_pages < 1);
while (current_header_page < header_pages) {
rc = ecryptfs_grab_and_map_lower_page(&header_page,
&header_virt,
lower_inode,
current_header_page);
if (rc) {
ecryptfs_printk(KERN_ERR, "grab_cache_page for "
"header page [%d] failed; rc = [%d]\n",
current_header_page, rc);
goto out;
}
rc = lower_a_ops->prepare_write(lower_file, header_page, 0,
PAGE_CACHE_SIZE);
if (rc) {
ecryptfs_printk(KERN_ERR, "Error preparing to write "
"header page out; rc = [%d]\n", rc);
goto out;
}
memset(header_virt, 0, PAGE_CACHE_SIZE);
if (more_header_data_to_be_written) {
rc = ecryptfs_write_headers_virt(header_virt,
crypt_stat,
file->f_dentry);
if (rc) {
ecryptfs_printk(KERN_WARNING, "Error "
"generating header; rc = "
"[%d]\n", rc);
rc = -EIO;
memset(header_virt, 0, PAGE_CACHE_SIZE);
ecryptfs_unmap_and_release_lower_page(
header_page);
goto out;
}
if (current_header_page == 0)
memset(header_virt, 0, 8);
more_header_data_to_be_written = 0;
}
rc = lower_a_ops->commit_write(lower_file, header_page, 0,
PAGE_CACHE_SIZE);
ecryptfs_unmap_and_release_lower_page(header_page);
if (rc < 0) {
ecryptfs_printk(KERN_ERR,
"Error commiting header page write; "
"rc = [%d]\n", rc);
break;
}
current_header_page++;
}
if (rc >= 0) {
rc = 0;
ecryptfs_printk(KERN_DEBUG, "lower_inode->i_blocks = "
"[0x%.16x]\n", lower_inode->i_blocks);
i_size_write(inode, 0);
lower_inode->i_mtime = lower_inode->i_ctime = CURRENT_TIME;
mark_inode_dirty_sync(inode);
}
ecryptfs_printk(KERN_DEBUG, "Clearing ECRYPTFS_NEW_FILE flag in "
"crypt_stat at memory location [%p]\n", crypt_stat);
ECRYPTFS_CLEAR_FLAG(crypt_stat->flags, ECRYPTFS_NEW_FILE);
out:
return rc;
}
/**
* ecryptfs_commit_write
* @file: The eCryptfs file object
......@@ -643,12 +559,7 @@ static int ecryptfs_commit_write(struct file *file, struct page *page,
if (ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_NEW_FILE)) {
ecryptfs_printk(KERN_DEBUG, "ECRYPTFS_NEW_FILE flag set in "
"crypt_stat at memory location [%p]\n", crypt_stat);
rc = process_new_file(crypt_stat, file, inode);
if (rc) {
ecryptfs_printk(KERN_ERR, "Error processing new "
"file; rc = [%d]\n", rc);
goto out;
}
ECRYPTFS_CLEAR_FLAG(crypt_stat->flags, ECRYPTFS_NEW_FILE);
} else
ecryptfs_printk(KERN_DEBUG, "Not a new file\n");
ecryptfs_printk(KERN_DEBUG, "Calling fill_zeros_to_end_of_page"
......
......@@ -107,8 +107,8 @@ static int ecryptfs_process_nl_response(struct sk_buff *skb)
"incorrectly specified data length\n");
goto out;
}
rc = ecryptfs_process_response(msg, NETLINK_CREDS(skb)->pid,
nlh->nlmsg_seq);
rc = ecryptfs_process_response(msg, NETLINK_CREDS(skb)->uid,
NETLINK_CREDS(skb)->pid, nlh->nlmsg_seq);
if (rc)
printk(KERN_ERR
"Error processing response message; rc = [%d]\n", rc);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment