diff options
author | Tyler Hicks <tyhicks@linux.vnet.ibm.com> | 2009-08-12 02:06:54 -0400 |
---|---|---|
committer | Tyler Hicks <tyhicks@linux.vnet.ibm.com> | 2009-09-23 10:10:32 -0400 |
commit | ac22ba23b659e34a5961aec8c945608e471b0d5b (patch) | |
tree | 6629c15380fe2db238fa078e912f4cf393708161 /fs/ecryptfs | |
parent | b0105eaefa7cce8f4a941d0fc6354b250d30e745 (diff) |
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>
Diffstat (limited to 'fs/ecryptfs')
-rw-r--r-- | fs/ecryptfs/kthread.c | 24 | ||||
-rw-r--r-- | fs/ecryptfs/main.c | 3 |
2 files changed, 9 insertions, 18 deletions
diff --git a/fs/ecryptfs/kthread.c b/fs/ecryptfs/kthread.c index c6d7a4d748a0..e14cf7e588db 100644 --- a/fs/ecryptfs/kthread.c +++ b/fs/ecryptfs/kthread.c | |||
@@ -136,6 +136,7 @@ int ecryptfs_privileged_open(struct file **lower_file, | |||
136 | const struct cred *cred) | 136 | const struct cred *cred) |
137 | { | 137 | { |
138 | struct ecryptfs_open_req *req; | 138 | struct ecryptfs_open_req *req; |
139 | int flags = O_LARGEFILE; | ||
139 | int rc = 0; | 140 | int rc = 0; |
140 | 141 | ||
141 | /* Corresponding dput() and mntput() are done when the | 142 | /* Corresponding dput() and mntput() are done when the |
@@ -143,10 +144,14 @@ int ecryptfs_privileged_open(struct file **lower_file, | |||
143 | * destroyed. */ | 144 | * destroyed. */ |
144 | dget(lower_dentry); | 145 | dget(lower_dentry); |
145 | mntget(lower_mnt); | 146 | mntget(lower_mnt); |
146 | (*lower_file) = dentry_open(lower_dentry, lower_mnt, | 147 | flags |= IS_RDONLY(lower_dentry->d_inode) ? O_RDONLY : O_RDWR; |
147 | (O_RDWR | O_LARGEFILE), cred); | 148 | (*lower_file) = dentry_open(lower_dentry, lower_mnt, flags, cred); |
148 | if (!IS_ERR(*lower_file)) | 149 | if (!IS_ERR(*lower_file)) |
149 | goto out; | 150 | goto out; |
151 | if (flags & O_RDONLY) { | ||
152 | rc = PTR_ERR((*lower_file)); | ||
153 | goto out; | ||
154 | } | ||
150 | req = kmem_cache_alloc(ecryptfs_open_req_cache, GFP_KERNEL); | 155 | req = kmem_cache_alloc(ecryptfs_open_req_cache, GFP_KERNEL); |
151 | if (!req) { | 156 | if (!req) { |
152 | rc = -ENOMEM; | 157 | rc = -ENOMEM; |
@@ -180,21 +185,8 @@ int ecryptfs_privileged_open(struct file **lower_file, | |||
180 | __func__); | 185 | __func__); |
181 | goto out_unlock; | 186 | goto out_unlock; |
182 | } | 187 | } |
183 | if (IS_ERR(*req->lower_file)) { | 188 | if (IS_ERR(*req->lower_file)) |
184 | rc = PTR_ERR(*req->lower_file); | 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 | out_unlock: | 190 | out_unlock: |
199 | mutex_unlock(&req->mux); | 191 | mutex_unlock(&req->mux); |
200 | out_free: | 192 | out_free: |
diff --git a/fs/ecryptfs/main.c b/fs/ecryptfs/main.c index 9f0aa9883c28..101fe4c7b1ee 100644 --- a/fs/ecryptfs/main.c +++ b/fs/ecryptfs/main.c | |||
@@ -129,11 +129,10 @@ int ecryptfs_init_persistent_file(struct dentry *ecryptfs_dentry) | |||
129 | lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry); | 129 | lower_dentry = ecryptfs_dentry_to_lower(ecryptfs_dentry); |
130 | rc = ecryptfs_privileged_open(&inode_info->lower_file, | 130 | rc = ecryptfs_privileged_open(&inode_info->lower_file, |
131 | lower_dentry, lower_mnt, cred); | 131 | lower_dentry, lower_mnt, cred); |
132 | if (rc || IS_ERR(inode_info->lower_file)) { | 132 | if (rc) { |
133 | printk(KERN_ERR "Error opening lower persistent file " | 133 | printk(KERN_ERR "Error opening lower persistent file " |
134 | "for lower_dentry [0x%p] and lower_mnt [0x%p]; " | 134 | "for lower_dentry [0x%p] and lower_mnt [0x%p]; " |
135 | "rc = [%d]\n", lower_dentry, lower_mnt, rc); | 135 | "rc = [%d]\n", lower_dentry, lower_mnt, rc); |
136 | rc = PTR_ERR(inode_info->lower_file); | ||
137 | inode_info->lower_file = NULL; | 136 | inode_info->lower_file = NULL; |
138 | } | 137 | } |
139 | } | 138 | } |