Skip to content

Commit 5416b8a

Browse files
committed
crypto: acomp - Add ACOMP_REQUEST_ALLOC and acomp_request_alloc_extra
Add ACOMP_REQUEST_ALLOC which is a wrapper around acomp_request_alloc that falls back to a synchronous stack reqeust if the allocation fails. Also add ACOMP_REQUEST_ON_STACK which stores the request on the stack only. The request should be freed with acomp_request_free. Finally add acomp_request_alloc_extra which gives the user extra memory to use in conjunction with the request. Signed-off-by: Herbert Xu <[email protected]>
1 parent 2c1808e commit 5416b8a

File tree

4 files changed

+117
-8
lines changed

4 files changed

+117
-8
lines changed

crypto/acompress.c

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,28 +60,56 @@ static void crypto_acomp_exit_tfm(struct crypto_tfm *tfm)
6060
struct crypto_acomp *acomp = __crypto_acomp_tfm(tfm);
6161
struct acomp_alg *alg = crypto_acomp_alg(acomp);
6262

63-
alg->exit(acomp);
63+
if (alg->exit)
64+
alg->exit(acomp);
65+
66+
if (acomp_is_async(acomp))
67+
crypto_free_acomp(acomp->fb);
6468
}
6569

6670
static int crypto_acomp_init_tfm(struct crypto_tfm *tfm)
6771
{
6872
struct crypto_acomp *acomp = __crypto_acomp_tfm(tfm);
6973
struct acomp_alg *alg = crypto_acomp_alg(acomp);
74+
struct crypto_acomp *fb = NULL;
75+
int err;
76+
77+
acomp->fb = acomp;
7078

7179
if (tfm->__crt_alg->cra_type != &crypto_acomp_type)
7280
return crypto_init_scomp_ops_async(tfm);
7381

82+
if (acomp_is_async(acomp)) {
83+
fb = crypto_alloc_acomp(crypto_acomp_alg_name(acomp), 0,
84+
CRYPTO_ALG_ASYNC);
85+
if (IS_ERR(fb))
86+
return PTR_ERR(fb);
87+
88+
err = -EINVAL;
89+
if (crypto_acomp_reqsize(fb) > MAX_SYNC_COMP_REQSIZE)
90+
goto out_free_fb;
91+
92+
acomp->fb = fb;
93+
}
94+
7495
acomp->compress = alg->compress;
7596
acomp->decompress = alg->decompress;
7697
acomp->reqsize = alg->reqsize;
7798

78-
if (alg->exit)
79-
acomp->base.exit = crypto_acomp_exit_tfm;
99+
acomp->base.exit = crypto_acomp_exit_tfm;
80100

81-
if (alg->init)
82-
return alg->init(acomp);
101+
if (!alg->init)
102+
return 0;
103+
104+
err = alg->init(acomp);
105+
if (err)
106+
goto out_free_fb;
83107

84108
return 0;
109+
110+
out_free_fb:
111+
crypto_free_acomp(fb);
112+
return err;
85113
}
86114

87115
static unsigned int crypto_acomp_extsize(struct crypto_alg *alg)

include/crypto/acompress.h

Lines changed: 77 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@
1010
#define _CRYPTO_ACOMP_H
1111

1212
#include <linux/atomic.h>
13+
#include <linux/args.h>
1314
#include <linux/compiler_types.h>
1415
#include <linux/container_of.h>
1516
#include <linux/crypto.h>
17+
#include <linux/err.h>
1618
#include <linux/scatterlist.h>
1719
#include <linux/slab.h>
1820
#include <linux/spinlock_types.h>
@@ -32,6 +34,14 @@
3234

3335
#define CRYPTO_ACOMP_DST_MAX 131072
3436

37+
#define MAX_SYNC_COMP_REQSIZE 0
38+
39+
#define ACOMP_REQUEST_ALLOC(name, tfm, gfp) \
40+
char __##name##_req[sizeof(struct acomp_req) + \
41+
MAX_SYNC_COMP_REQSIZE] CRYPTO_MINALIGN_ATTR; \
42+
struct acomp_req *name = acomp_request_on_stack_init( \
43+
__##name##_req, (tfm), (gfp), false)
44+
3545
struct acomp_req;
3646

3747
struct acomp_req_chain {
@@ -83,12 +93,14 @@ struct acomp_req {
8393
* @compress: Function performs a compress operation
8494
* @decompress: Function performs a de-compress operation
8595
* @reqsize: Context size for (de)compression requests
96+
* @fb: Synchronous fallback tfm
8697
* @base: Common crypto API algorithm data structure
8798
*/
8899
struct crypto_acomp {
89100
int (*compress)(struct acomp_req *req);
90101
int (*decompress)(struct acomp_req *req);
91102
unsigned int reqsize;
103+
struct crypto_acomp *fb;
92104
struct crypto_tfm base;
93105
};
94106

@@ -210,24 +222,68 @@ static inline int crypto_has_acomp(const char *alg_name, u32 type, u32 mask)
210222
return crypto_has_alg(alg_name, type, mask);
211223
}
212224

225+
static inline const char *crypto_acomp_alg_name(struct crypto_acomp *tfm)
226+
{
227+
return crypto_tfm_alg_name(crypto_acomp_tfm(tfm));
228+
}
229+
230+
static inline const char *crypto_acomp_driver_name(struct crypto_acomp *tfm)
231+
{
232+
return crypto_tfm_alg_driver_name(crypto_acomp_tfm(tfm));
233+
}
234+
213235
/**
214236
* acomp_request_alloc() -- allocates asynchronous (de)compression request
215237
*
216238
* @tfm: ACOMPRESS tfm handle allocated with crypto_alloc_acomp()
239+
* @gfp: gfp to pass to kzalloc (defaults to GFP_KERNEL)
217240
*
218241
* Return: allocated handle in case of success or NULL in case of an error
219242
*/
220-
static inline struct acomp_req *acomp_request_alloc_noprof(struct crypto_acomp *tfm)
243+
static inline struct acomp_req *acomp_request_alloc_extra_noprof(
244+
struct crypto_acomp *tfm, size_t extra, gfp_t gfp)
221245
{
222246
struct acomp_req *req;
247+
size_t len;
248+
249+
len = ALIGN(sizeof(*req) + crypto_acomp_reqsize(tfm), CRYPTO_MINALIGN);
250+
if (check_add_overflow(len, extra, &len))
251+
return NULL;
223252

224-
req = kzalloc_noprof(sizeof(*req) + crypto_acomp_reqsize(tfm), GFP_KERNEL);
253+
req = kzalloc_noprof(len, gfp);
225254
if (likely(req))
226255
acomp_request_set_tfm(req, tfm);
227256
return req;
228257
}
258+
#define acomp_request_alloc_noprof(tfm, ...) \
259+
CONCATENATE(acomp_request_alloc_noprof_, COUNT_ARGS(__VA_ARGS__))( \
260+
tfm, ##__VA_ARGS__)
261+
#define acomp_request_alloc_noprof_0(tfm) \
262+
acomp_request_alloc_noprof_1(tfm, GFP_KERNEL)
263+
#define acomp_request_alloc_noprof_1(tfm, gfp) \
264+
acomp_request_alloc_extra_noprof(tfm, 0, gfp)
229265
#define acomp_request_alloc(...) alloc_hooks(acomp_request_alloc_noprof(__VA_ARGS__))
230266

267+
/**
268+
* acomp_request_alloc_extra() -- allocate acomp request with extra memory
269+
*
270+
* @tfm: ACOMPRESS tfm handle allocated with crypto_alloc_acomp()
271+
* @extra: amount of extra memory
272+
* @gfp: gfp to pass to kzalloc
273+
*
274+
* Return: allocated handle in case of success or NULL in case of an error
275+
*/
276+
#define acomp_request_alloc_extra(...) alloc_hooks(acomp_request_alloc_extra_noprof(__VA_ARGS__))
277+
278+
static inline void *acomp_request_extra(struct acomp_req *req)
279+
{
280+
struct crypto_acomp *tfm = crypto_acomp_reqtfm(req);
281+
size_t len;
282+
283+
len = ALIGN(sizeof(*req) + crypto_acomp_reqsize(tfm), CRYPTO_MINALIGN);
284+
return (void *)((char *)req + len);
285+
}
286+
231287
/**
232288
* acomp_request_free() -- zeroize and free asynchronous (de)compression
233289
* request as well as the output buffer if allocated
@@ -237,6 +293,8 @@ static inline struct acomp_req *acomp_request_alloc_noprof(struct crypto_acomp *
237293
*/
238294
static inline void acomp_request_free(struct acomp_req *req)
239295
{
296+
if (!req || (req->base.flags & CRYPTO_TFM_REQ_ON_STACK))
297+
return;
240298
kfree_sensitive(req);
241299
}
242300

@@ -257,7 +315,8 @@ static inline void acomp_request_set_callback(struct acomp_req *req,
257315
void *data)
258316
{
259317
u32 keep = CRYPTO_ACOMP_REQ_SRC_VIRT | CRYPTO_ACOMP_REQ_SRC_NONDMA |
260-
CRYPTO_ACOMP_REQ_DST_VIRT | CRYPTO_ACOMP_REQ_DST_NONDMA;
318+
CRYPTO_ACOMP_REQ_DST_VIRT | CRYPTO_ACOMP_REQ_DST_NONDMA |
319+
CRYPTO_TFM_REQ_ON_STACK;
261320

262321
req->base.complete = cmpl;
263322
req->base.data = data;
@@ -446,4 +505,19 @@ int crypto_acomp_compress(struct acomp_req *req);
446505
*/
447506
int crypto_acomp_decompress(struct acomp_req *req);
448507

508+
static inline struct acomp_req *acomp_request_on_stack_init(
509+
char *buf, struct crypto_acomp *tfm, gfp_t gfp, bool stackonly)
510+
{
511+
struct acomp_req *req;
512+
513+
if (!stackonly && (req = acomp_request_alloc(tfm, gfp)))
514+
return req;
515+
516+
req = (void *)buf;
517+
acomp_request_set_tfm(req, tfm->fb);
518+
req->base.flags = CRYPTO_TFM_REQ_ON_STACK;
519+
520+
return req;
521+
}
522+
449523
#endif

include/crypto/internal/acompress.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@
1212
#include <crypto/acompress.h>
1313
#include <crypto/algapi.h>
1414

15+
#define ACOMP_REQUEST_ON_STACK(name, tfm) \
16+
char __##name##_req[sizeof(struct acomp_req) + \
17+
MAX_SYNC_COMP_REQSIZE] CRYPTO_MINALIGN_ATTR; \
18+
struct acomp_req *name = acomp_request_on_stack_init( \
19+
__##name##_req, (tfm), 0, true)
20+
1521
/**
1622
* struct acomp_alg - asynchronous compression algorithm
1723
*

include/linux/crypto.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@
138138
#define CRYPTO_TFM_REQ_FORBID_WEAK_KEYS 0x00000100
139139
#define CRYPTO_TFM_REQ_MAY_SLEEP 0x00000200
140140
#define CRYPTO_TFM_REQ_MAY_BACKLOG 0x00000400
141+
#define CRYPTO_TFM_REQ_ON_STACK 0x00000800
141142

142143
/*
143144
* Miscellaneous stuff.

0 commit comments

Comments
 (0)