summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@gmail.com>2020-10-24 20:56:47 -0400
committerKent Overstreet <kent.overstreet@gmail.com>2020-11-05 12:45:14 -0500
commitcfbfd3e53cf303fe4b5a185e04007a177f2d246b (patch)
tree21c35a49d55617e946c60139890770cd009b21de
parentb40bdd9e763909e7c1dc14313afb01e1beefb0aa (diff)
bcachefs: Fix rare use after free in read path
If the bkey_on_stack_reassemble() call in __bch2_read_indirect_extent() reallocates the buffer, k in bch2_read - which we pointed at the bkey_on_stack buffer - will now point to a stale buffer. Whoops. Signed-off-by: Kent Overstreet <kent.overstreet@gmail.com>
-rw-r--r--fs/bcachefs/fs-io.c7
-rw-r--r--fs/bcachefs/fs.c11
-rw-r--r--fs/bcachefs/io.c6
3 files changed, 14 insertions, 10 deletions
diff --git a/fs/bcachefs/fs-io.c b/fs/bcachefs/fs-io.c
index 4ceeafcfa33c..3aed2ca4dced 100644
--- a/fs/bcachefs/fs-io.c
+++ b/fs/bcachefs/fs-io.c
@@ -839,18 +839,19 @@ retry:
if (ret)
break;
- bkey_on_stack_reassemble(&sk, c, k);
- k = bkey_i_to_s_c(sk.k);
-
offset_into_extent = iter->pos.offset -
bkey_start_offset(k.k);
sectors = k.k->size - offset_into_extent;
+ bkey_on_stack_reassemble(&sk, c, k);
+
ret = bch2_read_indirect_extent(trans,
&offset_into_extent, &sk);
if (ret)
break;
+ k = bkey_i_to_s_c(sk.k);
+
sectors = min(sectors, k.k->size - offset_into_extent);
bch2_trans_unlock(trans);
diff --git a/fs/bcachefs/fs.c b/fs/bcachefs/fs.c
index fcef87f8f2f2..5e0921f36f77 100644
--- a/fs/bcachefs/fs.c
+++ b/fs/bcachefs/fs.c
@@ -898,20 +898,21 @@ retry:
continue;
}
- bkey_on_stack_realloc(&cur, c, k.k->u64s);
- bkey_on_stack_realloc(&prev, c, k.k->u64s);
- bkey_reassemble(cur.k, k);
- k = bkey_i_to_s_c(cur.k);
-
offset_into_extent = iter->pos.offset -
bkey_start_offset(k.k);
sectors = k.k->size - offset_into_extent;
+ bkey_on_stack_realloc(&cur, c, k.k->u64s);
+ bkey_on_stack_realloc(&prev, c, k.k->u64s);
+ bkey_reassemble(cur.k, k);
+
ret = bch2_read_indirect_extent(&trans,
&offset_into_extent, &cur);
if (ret)
break;
+ k = bkey_i_to_s_c(cur.k);
+
sectors = min(sectors, k.k->size - offset_into_extent);
if (offset_into_extent)
diff --git a/fs/bcachefs/io.c b/fs/bcachefs/io.c
index 58cc90b198f5..970ad8f7d1ed 100644
--- a/fs/bcachefs/io.c
+++ b/fs/bcachefs/io.c
@@ -1676,7 +1676,6 @@ retry:
unsigned bytes, sectors, offset_into_extent;
bkey_on_stack_reassemble(&sk, c, k);
- k = bkey_i_to_s_c(sk.k);
offset_into_extent = iter->pos.offset -
bkey_start_offset(k.k);
@@ -1687,6 +1686,8 @@ retry:
if (ret)
break;
+ k = bkey_i_to_s_c(sk.k);
+
sectors = min(sectors, k.k->size - offset_into_extent);
bch2_trans_unlock(&trans);
@@ -2314,13 +2315,14 @@ retry:
sectors = k.k->size - offset_into_extent;
bkey_on_stack_reassemble(&sk, c, k);
- k = bkey_i_to_s_c(sk.k);
ret = bch2_read_indirect_extent(&trans,
&offset_into_extent, &sk);
if (ret)
goto err;
+ k = bkey_i_to_s_c(sk.k);
+
/*
* With indirect extents, the amount of data to read is the min
* of the original extent and the indirect extent: