eCryptfs: Check for O_RDONLY lower inodes when opening lower files
authorTyler Hicks <tyhicks@linux.vnet.ibm.com>
Wed, 12 Aug 2009 06:06:54 +0000 (01:06 -0500)
committerTyler Hicks <tyhicks@linux.vnet.ibm.com>
Wed, 23 Sep 2009 14:10:32 +0000 (09:10 -0500)
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: Serge 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: Tyler Hicks <tyhicks@linux.vnet.ibm.com>
fs/ecryptfs/kthread.c
fs/ecryptfs/main.c

index c6d7a4d..e14cf7e 100644 (file)
@@ -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:
index 9f0aa98..101fe4c 100644 (file)
@@ -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;
                }
        }