Commit 26c439d4 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'ecryptfs-3.5-rc6-fixes' of...

Merge tag 'ecryptfs-3.5-rc6-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tyhicks/ecryptfs

Pull eCryptfs fixes from Tyler Hicks:
 "Fixes an incorrect access mode check when preparing to open a file in
  the lower filesystem.  This isn't an urgent fix, but it is simple and
  the check was obviously incorrect.

  Also fixes a couple important bugs in the eCryptfs miscdev interface.
  These changes are low risk due to the small number of users that use
  the miscdev interface.  I was able to keep the changes minimal and I
  have some cleaner, more complete changes queued up for the next merge
  window that will build on these patches."

* tag 'ecryptfs-3.5-rc6-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tyhicks/ecryptfs:
  eCryptfs: Gracefully refuse miscdev file ops on inherited/passed files
  eCryptfs: Fix lockdep warning in miscdev operations
  eCryptfs: Properly check for O_RDONLY flag before doing privileged open
parents c8912f2b 8dc67805
...@@ -149,7 +149,7 @@ int ecryptfs_privileged_open(struct file **lower_file, ...@@ -149,7 +149,7 @@ int ecryptfs_privileged_open(struct file **lower_file,
(*lower_file) = dentry_open(lower_dentry, lower_mnt, flags, cred); (*lower_file) = dentry_open(lower_dentry, lower_mnt, flags, cred);
if (!IS_ERR(*lower_file)) if (!IS_ERR(*lower_file))
goto out; goto out;
if (flags & O_RDONLY) { if ((flags & O_ACCMODE) == O_RDONLY) {
rc = PTR_ERR((*lower_file)); rc = PTR_ERR((*lower_file));
goto out; goto out;
} }
......
...@@ -49,7 +49,10 @@ ecryptfs_miscdev_poll(struct file *file, poll_table *pt) ...@@ -49,7 +49,10 @@ ecryptfs_miscdev_poll(struct file *file, poll_table *pt)
mutex_lock(&ecryptfs_daemon_hash_mux); mutex_lock(&ecryptfs_daemon_hash_mux);
/* TODO: Just use file->private_data? */ /* TODO: Just use file->private_data? */
rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns()); rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns());
BUG_ON(rc || !daemon); if (rc || !daemon) {
mutex_unlock(&ecryptfs_daemon_hash_mux);
return -EINVAL;
}
mutex_lock(&daemon->mux); mutex_lock(&daemon->mux);
mutex_unlock(&ecryptfs_daemon_hash_mux); mutex_unlock(&ecryptfs_daemon_hash_mux);
if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) { if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) {
...@@ -122,6 +125,7 @@ ecryptfs_miscdev_open(struct inode *inode, struct file *file) ...@@ -122,6 +125,7 @@ ecryptfs_miscdev_open(struct inode *inode, struct file *file)
goto out_unlock_daemon; goto out_unlock_daemon;
} }
daemon->flags |= ECRYPTFS_DAEMON_MISCDEV_OPEN; daemon->flags |= ECRYPTFS_DAEMON_MISCDEV_OPEN;
file->private_data = daemon;
atomic_inc(&ecryptfs_num_miscdev_opens); atomic_inc(&ecryptfs_num_miscdev_opens);
out_unlock_daemon: out_unlock_daemon:
mutex_unlock(&daemon->mux); mutex_unlock(&daemon->mux);
...@@ -152,9 +156,9 @@ ecryptfs_miscdev_release(struct inode *inode, struct file *file) ...@@ -152,9 +156,9 @@ ecryptfs_miscdev_release(struct inode *inode, struct file *file)
mutex_lock(&ecryptfs_daemon_hash_mux); mutex_lock(&ecryptfs_daemon_hash_mux);
rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns()); rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns());
BUG_ON(rc || !daemon); if (rc || !daemon)
daemon = file->private_data;
mutex_lock(&daemon->mux); mutex_lock(&daemon->mux);
BUG_ON(daemon->pid != task_pid(current));
BUG_ON(!(daemon->flags & ECRYPTFS_DAEMON_MISCDEV_OPEN)); BUG_ON(!(daemon->flags & ECRYPTFS_DAEMON_MISCDEV_OPEN));
daemon->flags &= ~ECRYPTFS_DAEMON_MISCDEV_OPEN; daemon->flags &= ~ECRYPTFS_DAEMON_MISCDEV_OPEN;
atomic_dec(&ecryptfs_num_miscdev_opens); atomic_dec(&ecryptfs_num_miscdev_opens);
...@@ -191,31 +195,32 @@ int ecryptfs_send_miscdev(char *data, size_t data_size, ...@@ -191,31 +195,32 @@ int ecryptfs_send_miscdev(char *data, size_t data_size,
struct ecryptfs_msg_ctx *msg_ctx, u8 msg_type, struct ecryptfs_msg_ctx *msg_ctx, u8 msg_type,
u16 msg_flags, struct ecryptfs_daemon *daemon) u16 msg_flags, struct ecryptfs_daemon *daemon)
{ {
int rc = 0; struct ecryptfs_message *msg;
mutex_lock(&msg_ctx->mux); msg = kmalloc((sizeof(*msg) + data_size), GFP_KERNEL);
msg_ctx->msg = kmalloc((sizeof(*msg_ctx->msg) + data_size), if (!msg) {
GFP_KERNEL);
if (!msg_ctx->msg) {
rc = -ENOMEM;
printk(KERN_ERR "%s: Out of memory whilst attempting " printk(KERN_ERR "%s: Out of memory whilst attempting "
"to kmalloc(%zd, GFP_KERNEL)\n", __func__, "to kmalloc(%zd, GFP_KERNEL)\n", __func__,
(sizeof(*msg_ctx->msg) + data_size)); (sizeof(*msg) + data_size));
goto out_unlock; return -ENOMEM;
} }
mutex_lock(&msg_ctx->mux);
msg_ctx->msg = msg;
msg_ctx->msg->index = msg_ctx->index; msg_ctx->msg->index = msg_ctx->index;
msg_ctx->msg->data_len = data_size; msg_ctx->msg->data_len = data_size;
msg_ctx->type = msg_type; msg_ctx->type = msg_type;
memcpy(msg_ctx->msg->data, data, data_size); memcpy(msg_ctx->msg->data, data, data_size);
msg_ctx->msg_size = (sizeof(*msg_ctx->msg) + data_size); msg_ctx->msg_size = (sizeof(*msg_ctx->msg) + data_size);
mutex_lock(&daemon->mux);
list_add_tail(&msg_ctx->daemon_out_list, &daemon->msg_ctx_out_queue); list_add_tail(&msg_ctx->daemon_out_list, &daemon->msg_ctx_out_queue);
mutex_unlock(&msg_ctx->mux);
mutex_lock(&daemon->mux);
daemon->num_queued_msg_ctx++; daemon->num_queued_msg_ctx++;
wake_up_interruptible(&daemon->wait); wake_up_interruptible(&daemon->wait);
mutex_unlock(&daemon->mux); mutex_unlock(&daemon->mux);
out_unlock:
mutex_unlock(&msg_ctx->mux); return 0;
return rc;
} }
/* /*
...@@ -269,8 +274,16 @@ ecryptfs_miscdev_read(struct file *file, char __user *buf, size_t count, ...@@ -269,8 +274,16 @@ ecryptfs_miscdev_read(struct file *file, char __user *buf, size_t count,
mutex_lock(&ecryptfs_daemon_hash_mux); mutex_lock(&ecryptfs_daemon_hash_mux);
/* TODO: Just use file->private_data? */ /* TODO: Just use file->private_data? */
rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns()); rc = ecryptfs_find_daemon_by_euid(&daemon, euid, current_user_ns());
BUG_ON(rc || !daemon); if (rc || !daemon) {
mutex_unlock(&ecryptfs_daemon_hash_mux);
return -EINVAL;
}
mutex_lock(&daemon->mux); mutex_lock(&daemon->mux);
if (task_pid(current) != daemon->pid) {
mutex_unlock(&daemon->mux);
mutex_unlock(&ecryptfs_daemon_hash_mux);
return -EPERM;
}
if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) { if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) {
rc = 0; rc = 0;
mutex_unlock(&ecryptfs_daemon_hash_mux); mutex_unlock(&ecryptfs_daemon_hash_mux);
...@@ -307,9 +320,6 @@ ecryptfs_miscdev_read(struct file *file, char __user *buf, size_t count, ...@@ -307,9 +320,6 @@ ecryptfs_miscdev_read(struct file *file, char __user *buf, size_t count,
* message from the queue; try again */ * message from the queue; try again */
goto check_list; goto check_list;
} }
BUG_ON(euid != daemon->euid);
BUG_ON(current_user_ns() != daemon->user_ns);
BUG_ON(task_pid(current) != daemon->pid);
msg_ctx = list_first_entry(&daemon->msg_ctx_out_queue, msg_ctx = list_first_entry(&daemon->msg_ctx_out_queue,
struct ecryptfs_msg_ctx, daemon_out_list); struct ecryptfs_msg_ctx, daemon_out_list);
BUG_ON(!msg_ctx); BUG_ON(!msg_ctx);
......
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