Skip to content

Commit c7fa8b7

Browse files
davem330pundiramit
authored andcommitted
crypto: Work around deallocated stack frame reference gcc bug on sparc.
commit d41519a69b35b10af7fda867fb9100df24fdf403 upstream. On sparc, if we have an alloca() like situation, as is the case with SHASH_DESC_ON_STACK(), we can end up referencing deallocated stack memory. The result can be that the value is clobbered if a trap or interrupt arrives at just the right instruction. It only occurs if the function ends returning a value from that alloca() area and that value can be placed into the return value register using a single instruction. For example, in lib/libcrc32c.c:crc32c() we end up with a return sequence like: return %i7+8 lduw [%o5+16], %o0 ! MEM[(u32 *)__shash_desc.1_10 + 16B], %o5 holds the base of the on-stack area allocated for the shash descriptor. But the return released the stack frame and the register window. So if an intererupt arrives between 'return' and 'lduw', then the value read at %o5+16 can be corrupted. Add a data compiler barrier to work around this problem. This is exactly what the gcc fix will end up doing as well, and it absolutely should not change the code generated for other cpus (unless gcc on them has the same bug :-) With crucial insight from Eric Sandeen. Reported-by: Anatoly Pugachev <matorola@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 00034f4 commit c7fa8b7

3 files changed

Lines changed: 12 additions & 4 deletions

File tree

fs/btrfs/hash.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ u32 btrfs_crc32c(u32 crc, const void *address, unsigned int length)
3333
{
3434
SHASH_DESC_ON_STACK(shash, tfm);
3535
u32 *ctx = (u32 *)shash_desc_ctx(shash);
36+
u32 retval;
3637
int err;
3738

3839
shash->tfm = tfm;
@@ -42,5 +43,7 @@ u32 btrfs_crc32c(u32 crc, const void *address, unsigned int length)
4243
err = crypto_shash_update(shash, address, length);
4344
BUG_ON(err);
4445

45-
return *ctx;
46+
retval = *ctx;
47+
barrier_data(ctx);
48+
return retval;
4649
}

fs/f2fs/f2fs.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1268,6 +1268,7 @@ static inline u32 f2fs_crc32(struct f2fs_sb_info *sbi, const void *address,
12681268
{
12691269
SHASH_DESC_ON_STACK(shash, sbi->s_chksum_driver);
12701270
u32 *ctx = (u32 *)shash_desc_ctx(shash);
1271+
u32 retval;
12711272
int err;
12721273

12731274
shash->tfm = sbi->s_chksum_driver;
@@ -1277,7 +1278,9 @@ static inline u32 f2fs_crc32(struct f2fs_sb_info *sbi, const void *address,
12771278
err = crypto_shash_update(shash, address, length);
12781279
BUG_ON(err);
12791280

1280-
return *ctx;
1281+
retval = *ctx;
1282+
barrier_data(ctx);
1283+
return retval;
12811284
}
12821285

12831286
static inline bool f2fs_crc_valid(struct f2fs_sb_info *sbi, __u32 blk_crc,

lib/libcrc32c.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ static struct crypto_shash *tfm;
4242
u32 crc32c(u32 crc, const void *address, unsigned int length)
4343
{
4444
SHASH_DESC_ON_STACK(shash, tfm);
45-
u32 *ctx = (u32 *)shash_desc_ctx(shash);
45+
u32 ret, *ctx = (u32 *)shash_desc_ctx(shash);
4646
int err;
4747

4848
shash->tfm = tfm;
@@ -52,7 +52,9 @@ u32 crc32c(u32 crc, const void *address, unsigned int length)
5252
err = crypto_shash_update(shash, address, length);
5353
BUG_ON(err);
5454

55-
return *ctx;
55+
ret = *ctx;
56+
barrier_data(ctx);
57+
return ret;
5658
}
5759

5860
EXPORT_SYMBOL(crc32c);

0 commit comments

Comments
 (0)