Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -149,7 +149,7 @@ int ecryptfs_privileged_open(struct file **lower_file,
	(*lower_file) = dentry_open(lower_dentry, lower_mnt, flags, cred);
	if (!IS_ERR(*lower_file))
		goto out;
	if (flags & O_RDONLY) {
	if ((flags & O_ACCMODE) == O_RDONLY) {
		rc = PTR_ERR((*lower_file));
		goto out;
	}
+29 −19
Original line number Diff line number Diff line
@@ -49,7 +49,10 @@ 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, euid, current_user_ns());
	BUG_ON(rc || !daemon);
	if (rc || !daemon) {
		mutex_unlock(&ecryptfs_daemon_hash_mux);
		return -EINVAL;
	}
	mutex_lock(&daemon->mux);
	mutex_unlock(&ecryptfs_daemon_hash_mux);
	if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) {
@@ -122,6 +125,7 @@ ecryptfs_miscdev_open(struct inode *inode, struct file *file)
		goto out_unlock_daemon;
	}
	daemon->flags |= ECRYPTFS_DAEMON_MISCDEV_OPEN;
	file->private_data = daemon;
	atomic_inc(&ecryptfs_num_miscdev_opens);
out_unlock_daemon:
	mutex_unlock(&daemon->mux);
@@ -152,9 +156,9 @@ ecryptfs_miscdev_release(struct inode *inode, struct file *file)

	mutex_lock(&ecryptfs_daemon_hash_mux);
	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);
	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);
@@ -191,31 +195,32 @@ 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;
	struct ecryptfs_message *msg;

	mutex_lock(&msg_ctx->mux);
	msg_ctx->msg = kmalloc((sizeof(*msg_ctx->msg) + data_size),
			       GFP_KERNEL);
	if (!msg_ctx->msg) {
		rc = -ENOMEM;
	msg = kmalloc((sizeof(*msg) + data_size), GFP_KERNEL);
	if (!msg) {
		printk(KERN_ERR "%s: Out of memory whilst attempting "
		       "to kmalloc(%zd, GFP_KERNEL)\n", __func__,
		       (sizeof(*msg_ctx->msg) + data_size));
		goto out_unlock;
		       (sizeof(*msg) + data_size));
		return -ENOMEM;
	}

	mutex_lock(&msg_ctx->mux);
	msg_ctx->msg = msg;
	msg_ctx->msg->index = msg_ctx->index;
	msg_ctx->msg->data_len = data_size;
	msg_ctx->type = msg_type;
	memcpy(msg_ctx->msg->data, data, 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);
	mutex_unlock(&msg_ctx->mux);

	mutex_lock(&daemon->mux);
	daemon->num_queued_msg_ctx++;
	wake_up_interruptible(&daemon->wait);
	mutex_unlock(&daemon->mux);
out_unlock:
	mutex_unlock(&msg_ctx->mux);
	return rc;

	return 0;
}

/*
@@ -269,8 +274,16 @@ 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, euid, current_user_ns());
	BUG_ON(rc || !daemon);
	if (rc || !daemon) {
		mutex_unlock(&ecryptfs_daemon_hash_mux);
		return -EINVAL;
	}
	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) {
		rc = 0;
		mutex_unlock(&ecryptfs_daemon_hash_mux);
@@ -307,9 +320,6 @@ check_list:
		 * message from the queue; try again */
		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,
				   struct ecryptfs_msg_ctx, daemon_out_list);
	BUG_ON(!msg_ctx);