aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authordavid m. richter <richterd@citi.umich.edu>2007-07-31 03:39:12 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-31 18:39:42 -0400
commit9700382c3c9ff3e673e587084d76eedb3ba88668 (patch)
tree57ed58d87e765323692e463c8b7ee64f702dff0d /fs
parent937472b00b666ecbf1464502f857ec63b024af72 (diff)
VFS: fix a race in lease-breaking during truncate
It is possible that another process could acquire a new file lease right after break_lease() is called during a truncate, but before lease-granting is disabled by the subsequent get_write_access(). Merely switching the order of the break_lease() and get_write_access() calls prevents this race. Signed-off-by: David M. Richter <richterd@citi.umich.edu> Signed-off-by: "J. Bruce Fields" <bfields@citi.umich.edu> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/open.c16
1 files changed, 9 insertions, 7 deletions
diff --git a/fs/open.c b/fs/open.c
index e27c205364d3..1d9e5e98bf4e 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -256,24 +256,26 @@ static long do_sys_truncate(const char __user * path, loff_t length)
256 if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) 256 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
257 goto dput_and_out; 257 goto dput_and_out;
258 258
259 /* 259 error = get_write_access(inode);
260 * Make sure that there are no leases.
261 */
262 error = break_lease(inode, FMODE_WRITE);
263 if (error) 260 if (error)
264 goto dput_and_out; 261 goto dput_and_out;
265 262
266 error = get_write_access(inode); 263 /*
264 * Make sure that there are no leases. get_write_access() protects
265 * against the truncate racing with a lease-granting setlease().
266 */
267 error = break_lease(inode, FMODE_WRITE);
267 if (error) 268 if (error)
268 goto dput_and_out; 269 goto put_write_and_out;
269 270
270 error = locks_verify_truncate(inode, NULL, length); 271 error = locks_verify_truncate(inode, NULL, length);
271 if (!error) { 272 if (!error) {
272 DQUOT_INIT(inode); 273 DQUOT_INIT(inode);
273 error = do_truncate(nd.dentry, length, 0, NULL); 274 error = do_truncate(nd.dentry, length, 0, NULL);
274 } 275 }
275 put_write_access(inode);
276 276
277put_write_and_out:
278 put_write_access(inode);
277dput_and_out: 279dput_and_out:
278 path_release(&nd); 280 path_release(&nd);
279out: 281out: