Commit ac22ba23b659e34a5961aec8c945608e471b0d5b

Authored by Tyler Hicks
1 parent b0105eaefa

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: 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>

Showing 2 changed files with 9 additions and 18 deletions Side-by-side Diff

fs/ecryptfs/kthread.c
... ... @@ -136,6 +136,7 @@
136 136 const struct cred *cred)
137 137 {
138 138 struct ecryptfs_open_req *req;
  139 + int flags = O_LARGEFILE;
139 140 int rc = 0;
140 141  
141 142 /* Corresponding dput() and mntput() are done when the
142 143  
... ... @@ -143,10 +144,14 @@
143 144 * destroyed. */
144 145 dget(lower_dentry);
145 146 mntget(lower_mnt);
146   - (*lower_file) = dentry_open(lower_dentry, lower_mnt,
147   - (O_RDWR | O_LARGEFILE), cred);
  147 + flags |= IS_RDONLY(lower_dentry->d_inode) ? O_RDONLY : O_RDWR;
  148 + (*lower_file) = dentry_open(lower_dentry, lower_mnt, flags, cred);
148 149 if (!IS_ERR(*lower_file))
149 150 goto out;
  151 + if (flags & O_RDONLY) {
  152 + rc = PTR_ERR((*lower_file));
  153 + goto out;
  154 + }
150 155 req = kmem_cache_alloc(ecryptfs_open_req_cache, GFP_KERNEL);
151 156 if (!req) {
152 157 rc = -ENOMEM;
153 158  
... ... @@ -180,21 +185,8 @@
180 185 __func__);
181 186 goto out_unlock;
182 187 }
183   - if (IS_ERR(*req->lower_file)) {
  188 + if (IS_ERR(*req->lower_file))
184 189 rc = PTR_ERR(*req->lower_file);
185   - dget(lower_dentry);
186   - mntget(lower_mnt);
187   - (*lower_file) = dentry_open(lower_dentry, lower_mnt,
188   - (O_RDONLY | O_LARGEFILE), cred);
189   - if (IS_ERR(*lower_file)) {
190   - rc = PTR_ERR(*req->lower_file);
191   - (*lower_file) = NULL;
192   - printk(KERN_WARNING "%s: Error attempting privileged "
193   - "open of lower file with either RW or RO "
194   - "perms; rc = [%d]. Giving up.\n",
195   - __func__, rc);
196   - }
197   - }
198 190 out_unlock:
199 191 mutex_unlock(&req->mux);
200 192 out_free:
... ... @@ -129,11 +129,10 @@
129 129 lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry);
130 130 rc = ecryptfs_privileged_open(&inode_info->lower_file,
131 131 lower_dentry, lower_mnt, cred);
132   - if (rc || IS_ERR(inode_info->lower_file)) {
  132 + if (rc) {
133 133 printk(KERN_ERR "Error opening lower persistent file "
134 134 "for lower_dentry [0x%p] and lower_mnt [0x%p]; "
135 135 "rc = [%d]\n", lower_dentry, lower_mnt, rc);
136   - rc = PTR_ERR(inode_info->lower_file);
137 136 inode_info->lower_file = NULL;
138 137 }
139 138 }