eCryptfs: Introduce device handle for userspace daemon communications
Subsystems (2)
PATCH 1/2 eCryptfs: Introduce device handle for userspace daemon communications
Functions to facilitate reading and writing to the eCryptfs miscellaneous device handle. This will replace the netlink interface as the preferred mechanism for communicating with the userspace eCryptfs daemon.
Each user has his own daemon, which registers itself by opening the eCryptfs device handle. Only one daemon per euid may be registered at any given time. The eCryptfs module sends a message to a daemon by adding its message to the daemon's outgoing message queue. The daemon reads the device handle to get the oldest message off the queue.
Incoming messages from the userspace daemon are immediately handled. If the message is a response, then the corresponding process that is blocked waiting for the response is awakened.
--- fs/ecryptfs/miscdev.c | 580 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 580 insertions(+), 0 deletions(-) create mode 100644 fs/ecryptfs/miscdev.c
fs/ecryptfs/miscdev.c new file +580 -0
@@ -0,0 +1,580 @@ +/** +* eCryptfs: Linux filesystem encryption layer +* +* Copyright (C) 2008 International Business Machines Corp. +* Author(s): Michael A. Halcrow <[email protected]> +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License version +* 2 as published by the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but +* WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +* 02111-1307, USA. +*/ + +#include <linux/fs.h> +#include <linux/hash.h> +#include <linux/random.h> +#include <linux/miscdevice.h> +#include <linux/poll.h> +#include <linux/wait.h> +#include <linux/module.h> +#include "ecryptfs_kernel.h" + +static atomic_t ecryptfs_num_miscdev_opens; + +/** +* ecryptfs_miscdev_poll +* @file: dev file (ignored) +* @pt: dev poll table (ignored) +* +* Returns the poll mask +*/ +static unsigned int +ecryptfs_miscdev_poll (struct file *file,poll_table *pt) +{ +struct ecryptfs_daemon *daemon; +unsigned int mask =0 ; +int rc; + +mutex_lock (&ecryptfs_daemon_hash_mux); +/* TODO: Just use file->private_data? */ + rc =ecryptfs_find_daemon_by_euid (&daemon, current->euid); +BUG_ON (rc || !daemon); +mutex_lock (&daemon->mux); +mutex_unlock (&ecryptfs_daemon_hash_mux); +if (daemon->flags &ECRYPTFS_DAEMON_ZOMBIE ) { +printk (KERN_WARNING "%s: Attempt to poll on zombified " +"daemon\n" , __func__); + goto out_unlock_daemon; + } +if (daemon->flags &ECRYPTFS_DAEMON_IN_READ ) + goto out_unlock_daemon; +if (daemon->flags &ECRYPTFS_DAEMON_IN_POLL ) + goto out_unlock_daemon; + daemon->flags |=ECRYPTFS_DAEMON_IN_POLL ; +mutex_unlock (&daemon->mux); +poll_wait (file, &daemon->wait, pt); +mutex_lock (&daemon->mux); +if (!list_empty (&daemon->msg_ctx_out_queue)) + mask |=POLLIN |POLLRDNORM ; +out_unlock_daemon: + daemon->flags &= ~ECRYPTFS_DAEMON_IN_POLL ; +mutex_unlock (&daemon->mux); +return mask; +} + +/** +* ecryptfs_miscdev_open +* @inode: inode of miscdev handle (ignored) +* @file: file for miscdev handle (ignored) +* +* Returns zero on success; non-zero otherwise +*/ +static int +ecryptfs_miscdev_open (struct inode *inode,struct file *file) +{ +struct ecryptfs_daemon *daemon =NULL ; +int rc; + +mutex_lock (&ecryptfs_daemon_hash_mux); + rc =try_module_get (THIS_MODULE ); +if (rc ==0 ) { + rc = -EIO ; +printk (KERN_ERR "%s: Error attempting to increment module use " +"count; rc = [%d]\n" , __func__, rc); + goto out_unlock_daemon_list; + } + rc =ecryptfs_find_daemon_by_euid (&daemon, current->euid); +if (rc || !daemon) { + rc =ecryptfs_spawn_daemon (&daemon, current->euid, + current->pid); +if (rc) { +printk (KERN_ERR "%s: Error attempting to spawn daemon; " +"rc = [%d]\n" , __func__, rc); + goto out_module_put_unlock_daemon_list; + } + } +mutex_lock (&daemon->mux); +if (daemon->pid != current->pid) { + rc = -EINVAL ; +printk (KERN_ERR "%s: pid [%d] has registered with euid [%d], " +"but pid [%d] has attempted to open the handle " +"instead\n" , __func__, daemon->pid, daemon->euid, + current->pid); + goto out_unlock_daemon; + } +if (daemon->flags &ECRYPTFS_DAEMON_MISCDEV_OPEN ) { + rc = -EBUSY ; +printk (KERN_ERR "%s: Miscellaneous device handle may only be " +"opened once per daemon; pid [%d] already has this " +"handle open\n" , __func__, daemon->pid); + goto out_unlock_daemon; + } + daemon->flags |=ECRYPTFS_DAEMON_MISCDEV_OPEN ; +atomic_inc (&ecryptfs_num_miscdev_opens); +out_unlock_daemon: +mutex_unlock (&daemon->mux); +out_module_put_unlock_daemon_list: +if (rc) +module_put (THIS_MODULE ); +out_unlock_daemon_list: +mutex_unlock (&ecryptfs_daemon_hash_mux); +return rc; +} + +/** +* ecryptfs_miscdev_release +* @inode: inode of fs/ecryptfs/euid handle (ignored) +* @file: file for fs/ecryptfs/euid handle (ignored) +* +* This keeps the daemon registered until the daemon sends another +* ioctl to fs/ecryptfs/ctl or until the kernel module unregisters. +* +* Returns zero on success; non-zero otherwise +*/ +static int +ecryptfs_miscdev_release (struct inode *inode,struct file *file) +{ +struct ecryptfs_daemon *daemon =NULL ; +int rc; + +mutex_lock (&ecryptfs_daemon_hash_mux); + rc =ecryptfs_find_daemon_by_euid (&daemon, current->euid); +BUG_ON (rc || !daemon); +mutex_lock (&daemon->mux); +BUG_ON (daemon->pid != current->pid); +BUG_ON (!(daemon->flags &ECRYPTFS_DAEMON_MISCDEV_OPEN )); + daemon->flags &= ~ECRYPTFS_DAEMON_MISCDEV_OPEN ; +atomic_dec (&ecryptfs_num_miscdev_opens); +mutex_unlock (&daemon->mux); + rc =ecryptfs_exorcise_daemon (daemon); +if (rc) { +printk (KERN_CRIT "%s: Fatal error whilst attempting to " +"shut down daemon; rc = [%d]. Please report this " +"bug.\n" , __func__, rc); +BUG (); + } +module_put (THIS_MODULE ); +mutex_unlock (&ecryptfs_daemon_hash_mux); +return rc; +} + +/** +* ecryptfs_send_miscdev +* @data: Data to send to daemon; may be NULL +* @data_size: Amount of data to send to daemon +* @msg_ctx: Message context, which is used to handle the reply. If +* this is NULL, then we do not expect a reply. +* @msg_type: Type of message +* @msg_flags: Flags for message +* @daemon: eCryptfs daemon object +* +* Add msg_ctx to queue and then, if it exists, notify the blocked +* miscdevess about the data being available. Must be called with +* ecryptfs_daemon_hash_mux held. +* +* Returns zero on success; non-zero otherwise +*/ +int ecryptfs_send_miscdev (char *data,size_t data_size, +struct ecryptfs_msg_ctx *msg_ctx,u8 msg_type, +u16 msg_flags,struct ecryptfs_daemon *daemon) +{ +int rc =0 ; + +mutex_lock (&msg_ctx->mux); +if (data) { + msg_ctx->msg =kmalloc ((sizeof (*msg_ctx->msg) + data_size), +GFP_KERNEL ); +if (!msg_ctx->msg) { + rc = -ENOMEM ; +printk (KERN_ERR "%s: Out of memory whilst attempting " +"to kmalloc(%d, GFP_KERNEL)\n" , __func__, + (sizeof (*msg_ctx->msg) + data_size)); + goto out_unlock; + } + }else + msg_ctx->msg =NULL ; + msg_ctx->msg->index = msg_ctx->index; + msg_ctx->msg->data_len = data_size; + msg_ctx->type = msg_type; +if (data) { +memcpy (msg_ctx->msg->data, data, data_size); + msg_ctx->msg_size = (sizeof (*msg_ctx->msg) + data_size); + }else + msg_ctx->msg_size =0 ; +mutex_lock (&daemon->mux); +list_add_tail (&msg_ctx->daemon_out_list, &daemon->msg_ctx_out_queue); + daemon->num_queued_msg_ctx++; +wake_up_interruptible (&daemon->wait); +mutex_unlock (&daemon->mux); +out_unlock: +mutex_unlock (&msg_ctx->mux); +return rc; +} + +/** +* ecryptfs_miscdev_read - format and send message from queue +* @file: fs/ecryptfs/euid miscdevfs handle (ignored) +* @buf: User buffer into which to copy the next message on the daemon queue +* @count: Amount of space available in @buf +* @ppos: Offset in file (ignored) +* +* Pulls the most recent message from the daemon queue, formats it for +* being sent via a miscdevfs handle, and copies it into @buf +* +* Returns the number of bytes copied into the user buffer +*/ +static int +ecryptfs_miscdev_read (struct file *file,char __user *buf,size_t count, +loff_t *ppos) +{ +struct ecryptfs_daemon *daemon; +struct ecryptfs_msg_ctx *msg_ctx; +size_t packet_length_size; +u32 counter_nbo; +char packet_length[3 ]; +size_t i; +size_t total_length; +int rc; + +mutex_lock (&ecryptfs_daemon_hash_mux); +/* TODO: Just use file->private_data? */ + rc =ecryptfs_find_daemon_by_euid (&daemon, current->euid); +BUG_ON (rc || !daemon); +mutex_lock (&daemon->mux); +if (daemon->flags &ECRYPTFS_DAEMON_ZOMBIE ) { + rc =0 ; +printk (KERN_WARNING "%s: Attempt to read from zombified " +"daemon\n" , __func__); + goto out_unlock_daemon; + } +if (daemon->flags &ECRYPTFS_DAEMON_IN_READ ) { + rc =0 ; + goto out_unlock_daemon; + } +/* This daemon will not go away so long as this flag is set */ + daemon->flags |=ECRYPTFS_DAEMON_IN_READ ; +mutex_unlock (&ecryptfs_daemon_hash_mux); +check_list: +if (list_empty (&daemon->msg_ctx_out_queue)) { +mutex_unlock (&daemon->mux); + rc =wait_event_interruptible ( + daemon->wait, !list_empty (&daemon->msg_ctx_out_queue)); +mutex_lock (&daemon->mux); +if (rc <0 ) { + rc =0 ; + goto out_unlock_daemon; + } + } +if (daemon->flags &ECRYPTFS_DAEMON_ZOMBIE ) { + rc =0 ; + goto out_unlock_daemon; + } +if (list_empty (&daemon->msg_ctx_out_queue)) { +/* Something else jumped in since the +* wait_event_interruptable() and removed the +* message from the queue; try again */ + goto check_list; + } +BUG_ON (current->euid != daemon->euid); +BUG_ON (current->pid != daemon->pid); + msg_ctx =list_first_entry (&daemon->msg_ctx_out_queue, + struct ecryptfs_msg_ctx, daemon_out_list); +BUG_ON (!msg_ctx); +mutex_lock (&msg_ctx->mux); +if (msg_ctx->msg) { + rc =ecryptfs_write_packet_length (packet_length, + msg_ctx->msg_size, + &packet_length_size); +if (rc) { + rc =0 ; +printk (KERN_WARNING "%s: Error writing packet length; " +"rc = [%d]\n" , __func__, rc); + goto out_unlock_msg_ctx; + } + }else { + packet_length_size =0 ; + msg_ctx->msg_size =0 ; + } +/* miscdevfs packet format: +* Octet 0: Type +* Octets 1-4: network byte order msg_ctx->counter +* Octets 5-N0: Size of struct ecryptfs_message to follow +* Octets N0-N1: struct ecryptfs_message (including data) +* +* Octets 5-N1 not written if the packet type does not +* include a message */ + total_length = (1 +4 + packet_length_size + msg_ctx->msg_size); +if (count < total_length) { + rc =0 ; +printk (KERN_WARNING "%s: Only given user buffer of " +"size [%Zd], but we need [%Zd] to read the " +"pending message\n" , __func__, count, total_length); + goto out_unlock_msg_ctx; + } + i =0 ; + buf[i++] = msg_ctx->type; + counter_nbo =cpu_to_be32 (msg_ctx->counter); +memcpy (&buf[i], (char *)&counter_nbo,4 ); + i +=4 ; +if (msg_ctx->msg) { +memcpy (&buf[i], packet_length, packet_length_size); + i += packet_length_size; + rc =copy_to_user (&buf[i], msg_ctx->msg, msg_ctx->msg_size); +if (rc) { +printk (KERN_ERR "%s: copy_to_user returned error " +"[%d]\n" , __func__, rc); + goto out_unlock_msg_ctx; + } + i += msg_ctx->msg_size; + } + rc = i; +list_del (&msg_ctx->daemon_out_list); +kfree (msg_ctx->msg); + msg_ctx->msg =NULL ; +/* We do not expect a reply from the userspace daemon for any +* message type other than ECRYPTFS_MSG_REQUEST */ +if (msg_ctx->type !=ECRYPTFS_MSG_REQUEST ) +ecryptfs_msg_ctx_alloc_to_free (msg_ctx); +out_unlock_msg_ctx: +mutex_unlock (&msg_ctx->mux); +out_unlock_daemon: + daemon->flags &= ~ECRYPTFS_DAEMON_IN_READ ; +mutex_unlock (&daemon->mux); +return rc; +} + +/** +* ecryptfs_miscdev_helo +* @euid: effective user id of miscdevess sending helo packet +* @pid: miscdevess id of miscdevess sending helo packet +* +* Returns zero on success; non-zero otherwise +*/ +static int ecryptfs_miscdev_helo (uid_t uid,pid_t pid) +{ +int rc; + + rc =ecryptfs_process_helo (ECRYPTFS_TRANSPORT_MISCDEV , uid, pid); +if (rc) +printk (KERN_WARNING "Error processing HELO; rc = [%d]\n" , rc); +return rc; +} + +/** +* ecryptfs_miscdev_quit +* @euid: effective user id of miscdevess sending quit packet +* @pid: miscdevess id of miscdevess sending quit packet +* +* Returns zero on success; non-zero otherwise +*/ +static int ecryptfs_miscdev_quit (uid_t euid,pid_t pid) +{ +int rc; + + rc =ecryptfs_process_quit (euid, pid); +if (rc) +printk (KERN_WARNING +"Error processing QUIT message; rc = [%d]\n" , rc); +return rc; +} + +/** +* ecryptfs_miscdev_response - miscdevess response to message previously sent to daemon +* @data: Bytes comprising struct ecryptfs_message +* @data_size: sizeof(struct ecryptfs_message) + data len +* @euid: Effective user id of miscdevess sending the miscdev response +* @pid: Miscdevess id of miscdevess sending the miscdev response +* @seq: Sequence number for miscdev response packet +* +* Returns zero on success; non-zero otherwise +*/ +static int ecryptfs_miscdev_response (char *data,size_t data_size, +uid_t euid,pid_t pid,u32 seq) +{ +struct ecryptfs_message *msg = (struct ecryptfs_message *)data; +int rc; + +if ((sizeof (*msg) + msg->data_len) != data_size) { +printk (KERN_WARNING "%s: (sizeof(*msg) + msg->data_len) = " +"[%Zd]; data_size = [%Zd]. Invalid packet.\n" , __func__, + (sizeof (*msg) + msg->data_len), data_size); + rc = -EINVAL ; + goto out; + } + rc =ecryptfs_process_response (msg, euid, pid, seq); +if (rc) +printk (KERN_ERR +"Error processing response message; rc = [%d]\n" , rc); +out: +return rc; +} + +/** +* ecryptfs_miscdev_write - handle write to daemon miscdev handle +* @file: File for misc dev handle (ignored) +* @buf: Buffer containing user data +* @count: Amount of data in @buf +* @ppos: Pointer to offset in file (ignored) +* +* miscdevfs packet format: +* Octet 0: Type +* Octets 1-4: network byte order msg_ctx->counter (0's for non-response) +* Octets 5-N0: Size of struct ecryptfs_message to follow +* Octets N0-N1: struct ecryptfs_message (including data) +* +* Returns the number of bytes read from @buf +*/ +static ssize_t +ecryptfs_miscdev_write (struct file *file,const char __user *buf, +size_t count,loff_t *ppos) +{ +u32 counter_nbo, seq; +size_t packet_size, packet_size_length, i; +ssize_t sz =0 ; +char *data; +int rc; + +if (count ==0 ) + goto out; + data =kmalloc (count,GFP_KERNEL ); +if (!data) { +printk (KERN_ERR "%s: Out of memory whilst attempting to " +"kmalloc([%Zd], GFP_KERNEL)\n" , __func__, count); + goto out; + } + rc =copy_from_user (data, buf, count); +if (rc) { +printk (KERN_ERR "%s: copy_from_user returned error [%d]\n" , + __func__, rc); + goto out_free; + } + sz = count; + i =0 ; +switch (data[i++]) { +case ECRYPTFS_MSG_RESPONSE : +if (count < (1 +4 +1 +sizeof (struct ecryptfs_message ))) { +printk (KERN_WARNING "%s: Minimum acceptable packet " +"size is [%Zd], but amount of data written is " +"only [%Zd]. Discarding response packet.\n" , + __func__, + (1 +4 +1 +sizeof (struct ecryptfs_message )), + count); + goto out_free; + } +memcpy ((char *)&counter_nbo, &data[i],4 ); + seq =be32_to_cpu (counter_nbo); + i +=4 ; + rc =ecryptfs_parse_packet_length (&data[i], &packet_size, + &packet_size_length); +if (rc) { +printk (KERN_WARNING "%s: Error parsing packet length; " +"rc = [%d]\n" , __func__, rc); + goto out_free; + } + i += packet_size_length; +if ((1 +4 + packet_size_length + packet_size) != count) { +printk (KERN_WARNING "%s: (1 + packet_size_length([%Zd])" +" + packet_size([%Zd]))([%Zd]) != " +"count([%Zd]). Invalid packet format.\n" , + __func__, packet_size_length, packet_size, + (1 + packet_size_length + packet_size), count); + goto out_free; + } + rc =ecryptfs_miscdev_response (&data[i], packet_size, + current->euid, + current->pid, seq); +if (rc) +printk (KERN_WARNING "%s: Failed to deliver miscdev " +"response to requesting operation; rc = [%d]\n" , + __func__, rc); +break ; +case ECRYPTFS_MSG_HELO : + rc =ecryptfs_miscdev_helo (current->euid, current->pid); +if (rc) { +printk (KERN_ERR "%s: Error attempting to process " +"helo from pid [%d]; rc = [%d]\n" , __func__, + current->pid, rc); + goto out_free; + } +break ; +case ECRYPTFS_MSG_QUIT : + rc =ecryptfs_miscdev_quit (current->euid, current->pid); +if (rc) { +printk (KERN_ERR "%s: Error attempting to process " +"quit from pid [%d]; rc = [%d]\n" , __func__, + current->pid, rc); + goto out_free; + } +break ; +default : +ecryptfs_printk (KERN_WARNING ,"Dropping miscdev " +"message of unrecognized type [%d]\n" , + data[0 ]); +break ; + } +out_free: +kfree (data); +out: +return sz; +} + + +static const struct file_operations ecryptfs_miscdev_fops = { + .open = ecryptfs_miscdev_open, + .poll = ecryptfs_miscdev_poll, + .read = ecryptfs_miscdev_read, + .write = ecryptfs_miscdev_write, + .release = ecryptfs_miscdev_release, +}; + +static struct miscdevice ecryptfs_miscdev = { + .minor =MISC_DYNAMIC_MINOR , + .name ="ecryptfs" , + .fops = &ecryptfs_miscdev_fops +}; + +/** +* ecryptfs_init_ecryptfs_miscdev +* +* Messages sent to the userspace daemon from the kernel are placed on +* a queue associated with the daemon. The next read against the +* miscdev handle by that daemon will return the oldest message placed +* on the message queue for the daemon. +* +* Returns zero on success; non-zero otherwise +*/ +int ecryptfs_init_ecryptfs_miscdev (void ) +{ +int rc; + +atomic_set (&ecryptfs_num_miscdev_opens,0 ); +mutex_lock (&ecryptfs_daemon_hash_mux); + rc =misc_register (&ecryptfs_miscdev); +if (rc) +printk (KERN_ERR "%s: Failed to register miscellaneous device " +"for communications with userspace daemons; rc = [%d]\n" , + __func__, rc); +mutex_unlock (&ecryptfs_daemon_hash_mux); +return rc; +} + +/** +* ecryptfs_destroy_ecryptfs_miscdev +* +* All of the daemons must be exorcised prior to calling this +* function. +*/ +void ecryptfs_destroy_ecryptfs_miscdev (void ) +{ +BUG_ON (atomic_read (&ecryptfs_num_miscdev_opens) !=0 ); +misc_deregister (&ecryptfs_miscdev); +}
Signature · 1 line
1.5.1.6
PATCH 2/2 eCryptfs: Introduce device handle for userspace daemon communications
Integrate eCryptfs device handle into the module. Update the versioning information. Make the message types generic. Add an outgoing message queue to the daemon struct. Make the functions to parse and write the packet lengths available to the rest of the module. Add functions to create and destroy the daemon structs. Clean up some of the comments and make the code a little more consistent with itself.
--- fs/ecryptfs/Makefile | 2 +- fs/ecryptfs/ecryptfs_kernel.h | 79 ++++++-- fs/ecryptfs/keystore.c | 89 +++++---- fs/ecryptfs/messaging.c | 479 +++++++++++++++++++++++++++-------------- fs/ecryptfs/netlink.c | 8 +- 5 files changed, 433 insertions(+), 224 deletions(-)
fs/ecryptfs/Makefile +1 -1
@@ -4,4 +4,4 @@ obj-$(CONFIG_ECRYPT_FS) += ecryptfs.o -ecryptfs-objs := dentry.o file.o inode.o main.o super.o mmap.o read_write.o crypto.o keystore.o messaging.o netlink.o debug.o +ecryptfs-objs := dentry.o file.o inode.o main.o super.o mmap.o read_write.o crypto.o keystore.o messaging.o netlink.o miscdev.o debug.o
fs/ecryptfs/ecryptfs_kernel.h +61 -18
146 lines not on this page · raw message
fs/ecryptfs/keystore.c +49 -40
218 lines not on this page · raw message
fs/ecryptfs/messaging.c +318 -161
718 lines not on this page · raw message
fs/ecryptfs/netlink.c +4 -4
@@ -44,7 +44,7 @@ static struct sock *ecryptfs_nl_sock;* upon sending the message; non-zero upon error. */ int ecryptfs_send_netlink (char *data,int data_len, -struct ecryptfs_msg_ctx *msg_ctx,u16 msg_type, +struct ecryptfs_msg_ctx *msg_ctx,u8 msg_type,u16 msg_flags,pid_t daemon_pid) {struct sk_buff *skb;
@@ -176,20 +176,20 @@ static void ecryptfs_receive_nl_message(struct sk_buff *skb) goto free; }switch (nlh->nlmsg_type) { -case ECRYPTFS_NLMSG_RESPONSE : +case ECRYPTFS_MSG_RESPONSE :if (ecryptfs_process_nl_response (skb)) {ecryptfs_printk (KERN_WARNING ,"Failed to " "deliver netlink response to " "requesting operation\n" ); }break ; -case ECRYPTFS_NLMSG_HELO : +case ECRYPTFS_MSG_HELO :if (ecryptfs_process_nl_helo (skb)) {ecryptfs_printk (KERN_WARNING ,"Failed to " "fulfill HELO request\n" ); }break ; -case ECRYPTFS_NLMSG_QUIT : +case ECRYPTFS_MSG_QUIT :if (ecryptfs_process_nl_quit (skb)) {ecryptfs_printk (KERN_WARNING ,"Failed to " "fulfill QUIT request\n" );
Signature · 12 lines
1.5.1.6 ------------------------------------------------------------------------- This SF.net email is sponsored by the 2008 JavaOne(SM) Conference Don't miss this year's exciting event. There's still time to save $100. Use priority code J8TL2D2. http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone _______________________________________________ eCryptfs-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/ecryptfs-devel
Quoted 1 line · On Tue, 15 Apr 2008 15:24:38 -0500 Michael Halcrow <[email protected]> wrote:
Subject: [PATCH 2/2] eCryptfs: Introduce device handle for userspace daemon communications
This patch has the same title as [1/2]. I renamed it to "eCryptfs:
integrate eCryptfs device handle into the module."
-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference Don't miss this year's exciting event. There's still time to save $100. Use priority code J8TL2D2.
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone
_______________________________________________
eCryptfs-devel mailing list [email protected]
https://lists.sourceforge.net/lists/listinfo/ecryptfs-devel
Quoted 11 lines · On Tue, 15 Apr 2008 15:23:13 -0500 Michael Halcrow <[email protected]> wrote:
Functions to facilitate reading and writing to the eCryptfs miscellaneous device handle. This will replace the netlink interface as the preferred mechanism for communicating with the userspace eCryptfs daemon.
Each user has his own daemon, which registers itself by opening the eCryptfs device handle. Only one daemon per euid may be registered at any given time. The eCryptfs module sends a message to a daemon by adding its message to the daemon's outgoing message queue. The daemon reads the device handle to get the oldest message off the queue.
Quoted 4 lines
Incoming messages from the userspace daemon are immediately handled. If the message is a response, then the corresponding process that is blocked waiting for the response is awakened.
This is a drastic change, but the changelog doesn't tell us why it is being made!
fs/ecryptfs/miscdev.c
Quoted 6 lines
...
fs/ecryptfs/miscdev.c new file +5
-0+ rc =ecryptfs_find_daemon_by_euid (&daemon, current->euid); +if (daemon->pid != current->pid) { + rc =ecryptfs_find_daemon_by_euid (&daemon, current->euid); +BUG_ON (current->euid != daemon->euid); +BUG_ON (current->pid != daemon->pid);
This code uses pids and uids all over the place. Will it operate correctly in a containerised environment?
-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference Don't miss this year's exciting event. There's still time to save $100. Use priority code J8TL2D2.
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone
_______________________________________________
eCryptfs-devel mailing list [email protected]
https://lists.sourceforge.net/lists/listinfo/ecryptfs-devel
Quoted 22 lines · Andrew Morton
Quoted 11 lines · On Tue, 15 Apr 2008 15:23:13 -0500 Michael Halcrow <[email protected]> wrote:
Functions to facilitate reading and writing to the eCryptfs miscellaneous device handle. This will replace the netlink interface as the preferred mechanism for communicating with the userspace eCryptfs daemon.
Each user has his own daemon, which registers itself by opening the eCryptfs device handle. Only one daemon per euid may be registered at any given time. The eCryptfs module sends a message to a daemon by adding its message to the daemon's outgoing message queue. The daemon reads the device handle to get the oldest message off the queue.
Quoted 4 lines
Incoming messages from the userspace daemon are immediately handled. If the message is a response, then the corresponding process that is blocked waiting for the response is awakened.
This is a drastic change, but the changelog doesn't tell us why it is being made!
Quoted 9 lines
fs/ecryptfs/miscdev.c
Quoted 6 lines
...
fs/ecryptfs/miscdev.c new file +5
-0+ rc =ecryptfs_find_daemon_by_euid (&daemon, current->euid); +if (daemon->pid != current->pid) { + rc =ecryptfs_find_daemon_by_euid (&daemon, current->euid); +BUG_ON (current->euid != daemon->euid); +BUG_ON (current->pid != daemon->pid);This code uses pids and uids all over the place. Will it operate correctly in a containerised environment?
Thanks Andrew.
Mike, the pid_t definately needs to be replaced with a struct pid.
As for the euid, it'd be best if you also compared the user_namespace * to make sure we support one ecryptfs deamon per user namespace.
thanks,
-serge
PATCH 1/1 eCryptfs: Make key module subsystem respect namespaces
Quoted 14 lines · Serge E. Hallyn
Quoted 12 lines · Andrew Morton
Review
Quoted 6 lines · On Tue, 15 Apr 2008 15:23:13 -0500 Michael Halcrow <[email protected]> wrote:
...
(quoted diff) +5
-0+ rc = ecryptfs_find_daemon_by_euid(&daemon, current->euid); + if (daemon->pid != current->pid) { + rc = ecryptfs_find_daemon_by_euid(&daemon, current->euid); + BUG_ON(current->euid != daemon->euid); + BUG_ON(current->pid != daemon->pid);This code uses pids and uids all over the place. Will it operate correctly in a containerised environment?
Quoted 6 lines
Thanks Andrew.
Mike, the
pid_tdefinately needs to be replaced with a struct pid.As for the euid, it'd be best if you also compared the
user_namespace* to make sure we support one ecryptfs deamon per user namespace.
Make eCryptfs key module subsystem respect namespaces.
Since I will be removing the netlink interface in a future patch, I just made changes to the netlink.c code so that it will not break the build. With my recent patches, the kernel module currently defaults to the device handle interface rather than the netlink interface.
--- fs/ecryptfs/ecryptfs_kernel.h | 25 +++++++++----- fs/ecryptfs/messaging.c | 71 +++++++++++++++++++++++++++++----------- fs/ecryptfs/miscdev.c | 68 +++++++++++++++++++++++++-------------- fs/ecryptfs/netlink.c | 25 +++++++++----- 4 files changed, 126 insertions(+), 63 deletions(-)
fs/ecryptfs/ecryptfs_kernel.h +16 -9
@@ -34,6 +34,7 @@#include <linux/namei.h> #include <linux/scatterlist.h> #include <linux/hash.h> +#include <linux/nsproxy.h> /* Version verification for shared data structures w/ userspace */ #define ECRYPTFS_VERSION_MAJOR 0x00
@@ -410,8 +411,9 @@ struct ecryptfs_daemon {#define ECRYPTFS_DAEMON_MISCDEV_OPEN 0x00000008u32 flags;u32 num_queued_msg_ctx; -pid_t pid; +struct pid *pid;uid_t euid; +struct user_namespace *user_ns;struct task_struct *task;struct mutex mux;struct list_head msg_ctx_out_queue;
@@ -610,10 +612,13 @@ int ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags);int ecryptfs_read_xattr_region (char *page_virt,struct inode *ecryptfs_inode); -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,uid_t uid, -pid_t pid,u32 seq); +int ecryptfs_process_helo (unsigned int transport,uid_t euid, +struct user_namespace *user_ns,struct pid *pid); +int ecryptfs_process_quit (uid_t euid,struct user_namespace *user_ns, +struct pid *pid); +int ecryptfs_process_response (struct ecryptfs_message *msg,uid_t euid, +struct user_namespace *user_ns,struct pid *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,
@@ -623,13 +628,13 @@ void ecryptfs_release_messaging(unsigned int transport);int ecryptfs_send_netlink (char *data,int data_len,struct ecryptfs_msg_ctx *msg_ctx,u8 msg_type, -u16 msg_flags,pid_t daemon_pid); +u16 msg_flags,struct pid *daemon_pid);int ecryptfs_init_netlink (void );void ecryptfs_release_netlink (void );int ecryptfs_send_connector (char *data,int data_len,struct ecryptfs_msg_ctx *msg_ctx,u8 msg_type, -u16 msg_flags,pid_t daemon_pid); +u16 msg_flags,struct pid *daemon_pid);int ecryptfs_init_connector (void );void ecryptfs_release_connector (void );void
@@ -672,7 +677,8 @@ int ecryptfs_read_lower_page_segment(struct page *page_for_ecryptfs, struct inode *ecryptfs_inode);struct page *ecryptfs_get_locked_page (struct file *file,loff_t index);int ecryptfs_exorcise_daemon (struct ecryptfs_daemon *daemon); -int ecryptfs_find_daemon_by_euid (struct ecryptfs_daemon **daemon,uid_t euid); +int ecryptfs_find_daemon_by_euid (struct ecryptfs_daemon **daemon,uid_t euid, +struct user_namespace *user_ns);int ecryptfs_parse_packet_length (unsigned char *data,size_t *size,size_t *length_size); int ecryptfs_write_packet_length(char *dest, size_t size,
@@ -684,6 +690,7 @@ int ecryptfs_send_miscdev(char *data, size_t data_size, u16 msg_flags, struct ecryptfs_daemon *daemon);void ecryptfs_msg_ctx_alloc_to_free (struct ecryptfs_msg_ctx *msg_ctx);int -ecryptfs_spawn_daemon (struct ecryptfs_daemon **daemon,uid_t euid,pid_t pid); +ecryptfs_spawn_daemon (struct ecryptfs_daemon **daemon,uid_t euid, +struct user_namespace *user_ns,struct pid *pid);#endif /* #ifndef ECRYPTFS_KERNEL_H */
fs/ecryptfs/messaging.c +51 -20
198 lines not on this page · raw message
fs/ecryptfs/miscdev.c +43 -25
179 lines not on this page · raw message
fs/ecryptfs/netlink.c +16 -9
@@ -45,7 +45,7 @@ static struct sock *ecryptfs_nl_sock;*/ int ecryptfs_send_netlink (char *data,int data_len,struct ecryptfs_msg_ctx *msg_ctx,u8 msg_type, -u16 msg_flags,pid_t daemon_pid) +u16 msg_flags,struct pid *daemon_pid) {struct sk_buff *skb;struct nlmsghdr *nlh;
@@ -60,7 +60,7 @@ int ecryptfs_send_netlink(char *data, int data_len,ecryptfs_printk (KERN_ERR ,"Failed to allocate socket buffer\n" ); goto out; } - nlh =NLMSG_PUT (skb, daemon_pid, msg_ctx ? msg_ctx->counter :0 , + nlh =NLMSG_PUT (skb,pid_nr (daemon_pid), msg_ctx ? msg_ctx->counter :0 , msg_type, payload_len); nlh->nlmsg_flags = msg_flags;if (msg_ctx && payload_len) {
@@ -69,7 +69,7 @@ int ecryptfs_send_netlink(char *data, int data_len, msg->data_len = data_len;memcpy (msg->data, data, data_len); } - rc =netlink_unicast (ecryptfs_nl_sock, skb, daemon_pid,0 ); + rc =netlink_unicast (ecryptfs_nl_sock, skb,pid_nr (daemon_pid),0 );if (rc <0 ) {ecryptfs_printk (KERN_ERR ,"Failed to send eCryptfs netlink " "message; rc = [%d]\n" , rc);
@@ -99,6 +99,7 @@ static int ecryptfs_process_nl_response(struct sk_buff *skb) {struct nlmsghdr *nlh =nlmsg_hdr (skb);struct ecryptfs_message *msg =NLMSG_DATA (nlh); +struct pid *pid;int rc;if (skb->len -NLMSG_HDRLEN -sizeof (*msg) != msg->data_len) {
@@ -107,8 +108,10 @@ 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)->uid, -NETLINK_CREDS (skb)->pid, nlh->nlmsg_seq); + pid =find_get_pid (NETLINK_CREDS (skb)->pid); + rc =ecryptfs_process_response (msg,NETLINK_CREDS (skb)->uid,NULL , + pid, nlh->nlmsg_seq); +put_pid (pid);if (rc)printk (KERN_ERR "Error processing response message; rc = [%d]\n" , rc);
@@ -126,11 +129,13 @@ out:*/ static int ecryptfs_process_nl_helo (struct sk_buff *skb) { +struct pid *pid;int rc; + pid =find_get_pid (NETLINK_CREDS (skb)->pid); rc =ecryptfs_process_helo (ECRYPTFS_TRANSPORT_NETLINK , -NETLINK_CREDS (skb)->uid, -NETLINK_CREDS (skb)->pid); +NETLINK_CREDS (skb)->uid,NULL , pid); +put_pid (pid);if (rc)printk (KERN_WARNING "Error processing HELO; rc = [%d]\n" , rc);return rc;
@@ -147,10 +152,12 @@ static int ecryptfs_process_nl_helo(struct sk_buff *skb)*/ static int ecryptfs_process_nl_quit (struct sk_buff *skb) { +struct pid *pid;int rc; - rc =ecryptfs_process_quit (NETLINK_CREDS (skb)->uid, -NETLINK_CREDS (skb)->pid); + pid =find_get_pid (NETLINK_CREDS (skb)->pid); + rc =ecryptfs_process_quit (NETLINK_CREDS (skb)->uid,NULL , pid); +put_pid (pid);if (rc)printk (KERN_WARNING "Error processing QUIT message; rc = [%d]\n" , rc);
Signature · 1 line
1.5.3.6
PATCH 1/1 eCryptfs: Remove obsolete netlink interface to daemon
Remove the obsolete and buggy netlink interface to the userspace daemon.
--- fs/ecryptfs/Makefile | 2 +- fs/ecryptfs/ecryptfs_kernel.h | 12 -- fs/ecryptfs/main.c | 15 +-- fs/ecryptfs/messaging.c | 31 ++---- fs/ecryptfs/netlink.c | 249 ----------------------------------------- 5 files changed, 17 insertions(+), 292 deletions(-) delete mode 100644 fs/ecryptfs/netlink.c
fs/ecryptfs/Makefile +1 -1
@@ -4,4 +4,4 @@ obj-$(CONFIG_ECRYPT_FS) += ecryptfs.o -ecryptfs-objs := dentry.o file.o inode.o main.o super.o mmap.o read_write.o crypto.o keystore.o messaging.o netlink.o miscdev.o debug.o +ecryptfs-objs := dentry.o file.o inode.o main.o super.o mmap.o read_write.o crypto.o keystore.o messaging.o miscdev.o debug.o
fs/ecryptfs/ecryptfs_kernel.h +0 -12
@@ -625,18 +625,6 @@ int ecryptfs_wait_for_response(struct ecryptfs_msg_ctx *msg_ctx, struct ecryptfs_message **emsg);int ecryptfs_init_messaging (unsigned int transport);void ecryptfs_release_messaging (unsigned int transport); - -int ecryptfs_send_netlink (char *data,int data_len, -struct ecryptfs_msg_ctx *msg_ctx,u8 msg_type, -u16 msg_flags,struct pid *daemon_pid); -int ecryptfs_init_netlink (void ); -void ecryptfs_release_netlink (void ); - -int ecryptfs_send_connector (char *data,int data_len, -struct ecryptfs_msg_ctx *msg_ctx,u8 msg_type, -u16 msg_flags,struct pid *daemon_pid); -int ecryptfs_init_connector (void ); -void ecryptfs_release_connector (void ); void ecryptfs_write_header_metadata(char *virt, struct ecryptfs_crypt_stat *crypt_stat,
fs/ecryptfs/main.c +6 -9
@@ -30,7 +30,6 @@#include <linux/namei.h> #include <linux/skbuff.h> #include <linux/crypto.h> -#include <linux/netlink.h> #include <linux/mount.h> #include <linux/pagemap.h> #include <linux/key.h>
@@ -49,8 +48,7 @@ MODULE_PARM_DESC(ecryptfs_verbosity, "0, which is Quiet)");/** -* Module parameter that defines the number of netlink message buffer -* elements +* Module parameter that defines the number of message buffer elements */ unsigned int ecryptfs_message_buf_len =ECRYPTFS_DEFAULT_MSG_CTX_ELEMS ;
@@ -59,10 +57,8 @@ 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. +* Module parameter that defines the maximum guaranteed amount of time +* to wait for a response from the userspace daemon. */ signed long ecryptfs_message_wait_timeout =ECRYPTFS_MAX_MSG_CTX_TTL /HZ ;
@@ -797,8 +793,9 @@ static int __init ecryptfs_init(void) } rc =ecryptfs_init_messaging (ecryptfs_transport);if (rc) { -ecryptfs_printk (KERN_ERR ,"Failure occured while attempting to " -"initialize the eCryptfs netlink socket\n" ); +printk (KERN_ERR "%s: Failure occured while attempting to " +"initialize the eCryptfs daemon messaging subsystem; " +"rc = [%d]\n" , __func__, rc); goto out_do_sysfs_unregistration; } rc =ecryptfs_init_crypto ();
fs/ecryptfs/messaging.c +10 -21
@@ -155,16 +155,13 @@ static int ecryptfs_send_raw_message(unsigned int transport, u8 msg_type,int rc;switch (transport) { -case ECRYPTFS_TRANSPORT_NETLINK : - rc =ecryptfs_send_netlink (NULL ,0 ,NULL , msg_type,0 , - daemon->pid); -break ;case ECRYPTFS_TRANSPORT_MISCDEV : rc =ecryptfs_send_message_locked (transport,NULL ,0 , msg_type, &msg_ctx);if (rc) {printk (KERN_ERR "%s: Error whilst attempting to send " -"message via procfs; rc = [%d]\n" , __func__, rc); +"message via device handle; rc = [%d]\n" , + __func__, rc); goto out; }/* Raw messages are logically context-free (e.g., no
@@ -175,6 +172,7 @@ static int ecryptfs_send_raw_message(unsigned int transport, u8 msg_type, msg_ctx->state =ECRYPTFS_MSG_CTX_STATE_NO_REPLY ;mutex_unlock (&msg_ctx->mux);break ; +case ECRYPTFS_TRANSPORT_NETLINK :case ECRYPTFS_TRANSPORT_CONNECTOR :case ECRYPTFS_TRANSPORT_RELAYFS :default :
@@ -225,7 +223,7 @@ out:/** * ecryptfs_process_helo -* @transport: The underlying transport (netlink, etc.) +* @transport: The underlying transport (miscdev, etc.) * @euid: The user ID owner of the message * @user_ns: The namespace in which @euid applies * @pid: The process ID for the userspace program that sent the
@@ -272,7 +270,7 @@ int ecryptfs_process_helo(unsigned int transport, uid_t euid,* ecryptfs_exorcise_daemon - Destroy the daemon struct * * Must be called ceremoniously while in possession of -* ecryptfs_daemon_hash_mux and the daemon's own mux. +* ecryptfs_daemon_hash_mux. */ int ecryptfs_exorcise_daemon (struct ecryptfs_daemon *daemon) {
@@ -460,7 +458,7 @@ out:/** * ecryptfs_send_message_locked * @transport: The transport over which to send the message (i.e., -* netlink) +* miscdev) * @data: The data to send * @data_len: The length of data * @msg_ctx: The message context allocated for the send
@@ -496,14 +494,11 @@ ecryptfs_send_message_locked(unsigned int transport, char *data, int data_len,mutex_unlock (&(*msg_ctx)->mux);mutex_unlock (&ecryptfs_msg_ctx_lists_mux);switch (transport) { -case ECRYPTFS_TRANSPORT_NETLINK : - rc =ecryptfs_send_netlink (data, data_len, *msg_ctx, msg_type, -0 , daemon->pid); -break ;case ECRYPTFS_TRANSPORT_MISCDEV : rc =ecryptfs_send_miscdev (data, data_len, *msg_ctx, msg_type,0 , daemon);break ; +case ECRYPTFS_TRANSPORT_NETLINK :case ECRYPTFS_TRANSPORT_CONNECTOR :case ECRYPTFS_TRANSPORT_RELAYFS :default :
@@ -519,7 +514,7 @@ out:/** * ecryptfs_send_message * @transport: The transport over which to send the message (i.e., -* netlink) +* miscdev) * @data: The data to send * @data_len: The length of data * @msg_ctx: The message context allocated for the send
@@ -632,16 +627,12 @@ int ecryptfs_init_messaging(unsigned int transport) }mutex_unlock (&ecryptfs_msg_ctx_lists_mux);switch (transport) { -case ECRYPTFS_TRANSPORT_NETLINK : - rc =ecryptfs_init_netlink (); -if (rc) -ecryptfs_release_messaging (transport); -break ;case ECRYPTFS_TRANSPORT_MISCDEV : rc =ecryptfs_init_ecryptfs_miscdev ();if (rc)ecryptfs_release_messaging (transport);break ; +case ECRYPTFS_TRANSPORT_NETLINK :case ECRYPTFS_TRANSPORT_CONNECTOR :case ECRYPTFS_TRANSPORT_RELAYFS :default :
@@ -691,12 +682,10 @@ void ecryptfs_release_messaging(unsigned int transport)mutex_unlock (&ecryptfs_daemon_hash_mux); }switch (transport) { -case ECRYPTFS_TRANSPORT_NETLINK : -ecryptfs_release_netlink (); -break ;case ECRYPTFS_TRANSPORT_MISCDEV :ecryptfs_destroy_ecryptfs_miscdev ();break ; +case ECRYPTFS_TRANSPORT_NETLINK :case ECRYPTFS_TRANSPORT_CONNECTOR :case ECRYPTFS_TRANSPORT_RELAYFS :default :
fs/ecryptfs/netlink.c deleted +0 -249
249 lines not on this page · raw message
Signature · 1 line
1.5.1.6
Re: [PATCH] eCryptfs: Make key module subsystem respect namespaces
In reply to Michael HalcrowQuoted 163 lines · Michael Halcrow
Quoted 14 lines · Serge E. Hallyn
Quoted 12 lines · Andrew Morton
Review
Quoted 6 lines · On Tue, 15 Apr 2008 15:23:13 -0500 Michael Halcrow <[email protected]> wrote:
...
(quoted diff) +5
-0+ rc = ecryptfs_find_daemon_by_euid(&daemon, current->euid); + if (daemon->pid != current->pid) { + rc = ecryptfs_find_daemon_by_euid(&daemon, current->euid); + BUG_ON(current->euid != daemon->euid); + BUG_ON(current->pid != daemon->pid);This code uses pids and uids all over the place. Will it operate correctly in a containerised environment?
Quoted 6 lines
Thanks Andrew.
Mike, the
pid_tdefinately needs to be replaced with a struct pid.As for the euid, it'd be best if you also compared the
user_namespace* to make sure we support one ecryptfs deamon per user namespace.Make eCryptfs key module subsystem respect namespaces.
Since I will be removing the netlink interface in a future patch, I just made changes to the
netlink.ccode so that it will not break the build. With my recent patches, the kernel module currently defaults to the device handle interface rather than the netlink interface.Signed-off-by Michael Halcrow <[email protected]>--- fs/ecryptfs/ecryptfs_kernel.h | 25 +++++++++----- fs/ecryptfs/messaging.c | 71 +++++++++++++++++++++++++++++----------- fs/ecryptfs/miscdev.c | 68 +++++++++++++++++++++++++-------------- fs/ecryptfs/netlink.c | 25 +++++++++----- 4 files changed, 126 insertions(+), 63 deletions(-)fs/ecryptfs/ecryptfs_kernel.h +16
-9@@ -34,6 +34,7 @@#include <linux/namei.h> #include <linux/scatterlist.h> #include <linux/hash.h> +#include <linux/nsproxy.h> /* Version verification for shared data structures w/ userspace */ #define ECRYPTFS_VERSION_MAJOR 0x00@@ -410,8 +411,9 @@ struct ecryptfs_daemon {#define ECRYPTFS_DAEMON_MISCDEV_OPEN 0x00000008u32 flags;u32 num_queued_msg_ctx; -pid_t pid; +struct pid *pid;uid_t euid; +struct user_namespace *user_ns;struct task_struct *task;struct mutex mux;struct list_head msg_ctx_out_queue;@@ -610,10 +612,13 @@ int ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags);int ecryptfs_read_xattr_region (char *page_virt,struct inode *ecryptfs_inode); -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,uid_t uid, -pid_t pid,u32 seq); +int ecryptfs_process_helo (unsigned int transport,uid_t euid, +struct user_namespace *user_ns,struct pid *pid); +int ecryptfs_process_quit (uid_t euid,struct user_namespace *user_ns, +struct pid *pid); +int ecryptfs_process_response (struct ecryptfs_message *msg,uid_t euid, +struct user_namespace *user_ns,struct pid *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,@@ -623,13 +628,13 @@ void ecryptfs_release_messaging(unsigned int transport);int ecryptfs_send_netlink (char *data,int data_len,struct ecryptfs_msg_ctx *msg_ctx,u8 msg_type, -u16 msg_flags,pid_t daemon_pid); +u16 msg_flags,struct pid *daemon_pid);int ecryptfs_init_netlink (void );void ecryptfs_release_netlink (void );int ecryptfs_send_connector (char *data,int data_len,struct ecryptfs_msg_ctx *msg_ctx,u8 msg_type, -u16 msg_flags,pid_t daemon_pid); +u16 msg_flags,struct pid *daemon_pid);int ecryptfs_init_connector (void );void ecryptfs_release_connector (void );void @@ -672,7 +677,8 @@ int ecryptfs_read_lower_page_segment(struct page *page_for_ecryptfs, struct inode *ecryptfs_inode);struct page *ecryptfs_get_locked_page (struct file *file,loff_t index);int ecryptfs_exorcise_daemon (struct ecryptfs_daemon *daemon); -int ecryptfs_find_daemon_by_euid (struct ecryptfs_daemon **daemon,uid_t euid); +int ecryptfs_find_daemon_by_euid (struct ecryptfs_daemon **daemon,uid_t euid, +struct user_namespace *user_ns);int ecryptfs_parse_packet_length (unsigned char *data,size_t *size,size_t *length_size); int ecryptfs_write_packet_length(char *dest, size_t size,@@ -684,6 +690,7 @@ int ecryptfs_send_miscdev(char *data, size_t data_size, u16 msg_flags, struct ecryptfs_daemon *daemon);void ecryptfs_msg_ctx_alloc_to_free (struct ecryptfs_msg_ctx *msg_ctx);int -ecryptfs_spawn_daemon (struct ecryptfs_daemon **daemon,uid_t euid,pid_t pid); +ecryptfs_spawn_daemon (struct ecryptfs_daemon **daemon,uid_t euid, +struct user_namespace *user_ns,struct pid *pid);#endif /* #ifndef ECRYPTFS_KERNEL_H */ fs/ecryptfs/messaging.c +7
-3@@ -103,6 +103,7 @@ void ecryptfs_msg_ctx_alloc_to_free(struct ecryptfs_msg_ctx *msg_ctx)/** * ecryptfs_find_daemon_by_euid * @euid: The effective user id which maps to the desired daemon id +* @user_ns: The namespace in which @euid applies * @daemon: If return value is zero, points to the desired daemon pointer * * Must be called with ecryptfs_daemon_hash_mux held. @@ -111,7 +112,8 @@ void ecryptfs_msg_ctx_alloc_to_free(struct ecryptfs_msg_ctx *msg_ctx)* * Returns zero if the user id exists in the list; non-zero otherwise. */ -int ecryptfs_find_daemon_by_euid (struct ecryptfs_daemon **daemon,uid_t euid) +int ecryptfs_find_daemon_by_euid (struct ecryptfs_daemon **daemon,uid_t euid, +struct user_namespace *user_ns) {struct hlist_node *elem;int rc;@@ -119,7 +121,7 @@ int ecryptfs_find_daemon_by_euid(struct ecryptfs_daemon **daemon, uid_t euid)hlist_for_each_entry (*daemon, elem, &ecryptfs_daemon_hash[ecryptfs_uid_hash (euid)], euid_chain) { -if ((*daemon)->euid == euid) { +if ((*daemon)->euid == euid && (*daemon)->user_ns == user_ns) { rc =0 ; goto out; }@@ -186,6 +188,7 @@ out:* ecryptfs_spawn_daemon - Create and initialize a new daemon struct * @daemon: Pointer to set to newly allocated daemon struct * @euid: Effective user id for the daemon +* @user_ns: The namespace in which @euid applies * @pid: Process id for the daemon * * Must be called ceremoniously while in possession of @@ -194,7 +197,8 @@ out:* Returns zero on success; non-zero otherwise */ int -ecryptfs_spawn_daemon (struct ecryptfs_daemon **daemon,uid_t euid,pid_t pid) +ecryptfs_spawn_daemon (struct ecryptfs_daemon **daemon,uid_t euid, +struct user_namespace *user_ns,struct pid *pid) {int rc =0 ;
fs/ecryptfs/messaging.c ecryptfs_spawn_daemon(struct ecryptfs_daemon **daemon, uid_t euid, pid_t pid) · line 214
Quoted 5 lines
fs/ecryptfs/messaging.c +1
-0@@ -206,6 +210,7 @@ ecryptfs_spawn_daemon(struct ecryptfs_daemon **daemon, uid_t euid, pid_t pid) goto out; } (*daemon)->euid = euid; + (*daemon)->user_ns = user_ns; (*daemon)->pid = pid;
You'll want to do a get_pid() here, no?
And get_user_ns().
It's not because you particulary need them to stick around, but just to ensure no wraparound causes another daemon with the same struct pid or user_namespace to be spawned. Pretty gosh-darned unlikely, but still...
Quoted 134 lines
fs/ecryptfs/messaging.c +33
-15(*daemon)->task = current;mutex_init (&(*daemon)->mux);@@ -222,6 +227,7 @@ out:* ecryptfs_process_helo * @transport: The underlying transport (netlink, etc.) * @euid: The user ID owner of the message +* @user_ns: The namespace in which @euid applies * @pid: The process ID for the userspace program that sent the * message * @@ -231,32 +237,33 @@ out:* Returns zero after adding a new daemon to the hash list; * non-zero otherwise. */ -int ecryptfs_process_helo (unsigned int transport,uid_t euid,pid_t pid) +int ecryptfs_process_helo (unsigned int transport,uid_t euid, +struct user_namespace *user_ns,struct pid *pid) {struct ecryptfs_daemon *new_daemon;struct ecryptfs_daemon *old_daemon;int rc;mutex_lock (&ecryptfs_daemon_hash_mux); - rc =ecryptfs_find_daemon_by_euid (&old_daemon, euid); + rc =ecryptfs_find_daemon_by_euid (&old_daemon, euid, user_ns);if (rc !=0 ) {printk (KERN_WARNING "Received request from user [%d] " -"to register daemon [%d]; unregistering daemon " -"[%d]\n" , euid, pid, old_daemon->pid); +"to register daemon [0x%p]; unregistering daemon " +"[0x%p]\n" , euid, pid, old_daemon->pid); rc =ecryptfs_send_raw_message (transport,ECRYPTFS_MSG_QUIT , old_daemon);if (rc)printk (KERN_WARNING "Failed to send QUIT " -"message to daemon [%d]; rc = [%d]\n" , +"message to daemon [0x%p]; rc = [%d]\n" , old_daemon->pid, rc);hlist_del (&old_daemon->euid_chain);kfree (old_daemon); } - rc =ecryptfs_spawn_daemon (&new_daemon, euid, pid); + rc =ecryptfs_spawn_daemon (&new_daemon, euid, user_ns, pid);if (rc)printk (KERN_ERR "%s: The gods are displeased with this attempt " -"to create a new daemon object for euid [%d]; pid [%d]; " -"rc = [%d]\n" , __func__, euid, pid, rc); +"to create a new daemon object for euid [%d]; pid " +"[0x%p]; rc = [%d]\n" , __func__, euid, pid, rc);mutex_unlock (&ecryptfs_daemon_hash_mux);return rc; }@@ -277,7 +284,7 @@ int ecryptfs_exorcise_daemon(struct ecryptfs_daemon *daemon) || (daemon->flags & ECRYPTFS_DAEMON_IN_POLL)) { rc = -EBUSY ;printk (KERN_WARNING "%s: Attempt to destroy daemon with pid " -"[%d], but it is in the midst of a read or a poll\n" , +"[0x%p], but it is in the midst of a read or a poll\n" , __func__, daemon->pid);mutex_unlock (&daemon->mux); goto out;@@ -303,6 +310,7 @@ out:/** * ecryptfs_process_quit * @euid: The user ID owner of the message +* @user_ns: The namespace in which @euid applies * @pid: The process ID for the userspace program that sent the * message * @@ -310,17 +318,18 @@ out:* it is the registered that is requesting the deletion. Returns zero * after deleting the desired daemon; non-zero otherwise. */ -int ecryptfs_process_quit (uid_t euid,pid_t pid) +int ecryptfs_process_quit (uid_t euid,struct user_namespace *user_ns, +struct pid *pid) {struct ecryptfs_daemon *daemon;int rc;mutex_lock (&ecryptfs_daemon_hash_mux); - rc =ecryptfs_find_daemon_by_euid (&daemon, euid); + rc =ecryptfs_find_daemon_by_euid (&daemon, euid, user_ns);if (rc || !daemon) { rc = -EINVAL ;printk (KERN_ERR "Received request from user [%d] to " -"unregister unrecognized daemon [%d]\n" , euid, pid); +"unregister unrecognized daemon [0x%p]\n" , euid, pid); goto out_unlock; } rc =ecryptfs_exorcise_daemon (daemon);@@ -354,11 +363,13 @@ out_unlock:* Returns zero on success; non-zero otherwise */ int ecryptfs_process_response (struct ecryptfs_message *msg,uid_t euid, -pid_t pid,u32 seq) +struct user_namespace *user_ns,struct pid *pid, +u32 seq) {struct ecryptfs_daemon *daemon;struct ecryptfs_msg_ctx *msg_ctx;size_t msg_size; +struct nsproxy *nsproxy;int rc;if (msg->index >= ecryptfs_message_buf_len) {@@ -372,12 +383,24 @@ int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid, msg_ctx = &ecryptfs_msg_ctx_arr[msg->index];mutex_lock (&msg_ctx->mux);mutex_lock (&ecryptfs_daemon_hash_mux); - rc =ecryptfs_find_daemon_by_euid (&daemon, msg_ctx->task->euid); +rcu_read_lock (); + nsproxy =task_nsproxy (msg_ctx->task); +if (nsproxy ==NULL ) { + rc = -EBADMSG ; +printk (KERN_ERR "%s: Receiving process is a zombie. Dropping " +"message.\n" , __func__); +rcu_read_unlock (); +mutex_unlock (&ecryptfs_daemon_hash_mux); + goto wake_up; + } + rc =ecryptfs_find_daemon_by_euid (&daemon, msg_ctx->task->euid, + nsproxy->user_ns); +rcu_read_unlock ();mutex_unlock (&ecryptfs_daemon_hash_mux);if (rc) { rc = -EBADMSG ;printk (KERN_WARNING "%s: User [%d] received a " -"message response from process [%d] but does " +"message response from process [0x%p] but does " "not have a registered daemon\n" , __func__, msg_ctx->task->euid, pid); goto wake_up;
fs/ecryptfs/messaging.c int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid, · line 415
Quoted 4 lines
fs/ecryptfs/messaging.c +1
-0@@ -389,10 +412,17 @@ int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid, euid, msg_ctx->task->euid); goto unlock; } +if (nsproxy->user_ns != user_ns) {
Since you didn't grab a ref to the nsproxy, it's possible that it will have been freed before this, right? So you probably just want to grab a copy of nsproxy->user_ns while under the rcu_read_lock, where you can be sure it's still around.
Otherwise this looks good. Thanks, Mike.
Quoted 303 lines
fs/ecryptfs/messaging.c +9
-2+ rc = -EBADMSG ; +printk (KERN_WARNING "%s: Received message from user_ns " +"[0x%p]; expected message from user_ns [0x%p]\n" , + __func__, user_ns, nsproxy->user_ns); + goto unlock; + }if (daemon->pid != pid) { rc = -EBADMSG ;printk (KERN_ERR "%s: User [%d] sent a message response " -"from an unrecognized process [%d]\n" , +"from an unrecognized process [0x%p]\n" , __func__, msg_ctx->task->euid, pid); goto unlock; }@@ -446,7 +476,8 @@ ecryptfs_send_message_locked(unsigned int transport, char *data, int data_len,struct ecryptfs_daemon *daemon;int rc; - rc =ecryptfs_find_daemon_by_euid (&daemon, current->euid); + rc =ecryptfs_find_daemon_by_euid (&daemon, current->euid, + current->nsproxy->user_ns);if (rc || !daemon) { rc = -ENOTCONN ; printk(KERN_ERR "%s: User [%d] does not have a daemon "fs/ecryptfs/miscdev.c +43
-25@@ -46,7 +46,8 @@ ecryptfs_miscdev_poll(struct file *file, poll_table *pt)mutex_lock (&ecryptfs_daemon_hash_mux);/* TODO: Just use file->private_data? */ - rc =ecryptfs_find_daemon_by_euid (&daemon, current->euid); + rc =ecryptfs_find_daemon_by_euid (&daemon, current->euid, + current->nsproxy->user_ns);BUG_ON (rc || !daemon);mutex_lock (&daemon->mux);mutex_unlock (&ecryptfs_daemon_hash_mux);@@ -92,10 +93,12 @@ ecryptfs_miscdev_open(struct inode *inode, struct file *file) "count; rc = [%d]\n", __func__, rc); goto out_unlock_daemon_list; } - rc =ecryptfs_find_daemon_by_euid (&daemon, current->euid); + rc =ecryptfs_find_daemon_by_euid (&daemon, current->euid, + current->nsproxy->user_ns);if (rc || !daemon) { rc =ecryptfs_spawn_daemon (&daemon, current->euid, - current->pid); + current->nsproxy->user_ns, +task_pid (current));if (rc) {printk (KERN_ERR "%s: Error attempting to spawn daemon; " "rc = [%d]\n" , __func__, rc);@@ -103,18 +106,18 @@ ecryptfs_miscdev_open(struct inode *inode, struct file *file) } }mutex_lock (&daemon->mux); -if (daemon->pid != current->pid) { +if (daemon->pid !=task_pid (current)) { rc = -EINVAL ; -printk (KERN_ERR "%s: pid [%d] has registered with euid [%d], " -"but pid [%d] has attempted to open the handle " +printk (KERN_ERR "%s: pid [0x%p] has registered with euid [%d], " +"but pid [0x%p] has attempted to open the handle " "instead\n" , __func__, daemon->pid, daemon->euid, - current->pid); +task_pid (current)); goto out_unlock_daemon; }if (daemon->flags &ECRYPTFS_DAEMON_MISCDEV_OPEN ) { rc = -EBUSY ;printk (KERN_ERR "%s: Miscellaneous device handle may only be " -"opened once per daemon; pid [%d] already has this " +"opened once per daemon; pid [0x%p] already has this " "handle open\n" , __func__, daemon->pid); goto out_unlock_daemon; }@@ -147,10 +150,11 @@ ecryptfs_miscdev_release(struct inode *inode, struct file *file)int rc;mutex_lock (&ecryptfs_daemon_hash_mux); - rc =ecryptfs_find_daemon_by_euid (&daemon, current->euid); + rc =ecryptfs_find_daemon_by_euid (&daemon, current->euid, + current->nsproxy->user_ns);BUG_ON (rc || !daemon);mutex_lock (&daemon->mux); -BUG_ON (daemon->pid != current->pid); +BUG_ON (daemon->pid !=task_pid (current));BUG_ON (!(daemon->flags &ECRYPTFS_DAEMON_MISCDEV_OPEN )); daemon->flags &= ~ECRYPTFS_DAEMON_MISCDEV_OPEN ;atomic_dec (&ecryptfs_num_miscdev_opens);@@ -247,7 +251,8 @@ ecryptfs_miscdev_read(struct file *file, char __user *buf, size_t count,mutex_lock (&ecryptfs_daemon_hash_mux);/* TODO: Just use file->private_data? */ - rc =ecryptfs_find_daemon_by_euid (&daemon, current->euid); + rc =ecryptfs_find_daemon_by_euid (&daemon, current->euid, + current->nsproxy->user_ns);BUG_ON (rc || !daemon);mutex_lock (&daemon->mux);if (daemon->flags &ECRYPTFS_DAEMON_ZOMBIE ) {@@ -285,7 +290,8 @@ check_list: goto check_list; }BUG_ON (current->euid != daemon->euid); -BUG_ON (current->pid != daemon->pid); +BUG_ON (current->nsproxy->user_ns != daemon->user_ns); +BUG_ON (task_pid (current) != daemon->pid); msg_ctx =list_first_entry (&daemon->msg_ctx_out_queue, struct ecryptfs_msg_ctx, daemon_out_list);BUG_ON (!msg_ctx);@@ -355,15 +361,18 @@ out_unlock_daemon:/** * ecryptfs_miscdev_helo * @euid: effective user id of miscdevess sending helo packet +* @user_ns: The namespace in which @euid applies * @pid: miscdevess id of miscdevess sending helo packet * * Returns zero on success; non-zero otherwise */ -static int ecryptfs_miscdev_helo (uid_t uid,pid_t pid) +static int ecryptfs_miscdev_helo (uid_t euid,struct user_namespace *user_ns, +struct pid *pid) {int rc; - rc =ecryptfs_process_helo (ECRYPTFS_TRANSPORT_MISCDEV , uid, pid); + rc =ecryptfs_process_helo (ECRYPTFS_TRANSPORT_MISCDEV , euid, user_ns, + pid);if (rc)printk (KERN_WARNING "Error processing HELO; rc = [%d]\n" , rc);return rc;@@ -372,15 +381,17 @@ static int ecryptfs_miscdev_helo(uid_t uid, pid_t pid)/** * ecryptfs_miscdev_quit * @euid: effective user id of miscdevess sending quit packet +* @user_ns: The namespace in which @euid applies * @pid: miscdevess id of miscdevess sending quit packet * * Returns zero on success; non-zero otherwise */ -static int ecryptfs_miscdev_quit (uid_t euid,pid_t pid) +static int ecryptfs_miscdev_quit (uid_t euid,struct user_namespace *user_ns, +struct pid *pid) {int rc; - rc =ecryptfs_process_quit (euid, pid); + rc =ecryptfs_process_quit (euid, user_ns, pid);if (rc)printk (KERN_WARNING "Error processing QUIT message; rc = [%d]\n" , rc);@@ -392,13 +403,15 @@ static int ecryptfs_miscdev_quit(uid_t euid, pid_t pid)* @data: Bytes comprising struct ecryptfs_message * @data_size: sizeof(struct ecryptfs_message) + data len * @euid: Effective user id of miscdevess sending the miscdev response +* @user_ns: The namespace in which @euid applies * @pid: Miscdevess id of miscdevess sending the miscdev response * @seq: Sequence number for miscdev response packet * * Returns zero on success; non-zero otherwise */ static int ecryptfs_miscdev_response (char *data,size_t data_size, -uid_t euid,pid_t pid,u32 seq) +uid_t euid,struct user_namespace *user_ns, +struct pid *pid,u32 seq) {struct ecryptfs_message *msg = (struct ecryptfs_message *)data;int rc;@@ -410,7 +423,7 @@ static int ecryptfs_miscdev_response(char *data, size_t data_size, rc = -EINVAL ; goto out; } - rc =ecryptfs_process_response (msg, euid, pid, seq); + rc =ecryptfs_process_response (msg, euid, user_ns, pid, seq);if (rc)printk (KERN_ERR "Error processing response message; rc = [%d]\n" , rc);@@ -491,27 +504,32 @@ ecryptfs_miscdev_write(struct file *file, const char __user *buf, } rc =ecryptfs_miscdev_response (&data[i], packet_size, current->euid, - current->pid, seq); + current->nsproxy->user_ns, +task_pid (current), seq);if (rc)printk (KERN_WARNING "%s: Failed to deliver miscdev " "response to requesting operation; rc = [%d]\n" , __func__, rc);break ;case ECRYPTFS_MSG_HELO : - rc =ecryptfs_miscdev_helo (current->euid, current->pid); + rc =ecryptfs_miscdev_helo (current->euid, + current->nsproxy->user_ns, +task_pid (current));if (rc) {printk (KERN_ERR "%s: Error attempting to process " -"helo from pid [%d]; rc = [%d]\n" , __func__, - current->pid, rc); +"helo from pid [0x%p]; rc = [%d]\n" , __func__, +task_pid (current), rc); goto out_free; }break ;case ECRYPTFS_MSG_QUIT : - rc =ecryptfs_miscdev_quit (current->euid, current->pid); + rc =ecryptfs_miscdev_quit (current->euid, + current->nsproxy->user_ns, +task_pid (current));if (rc) {printk (KERN_ERR "%s: Error attempting to process " -"quit from pid [%d]; rc = [%d]\n" , __func__, - current->pid, rc); +"quit from pid [0x%p]; rc = [%d]\n" , __func__, +task_pid (current), rc); goto out_free; }break ;fs/ecryptfs/netlink.c +16
-9@@ -45,7 +45,7 @@ static struct sock *ecryptfs_nl_sock;*/ int ecryptfs_send_netlink (char *data,int data_len,struct ecryptfs_msg_ctx *msg_ctx,u8 msg_type, -u16 msg_flags,pid_t daemon_pid) +u16 msg_flags,struct pid *daemon_pid) {struct sk_buff *skb;struct nlmsghdr *nlh;@@ -60,7 +60,7 @@ int ecryptfs_send_netlink(char *data, int data_len,ecryptfs_printk (KERN_ERR ,"Failed to allocate socket buffer\n" ); goto out; } - nlh =NLMSG_PUT (skb, daemon_pid, msg_ctx ? msg_ctx->counter :0 , + nlh =NLMSG_PUT (skb,pid_nr (daemon_pid), msg_ctx ? msg_ctx->counter :0 , msg_type, payload_len); nlh->nlmsg_flags = msg_flags;if (msg_ctx && payload_len) {@@ -69,7 +69,7 @@ int ecryptfs_send_netlink(char *data, int data_len, msg->data_len = data_len;memcpy (msg->data, data, data_len); } - rc =netlink_unicast (ecryptfs_nl_sock, skb, daemon_pid,0 ); + rc =netlink_unicast (ecryptfs_nl_sock, skb,pid_nr (daemon_pid),0 );if (rc <0 ) {ecryptfs_printk (KERN_ERR ,"Failed to send eCryptfs netlink " "message; rc = [%d]\n" , rc);@@ -99,6 +99,7 @@ static int ecryptfs_process_nl_response(struct sk_buff *skb) {struct nlmsghdr *nlh =nlmsg_hdr (skb);struct ecryptfs_message *msg =NLMSG_DATA (nlh); +struct pid *pid;int rc;if (skb->len -NLMSG_HDRLEN -sizeof (*msg) != msg->data_len) {@@ -107,8 +108,10 @@ 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)->uid, -NETLINK_CREDS (skb)->pid, nlh->nlmsg_seq); + pid =find_get_pid (NETLINK_CREDS (skb)->pid); + rc =ecryptfs_process_response (msg,NETLINK_CREDS (skb)->uid,NULL , + pid, nlh->nlmsg_seq); +put_pid (pid);if (rc)printk (KERN_ERR "Error processing response message; rc = [%d]\n" , rc);@@ -126,11 +129,13 @@ out:*/ static int ecryptfs_process_nl_helo (struct sk_buff *skb) { +struct pid *pid;int rc; + pid =find_get_pid (NETLINK_CREDS (skb)->pid); rc =ecryptfs_process_helo (ECRYPTFS_TRANSPORT_NETLINK , -NETLINK_CREDS (skb)->uid, -NETLINK_CREDS (skb)->pid); +NETLINK_CREDS (skb)->uid,NULL , pid); +put_pid (pid);if (rc)printk (KERN_WARNING "Error processing HELO; rc = [%d]\n" , rc);return rc;@@ -147,10 +152,12 @@ static int ecryptfs_process_nl_helo(struct sk_buff *skb)*/ static int ecryptfs_process_nl_quit (struct sk_buff *skb) { +struct pid *pid;int rc; - rc =ecryptfs_process_quit (NETLINK_CREDS (skb)->uid, -NETLINK_CREDS (skb)->pid); + pid =find_get_pid (NETLINK_CREDS (skb)->pid); + rc =ecryptfs_process_quit (NETLINK_CREDS (skb)->uid,NULL , pid); +put_pid (pid);if (rc)printk (KERN_WARNING "Error processing QUIT message; rc = [%d]\n" , rc);Signature · 1 line
1.5.3.6
PATCH 1/1 eCryptfs: Fix refs to pid and user_ns
Quoted 47 lines · Serge E. Hallyn
Review ecryptfs_spawn_daemon(struct ecryptfs_daemon **daemon, uid_t euid, pid_t pid) · line 214
Quoted 6 lines · Michael Halcrow
(quoted diff) +1
-0@@ -206,6 +210,7 @@ ecryptfs_spawn_daemon(struct ecryptfs_daemon **daemon, uid_t euid, pid_t pid) goto out; } (*daemon)->euid = euid; + (*daemon)->user_ns = user_ns; (*daemon)->pid = pid;You'll want to do a
get_pid()here, no?And
get_user_ns().It's not because you particulary need them to stick around, but just to ensure no wraparound causes another daemon with the same struct pid or
user_namespaceto be spawned. Pretty gosh-darned unlikely, but still...
...Quoted 29 lines
(quoted diff) +14
-2@@ -372,12 +383,24 @@ int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid, msg_ctx = &ecryptfs_msg_ctx_arr[msg->index]; mutex_lock(&msg_ctx->mux); mutex_lock(&ecryptfs_daemon_hash_mux); - rc = ecryptfs_find_daemon_by_euid(&daemon, msg_ctx->task->euid); + rcu_read_lock(); + nsproxy = task_nsproxy(msg_ctx->task); + if (nsproxy == NULL) { + rc = -EBADMSG; + printk(KERN_ERR "%s: Receiving process is a zombie. Dropping " + "message.\n", __func__); + rcu_read_unlock(); + mutex_unlock(&ecryptfs_daemon_hash_mux); + goto wake_up; + } + rc = ecryptfs_find_daemon_by_euid(&daemon, msg_ctx->task->euid, + nsproxy->user_ns); + rcu_read_unlock(); mutex_unlock(&ecryptfs_daemon_hash_mux); if (rc) { rc = -EBADMSG; printk(KERN_WARNING "%s: User [%d] received a " - "message response from process [%d] but does " + "message response from process [0x%p] but does " "not have a registered daemon\n", __func__, msg_ctx->task->euid, pid); goto wake_up;@@ -389,10 +412,17 @@ int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid, euid, msg_ctx->task->euid);
Quoted 8 lines
Review int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid, · line 415
Quoted 3 lines
(quoted diff) +1
-0goto unlock; } + if (nsproxy->user_ns != user_ns) {Since you didn't grab a ref to the nsproxy, it's possible that it will have been freed before this, right? So you probably just want to grab a copy of
nsproxy->user_nswhile under thercu_read_lock, where you can be sure it's still around.
Have eCryptfs properly reference the pid and user_ns objects. Copy user_ns out of nsproxy in case nsproxy goes away after we drop the lock.
--- fs/ecryptfs/messaging.c | 16 ++++++++++++---- 1 files changed, 12 insertions(+), 4 deletions(-)
fs/ecryptfs/messaging.c +12 -4
@@ -20,6 +20,8 @@* 02111-1307, USA. */ #include <linux/sched.h> +#include <linux/user_namespace.h> +#include <linux/nsproxy.h> #include "ecryptfs_kernel.h" static LIST_HEAD (ecryptfs_msg_ctx_free_list);
@@ -208,8 +210,8 @@ ecryptfs_spawn_daemon(struct ecryptfs_daemon **daemon, uid_t euid, goto out; } (*daemon)->euid = euid; - (*daemon)->user_ns = user_ns; - (*daemon)->pid = pid; + (*daemon)->user_ns =get_user_ns (user_ns); + (*daemon)->pid =get_pid (pid); (*daemon)->task = current;mutex_init (&(*daemon)->mux);INIT_LIST_HEAD (&(*daemon)->msg_ctx_out_queue);
@@ -298,6 +300,10 @@ int ecryptfs_exorcise_daemon(struct ecryptfs_daemon *daemon)hlist_del (&daemon->euid_chain);if (daemon->task)wake_up_process (daemon->task); +if (daemon->pid) +put_pid (daemon->pid); +if (daemon->user_ns) +put_user_ns (daemon->user_ns);mutex_unlock (&daemon->mux);memset (daemon,0 ,sizeof (*daemon));kfree (daemon);
@@ -368,6 +374,7 @@ int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid,struct ecryptfs_msg_ctx *msg_ctx;size_t msg_size;struct nsproxy *nsproxy; +struct user_namespace *current_user_ns;int rc;if (msg->index >= ecryptfs_message_buf_len) {
@@ -391,8 +398,9 @@ int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid,mutex_unlock (&ecryptfs_daemon_hash_mux); goto wake_up; } + current_user_ns = nsproxy->user_ns; rc =ecryptfs_find_daemon_by_euid (&daemon, msg_ctx->task->euid, - nsproxy->user_ns); + current_user_ns);rcu_read_unlock ();mutex_unlock (&ecryptfs_daemon_hash_mux);if (rc) {
@@ -410,7 +418,7 @@ int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid, euid, msg_ctx->task->euid); goto unlock; } -if (nsproxy->user_ns != user_ns) { +if (current_user_ns != user_ns) { rc = -EBADMSG ; printk(KERN_WARNING "%s: Received message from user_ns " "[0x%p]; expected message from user_ns [0x%p]\n",
Signature · 1 line
1.5.1.6
Re: [PATCH] eCryptfs: Fix refs to pid and user_ns
Quoted 57 lines · Michael Halcrow
Quoted 47 lines · Serge E. Hallyn
fs/ecryptfs/messaging.c ecryptfs_spawn_daemon(struct ecryptfs_daemon **daemon, uid_t euid, pid_t pid) · line 214
Quoted 6 lines · Michael Halcrow
fs/ecryptfs/messaging.c +1
-0@@ -206,6 +210,7 @@ ecryptfs_spawn_daemon(struct ecryptfs_daemon **daemon, uid_t euid, pid_t pid) goto out; } (*daemon)->euid = euid; + (*daemon)->user_ns = user_ns; (*daemon)->pid = pid;You'll want to do a
get_pid()here, no?And
get_user_ns().It's not because you particulary need them to stick around, but just to ensure no wraparound causes another daemon with the same struct pid or
user_namespaceto be spawned. Pretty gosh-darned unlikely, but still...
...Quoted 29 lines
fs/ecryptfs/messaging.c +14
-2@@ -372,12 +383,24 @@ int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid, msg_ctx = &ecryptfs_msg_ctx_arr[msg->index];mutex_lock (&msg_ctx->mux);mutex_lock (&ecryptfs_daemon_hash_mux); - rc =ecryptfs_find_daemon_by_euid (&daemon, msg_ctx->task->euid); +rcu_read_lock (); + nsproxy =task_nsproxy (msg_ctx->task); +if (nsproxy ==NULL ) { + rc = -EBADMSG ; +printk (KERN_ERR "%s: Receiving process is a zombie. Dropping " +"message.\n" , __func__); +rcu_read_unlock (); +mutex_unlock (&ecryptfs_daemon_hash_mux); + goto wake_up; + } + rc =ecryptfs_find_daemon_by_euid (&daemon, msg_ctx->task->euid, + nsproxy->user_ns); +rcu_read_unlock ();mutex_unlock (&ecryptfs_daemon_hash_mux);if (rc) { rc = -EBADMSG ;printk (KERN_WARNING "%s: User [%d] received a " -"message response from process [%d] but does " +"message response from process [0x%p] but does " "not have a registered daemon\n" , __func__, msg_ctx->task->euid, pid); goto wake_up;@@ -389,10 +412,17 @@ int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid, euid, msg_ctx->task->euid);Quoted 8 lines
fs/ecryptfs/messaging.c int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid,
Quoted 3 lines
fs/ecryptfs/messaging.c +1
-0goto unlock; } +if (nsproxy->user_ns != user_ns) {Since you didn't grab a ref to the nsproxy, it's possible that it will have been freed before this, right? So you probably just want to grab a copy of
nsproxy->user_nswhile under thercu_read_lock, where you can be sure it's still around.
Quoted 5 lines
Have eCryptfs properly reference the pid and
user_nsobjects. Copyuser_nsout of nsproxy in case nsproxy goes away after we drop the lock.Signed-off-by Michael Halcrow <[email protected]>
Looks good. Thanks, Mike.
for both.
-serge
Quoted 69 lines
--- fs/ecryptfs/messaging.c | 16 ++++++++++++---- 1 files changed, 12 insertions(+), 4 deletions(-)fs/ecryptfs/messaging.c +12
-4@@ -20,6 +20,8 @@* 02111-1307, USA. */ #include <linux/sched.h> +#include <linux/user_namespace.h> +#include <linux/nsproxy.h> #include "ecryptfs_kernel.h" static LIST_HEAD (ecryptfs_msg_ctx_free_list);@@ -208,8 +210,8 @@ ecryptfs_spawn_daemon(struct ecryptfs_daemon **daemon, uid_t euid, goto out; } (*daemon)->euid = euid; - (*daemon)->user_ns = user_ns; - (*daemon)->pid = pid; + (*daemon)->user_ns =get_user_ns (user_ns); + (*daemon)->pid =get_pid (pid); (*daemon)->task = current;mutex_init (&(*daemon)->mux);INIT_LIST_HEAD (&(*daemon)->msg_ctx_out_queue);@@ -298,6 +300,10 @@ int ecryptfs_exorcise_daemon(struct ecryptfs_daemon *daemon)hlist_del (&daemon->euid_chain);if (daemon->task)wake_up_process (daemon->task); +if (daemon->pid) +put_pid (daemon->pid); +if (daemon->user_ns) +put_user_ns (daemon->user_ns);mutex_unlock (&daemon->mux);memset (daemon,0 ,sizeof (*daemon));kfree (daemon);@@ -368,6 +374,7 @@ int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid,struct ecryptfs_msg_ctx *msg_ctx;size_t msg_size;struct nsproxy *nsproxy; +struct user_namespace *current_user_ns;int rc;if (msg->index >= ecryptfs_message_buf_len) {@@ -391,8 +398,9 @@ int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid,mutex_unlock (&ecryptfs_daemon_hash_mux); goto wake_up; } + current_user_ns = nsproxy->user_ns; rc =ecryptfs_find_daemon_by_euid (&daemon, msg_ctx->task->euid, - nsproxy->user_ns); + current_user_ns);rcu_read_unlock ();mutex_unlock (&ecryptfs_daemon_hash_mux);if (rc) {@@ -410,7 +418,7 @@ int ecryptfs_process_response(struct ecryptfs_message *msg, uid_t euid, euid, msg_ctx->task->euid); goto unlock; } -if (nsproxy->user_ns != user_ns) { +if (current_user_ns != user_ns) { rc = -EBADMSG ; printk(KERN_WARNING "%s: Received message from user_ns " "[0x%p]; expected message from user_ns [0x%p]\n",Signature · 1 line
1.5.1.6
Quoted 14 lines · Andrew Morton
Quoted 11 lines · On Tue, 15 Apr 2008 15:23:13 -0500 Michael Halcrow <[email protected]> wrote:
Functions to facilitate reading and writing to the eCryptfs miscellaneous device handle. This will replace the netlink interface as the preferred mechanism for communicating with the userspace eCryptfs daemon.
Each user has his own daemon, which registers itself by opening the eCryptfs device handle. Only one daemon per euid may be registered at any given time. The eCryptfs module sends a message to a daemon by adding its message to the daemon's outgoing message queue. The daemon reads the device handle to get the oldest message off the queue.
Quoted 6 lines
Quoted 3 lines
Incoming messages from the userspace daemon are immediately handled. If the message is a response, then the corresponding process that is blocked waiting for the response is awakened.
This is a drastic change, but the changelog doesn't tell us why it is being made!
This resurrects the question from 2006:
Quoted 1 line · Andrew Morton
- _why_ does it use netlink?
I responded:
Quoted 3 lines
Netlink provides the transport mechanism that would minimize the complexity of the implementation, given that we can have multiple daemons (one per user).
A regular device file was my real preference from the get-go, but I went with netlink at the time because I thought it would be less complex for managing send queues (i.e., just do a unicast and move on). It turns out that we do not really get that much complexity reduction with netlink, and netlink is more heavyweight than a device handle.
In addition, the netlink interface to eCryptfs has been broken since 2.6.24. I am assuming this is a bug in how eCryptfs uses netlink, since the other in-kernel users of netlink do not seem to be having any problems. I have had one report of a user successfully using eCryptfs with netlink on 2.6.24, but for my own systems, when starting the userspace daemon, the initial helo message sent to the eCryptfs kernel module results in an oops right off the bat. I spent some time looking at it, but I have not yet found the cause. The netlink interface breaking gave me the motivation to just finish my patch to migrate to a regular device handle. If I cannot find out soon why the netlink interface in eCryptfs broke, I am likely to just send a patch to disable it in 2.6.24 and 2.6.25. I would like the device handle to be the preferred means of communicating with the userspace daemon from 2.6.26 on forward.
Mike
-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference Don't miss this year's exciting event. There's still time to save $100. Use priority code J8TL2D2.
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone
_______________________________________________
eCryptfs-devel mailing list [email protected]
https://lists.sourceforge.net/lists/listinfo/ecryptfs-devel
Quoted 3 lines · Michael Halcrow
If I cannot find out soon why the netlink interface in eCryptfs broke, I am likely to just send a patch to disable it in 2.6.24 and 2.6.25.
This patch yanks key module support out of eCryptfs. In the event that the netlink bug with eCryptfs does not get resolved soon, I intend for this to apply to point releases of 2.6.24 and 2.6.25.
This patch is only a feature-disabling workaround and conflicts with the patchset that introduces the device handle mechanism for communicating with the userspace key module daemon. Future kernel versions will use a regular device handle for communications with the userspace daemon rather than the netlink interface.
--- fs/ecryptfs/ecryptfs_kernel.h | 1 - fs/ecryptfs/keystore.c | 422 ++--------------------------------------- fs/ecryptfs/main.c | 11 +- fs/ecryptfs/messaging.c | 6 - 4 files changed, 13 insertions(+), 427 deletions(-)
fs/ecryptfs/ecryptfs_kernel.h +0 -1
@@ -51,7 +51,6 @@#define ECRYPTFS_VERSIONING_MULTKEY 0x00000020#define ECRYPTFS_VERSIONING_MASK (ECRYPTFS_VERSIONING_PASSPHRASE \ | ECRYPTFS_VERSIONING_PLAINTEXT_PASSTHROUGH \ - | ECRYPTFS_VERSIONING_PUBKEY \ | ECRYPTFS_VERSIONING_XATTR \ | ECRYPTFS_VERSIONING_MULTKEY)#define ECRYPTFS_MAX_PASSWORD_LENGTH 64
fs/ecryptfs/keystore.c +12 -410
459 lines not on this page · raw message
fs/ecryptfs/main.c +1 -10
@@ -795,25 +795,17 @@ static int __init ecryptfs_init(void)printk (KERN_ERR "sysfs registration failed\n" ); goto out_unregister_filesystem; } - rc =ecryptfs_init_messaging (ecryptfs_transport); -if (rc) { -ecryptfs_printk (KERN_ERR ,"Failure occured while attempting to " -"initialize the eCryptfs netlink socket\n" ); - goto out_do_sysfs_unregistration; - } rc =ecryptfs_init_crypto ();if (rc) {printk (KERN_ERR "Failure whilst attempting to init crypto; " "rc = [%d]\n" , rc); - goto out_release_messaging; + goto out_do_sysfs_unregistration; }if (ecryptfs_verbosity >0 )printk (KERN_CRIT "eCryptfs verbosity set to %d. Secret values " "will be written to the syslog!\n" , ecryptfs_verbosity); goto out; -out_release_messaging: -ecryptfs_release_messaging (ecryptfs_transport); out_do_sysfs_unregistration:do_sysfs_unregistration (); out_unregister_filesystem:
@@ -832,7 +824,6 @@ static void __exit ecryptfs_exit(void)if (rc)printk (KERN_ERR "Failure whilst attempting to destroy crypto; " "rc = [%d]\n" , rc); -ecryptfs_release_messaging (ecryptfs_transport);do_sysfs_unregistration ();unregister_filesystem (&ecryptfs_fs_type);ecryptfs_free_kmem_caches ();
fs/ecryptfs/messaging.c +0 -6
@@ -460,10 +460,6 @@ int ecryptfs_init_messaging(unsigned int transport)mutex_unlock (&ecryptfs_msg_ctx_lists_mux);switch (transport) {case ECRYPTFS_TRANSPORT_NETLINK : - rc =ecryptfs_init_netlink (); -if (rc) -ecryptfs_release_messaging (transport); -break ;case ECRYPTFS_TRANSPORT_CONNECTOR :case ECRYPTFS_TRANSPORT_RELAYFS :default :
@@ -507,8 +503,6 @@ void ecryptfs_release_messaging(unsigned int transport) }switch (transport) {case ECRYPTFS_TRANSPORT_NETLINK : -ecryptfs_release_netlink (); -break ;case ECRYPTFS_TRANSPORT_CONNECTOR :case ECRYPTFS_TRANSPORT_RELAYFS :default :
Signature · 1 line
1.5.3.6