Commit ac22ba23 authored by Tyler Hicks's avatar Tyler Hicks
Browse files

eCryptfs: Check for O_RDONLY lower inodes when opening lower files



If the lower inode is read-only, don't attempt to open the lower file
read/write and don't hand off the open request to the privileged
eCryptfs kthread for opening it read/write.  Instead, only try an
unprivileged, read-only open of the file and give up if that fails.
This patch fixes an oops when eCryptfs is mounted on top of a read-only
mount.

Acked-by: default avatarSerge Hallyn <serue@us.ibm.com>
Cc: Eric Sandeen <esandeen@redhat.com>
Cc: Dave Kleikamp <shaggy@linux.vnet.ibm.com>
Cc: ecryptfs-devel@lists.launchpad.net
Cc: stable <stable@kernel.org>
Signed-off-by: default avatarTyler Hicks <tyhicks@linux.vnet.ibm.com>
parent b0105eae
Loading
Loading
Loading
Loading
+8 −16
Original line number Diff line number Diff line
@@ -136,6 +136,7 @@ int ecryptfs_privileged_open(struct file **lower_file,
			     const struct cred *cred)
{
	struct ecryptfs_open_req *req;
	int flags = O_LARGEFILE;
	int rc = 0;

	/* Corresponding dput() and mntput() are done when the
@@ -143,10 +144,14 @@ int ecryptfs_privileged_open(struct file **lower_file,
	 * destroyed. */
	dget(lower_dentry);
	mntget(lower_mnt);
	(*lower_file) = dentry_open(lower_dentry, lower_mnt,
				    (O_RDWR | O_LARGEFILE), cred);
	flags |= IS_RDONLY(lower_dentry->d_inode) ? O_RDONLY : O_RDWR;
	(*lower_file) = dentry_open(lower_dentry, lower_mnt, flags, cred);
	if (!IS_ERR(*lower_file))
		goto out;
	if (flags & O_RDONLY) {
		rc = PTR_ERR((*lower_file));
		goto out;
	}
	req = kmem_cache_alloc(ecryptfs_open_req_cache, GFP_KERNEL);
	if (!req) {
		rc = -ENOMEM;
@@ -180,21 +185,8 @@ int ecryptfs_privileged_open(struct file **lower_file,
		       __func__);
		goto out_unlock;
	}
	if (IS_ERR(*req->lower_file)) {
	if (IS_ERR(*req->lower_file))
		rc = PTR_ERR(*req->lower_file);
		dget(lower_dentry);
		mntget(lower_mnt);
		(*lower_file) = dentry_open(lower_dentry, lower_mnt,
					    (O_RDONLY | O_LARGEFILE), cred);
		if (IS_ERR(*lower_file)) {
			rc = PTR_ERR(*req->lower_file);
			(*lower_file) = NULL;
			printk(KERN_WARNING "%s: Error attempting privileged "
			       "open of lower file with either RW or RO "
			       "perms; rc = [%d]. Giving up.\n",
			       __func__, rc);
		}
	}
out_unlock:
	mutex_unlock(&req->mux);
out_free:
+1 −2
Original line number Diff line number Diff line
@@ -129,11 +129,10 @@ int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry)
		lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
		rc = ecryptfs_privileged_open(&inode_info->lower_file,
					      lower_dentry, lower_mnt, cred);
		if (rc || IS_ERR(inode_info->lower_file)) {
		if (rc) {
			printk(KERN_ERR "Error opening lower persistent file "
			       "for lower_dentry [0x%p] and lower_mnt [0x%p]; "
			       "rc = [%d]\n", lower_dentry, lower_mnt, rc);
			rc = PTR_ERR(inode_info->lower_file);
			inode_info->lower_file = NULL;
		}
	}