Skip to content

Commit d41519a

Browse files
davem330herbertx
authored andcommitted
crypto: Work around deallocated stack frame reference gcc bug on sparc.
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. Cc: <[email protected]> Reported-by: Anatoly Pugachev <[email protected]> Signed-off-by: David S. Miller <[email protected]> Signed-off-by: Herbert Xu <[email protected]>
1 parent f3ad587 commit d41519a

File tree

4 files changed

+16
-5
lines changed

4 files changed

+16
-5
lines changed

drivers/infiniband/sw/rxe/rxe.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
static inline u32 rxe_crc32(struct rxe_dev *rxe,
6969
u32 crc, void *next, size_t len)
7070
{
71+
u32 retval;
7172
int err;
7273

7374
SHASH_DESC_ON_STACK(shash, rxe->tfm);
@@ -81,7 +82,9 @@ static inline u32 rxe_crc32(struct rxe_dev *rxe,
8182
return crc32_le(crc, next, len);
8283
}
8384

84-
return *(u32 *)shash_desc_ctx(shash);
85+
retval = *(u32 *)shash_desc_ctx(shash);
86+
barrier_data(shash_desc_ctx(shash));
87+
return retval;
8588
}
8689

8790
int rxe_set_mtu(struct rxe_dev *rxe, unsigned int dev_mtu);

fs/btrfs/hash.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ u32 btrfs_crc32c(u32 crc, const void *address, unsigned int length)
3838
{
3939
SHASH_DESC_ON_STACK(shash, tfm);
4040
u32 *ctx = (u32 *)shash_desc_ctx(shash);
41+
u32 retval;
4142
int err;
4243

4344
shash->tfm = tfm;
@@ -47,5 +48,7 @@ u32 btrfs_crc32c(u32 crc, const void *address, unsigned int length)
4748
err = crypto_shash_update(shash, address, length);
4849
BUG_ON(err);
4950

50-
return *ctx;
51+
retval = *ctx;
52+
barrier_data(ctx);
53+
return retval;
5154
}

fs/f2fs/f2fs.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1078,6 +1078,7 @@ static inline u32 f2fs_crc32(struct f2fs_sb_info *sbi, const void *address,
10781078
{
10791079
SHASH_DESC_ON_STACK(shash, sbi->s_chksum_driver);
10801080
u32 *ctx = (u32 *)shash_desc_ctx(shash);
1081+
u32 retval;
10811082
int err;
10821083

10831084
shash->tfm = sbi->s_chksum_driver;
@@ -1087,7 +1088,9 @@ static inline u32 f2fs_crc32(struct f2fs_sb_info *sbi, const void *address,
10871088
err = crypto_shash_update(shash, address, length);
10881089
BUG_ON(err);
10891090

1090-
return *ctx;
1091+
retval = *ctx;
1092+
barrier_data(ctx);
1093+
return retval;
10911094
}
10921095

10931096
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
@@ -43,7 +43,7 @@ static struct crypto_shash *tfm;
4343
u32 crc32c(u32 crc, const void *address, unsigned int length)
4444
{
4545
SHASH_DESC_ON_STACK(shash, tfm);
46-
u32 *ctx = (u32 *)shash_desc_ctx(shash);
46+
u32 ret, *ctx = (u32 *)shash_desc_ctx(shash);
4747
int err;
4848

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

56-
return *ctx;
56+
ret = *ctx;
57+
barrier_data(ctx);
58+
return ret;
5759
}
5860

5961
EXPORT_SYMBOL(crc32c);

0 commit comments

Comments
 (0)