In commit 42d9f6c77479 ("crypto: acomp - Move scomp stream allocation code into acomp"), the crypto_acomp_streams struct was made to rely on having the alloc_ctx and free_ctx operations defined in the same order as the scomp_alg struct. But in that same commit, the alloc_ctx and free_ctx members of scomp_alg may be randomized by structure layout randomization, since they are contained in a pure ops structure (containing only function pointers). If the pointers within scomp_alg are randomized, but those in crypto_acomp_streams are not, then the order may no longer match. This fixes the problem by defining a shared structure that both crypto_acomp_streams and scomp_alg share: acomp_ctx_ops. This new pure ops structure may now be randomized, while still allowing both crypto_acomp_streams and scomp_alg to have matching layout. Signed-off-by: Dan Moulding <dan@xxxxxxxx> Fixes: 42d9f6c77479 ("crypto: acomp - Move scomp stream allocation code into acomp") --- crypto/acompress.c | 6 +++--- crypto/lz4.c | 6 ++++-- include/crypto/internal/acompress.h | 10 +++++++--- include/crypto/internal/scompress.h | 5 +---- 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/crypto/acompress.c b/crypto/acompress.c index be28cbfd22e3..ff910035ee42 100644 --- a/crypto/acompress.c +++ b/crypto/acompress.c @@ -375,7 +375,7 @@ static void acomp_stream_workfn(struct work_struct *work) if (ps->ctx) continue; - ctx = s->alloc_ctx(); + ctx = s->ctx_ops.alloc_ctx(); if (IS_ERR(ctx)) break; @@ -398,7 +398,7 @@ void crypto_acomp_free_streams(struct crypto_acomp_streams *s) return; cancel_work_sync(&s->stream_work); - free_ctx = s->free_ctx; + free_ctx = s->ctx_ops.free_ctx; for_each_possible_cpu(i) { struct crypto_acomp_stream *ps = per_cpu_ptr(streams, i); @@ -427,7 +427,7 @@ int crypto_acomp_alloc_streams(struct crypto_acomp_streams *s) if (!streams) return -ENOMEM; - ctx = s->alloc_ctx(); + ctx = s->ctx_ops.alloc_ctx(); if (IS_ERR(ctx)) { free_percpu(streams); return PTR_ERR(ctx); diff --git a/crypto/lz4.c b/crypto/lz4.c index 7a984ae5ae52..c16c0d936708 100644 --- a/crypto/lz4.c +++ b/crypto/lz4.c @@ -68,8 +68,10 @@ static int lz4_sdecompress(struct crypto_scomp *tfm, const u8 *src, } static struct scomp_alg scomp = { - .alloc_ctx = lz4_alloc_ctx, - .free_ctx = lz4_free_ctx, + .ctx_ops = { + .alloc_ctx = lz4_alloc_ctx, + .free_ctx = lz4_free_ctx, + }, .compress = lz4_scompress, .decompress = lz4_sdecompress, .base = { diff --git a/include/crypto/internal/acompress.h b/include/crypto/internal/acompress.h index 2d97440028ff..c84a17ac26ca 100644 --- a/include/crypto/internal/acompress.h +++ b/include/crypto/internal/acompress.h @@ -55,15 +55,19 @@ struct acomp_alg { }; }; +struct acomp_ctx_ops { + void *(*alloc_ctx)(void); + void (*free_ctx)(void *); +}; + struct crypto_acomp_stream { spinlock_t lock; void *ctx; }; struct crypto_acomp_streams { - /* These must come first because of struct scomp_alg. */ - void *(*alloc_ctx)(void); - void (*free_ctx)(void *); + /* This must come first because of struct scomp_alg. */ + struct acomp_ctx_ops ctx_ops; struct crypto_acomp_stream __percpu *streams; struct work_struct stream_work; diff --git a/include/crypto/internal/scompress.h b/include/crypto/internal/scompress.h index 533d6c16a491..1d807a15aef2 100644 --- a/include/crypto/internal/scompress.h +++ b/include/crypto/internal/scompress.h @@ -35,10 +35,7 @@ struct scomp_alg { void *ctx); union { - struct { - void *(*alloc_ctx)(void); - void (*free_ctx)(void *ctx); - }; + struct acomp_ctx_ops ctx_ops; struct crypto_acomp_streams streams; }; -- 2.49.1