Commit ac22ba23 authored by Tyler Hicks's avatar Tyler Hicks

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
...@@ -136,6 +136,7 @@ int ecryptfs_privileged_open(struct file **lower_file, ...@@ -136,6 +136,7 @@ int ecryptfs_privileged_open(struct file **lower_file,
const struct cred *cred) const struct cred *cred)
{ {
struct ecryptfs_open_req *req; struct ecryptfs_open_req *req;
int flags = O_LARGEFILE;
int rc = 0; int rc = 0;
/* Corresponding dput() and mntput() are done when the /* Corresponding dput() and mntput() are done when the
...@@ -143,10 +144,14 @@ int ecryptfs_privileged_open(struct file **lower_file, ...@@ -143,10 +144,14 @@ int ecryptfs_privileged_open(struct file **lower_file,
* destroyed. */ * destroyed. */
dget(lower_dentry); dget(lower_dentry);
mntget(lower_mnt); mntget(lower_mnt);
(*lower_file) = dentry_open(lower_dentry, lower_mnt, flags |= IS_RDONLY(lower_dentry->d_inode) ? O_RDONLY : O_RDWR;
(O_RDWR | O_LARGEFILE), 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) {
rc = PTR_ERR((*lower_file));
goto out;
}
req = kmem_cache_alloc(ecryptfs_open_req_cache, GFP_KERNEL); req = kmem_cache_alloc(ecryptfs_open_req_cache, GFP_KERNEL);
if (!req) { if (!req) {
rc = -ENOMEM; rc = -ENOMEM;
...@@ -180,21 +185,8 @@ int ecryptfs_privileged_open(struct file **lower_file, ...@@ -180,21 +185,8 @@ int ecryptfs_privileged_open(struct file **lower_file,
__func__); __func__);
goto out_unlock; goto out_unlock;
} }
if (IS_ERR(*req->lower_file)) { if (IS_ERR(*req->lower_file))
rc = PTR_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: out_unlock:
mutex_unlock(&req->mux); mutex_unlock(&req->mux);
out_free: out_free:
......
...@@ -129,11 +129,10 @@ int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry) ...@@ -129,11 +129,10 @@ int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry)
lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry); lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
rc = ecryptfs_privileged_open(&inode_info->lower_file, rc = ecryptfs_privileged_open(&inode_info->lower_file,
lower_dentry, lower_mnt, cred); lower_dentry, lower_mnt, cred);
if (rc || IS_ERR(inode_info->lower_file)) { if (rc) {
printk(KERN_ERR "Error opening lower persistent file " printk(KERN_ERR "Error opening lower persistent file "
"for lower_dentry [0x%p] and lower_mnt [0x%p]; " "for lower_dentry [0x%p] and lower_mnt [0x%p]; "
"rc = [%d]\n", lower_dentry, lower_mnt, rc); "rc = [%d]\n", lower_dentry, lower_mnt, rc);
rc = PTR_ERR(inode_info->lower_file);
inode_info->lower_file = NULL; inode_info->lower_file = NULL;
} }
} }
......
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