[3.16.y-ckt stable] Patch "btrfs: fix signed overflows in btrfs_sync_file" has been added to staging queue
Luis Henriques
luis.henriques at canonical.com
Tue Jan 5 13:31:36 UTC 2016
This is a note to let you know that I have just added a patch titled
btrfs: fix signed overflows in btrfs_sync_file
to the linux-3.16.y-queue branch of the 3.16.y-ckt extended stable tree
which can be found at:
http://kernel.ubuntu.com/git/ubuntu/linux.git/log/?h=linux-3.16.y-queue
This patch is scheduled to be released in version 3.16.7-ckt22.
If you, or anyone else, feels it should not be added to this tree, please
reply to this email.
For more information about the 3.16.y-ckt tree, see
https://wiki.ubuntu.com/Kernel/Dev/ExtendedStable
Thanks.
-Luis
------
>From 8b867d859e1c31fd293096f0fddc24fce01ff41b Mon Sep 17 00:00:00 2001
From: David Sterba <dsterba at suse.com>
Date: Mon, 9 Nov 2015 11:44:45 +0100
Subject: btrfs: fix signed overflows in btrfs_sync_file
commit 9dcbeed4d7e11e1dcf5e55475de3754f0855d1c2 upstream.
The calculation of range length in btrfs_sync_file leads to signed
overflow. This was caught by PaX gcc SIZE_OVERFLOW plugin.
https://forums.grsecurity.net/viewtopic.php?f=1&t=4284
The fsync call passes 0 and LLONG_MAX, the range length does not fit to
loff_t and overflows, but the value is converted to u64 so it silently
works as expected.
The minimal fix is a typecast to u64, switching functions to take
(start, end) instead of (start, len) would be more intrusive.
Coccinelle script found that there's one more opencoded calculation of
the length.
<smpl>
@@
loff_t start, end;
@@
* end - start
</smpl>
Signed-off-by: David Sterba <dsterba at suse.com>
Signed-off-by: Chris Mason <clm at fb.com>
[ kamal: backport to 3.13-stable: use len in both btrfs_wait_ordered_range
calls, like
b659ef0 Btrfs: avoid syncing log in the fast fsync path when not necessary ]
Signed-off-by: Kamal Mostafa <kamal at canonical.com>
Signed-off-by: Luis Henriques <luis.henriques at canonical.com>
---
fs/btrfs/file.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 7a71c7885835..8d60cf519578 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -1868,7 +1868,13 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
struct btrfs_log_ctx ctx;
int ret = 0;
bool full_sync = 0;
+ u64 len;
+ /*
+ * The range length can be represented by u64, we have to do the typecasts
+ * to avoid signed overflow if it's [0, LLONG_MAX] eg. from fsync()
+ */
+ len = (u64)end - (u64)start + 1;
trace_btrfs_sync_file(file, datasync);
/*
@@ -1896,7 +1902,7 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
full_sync = test_bit(BTRFS_INODE_NEEDS_FULL_SYNC,
&BTRFS_I(inode)->runtime_flags);
if (full_sync) {
- ret = btrfs_wait_ordered_range(inode, start, end - start + 1);
+ ret = btrfs_wait_ordered_range(inode, start, len);
if (ret) {
mutex_unlock(&inode->i_mutex);
goto out;
@@ -2001,8 +2007,7 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
}
}
if (!full_sync) {
- ret = btrfs_wait_ordered_range(inode, start,
- end - start + 1);
+ ret = btrfs_wait_ordered_range(inode, start, len);
if (ret) {
btrfs_end_transaction(trans, root);
goto out;
More information about the kernel-team
mailing list