Commit ac22ba23b659e34a5961aec8c945608e471b0d5b
1 parent
b0105eaefa
Exists in
master
and in
7 other branches
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: |
fs/ecryptfs/main.c
... | ... | @@ -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 | } |