Skip to content

Commit bbefa1d

Browse files
committed
crypto: pcrypt - Avoid deadlock by using per-instance padata queues
If the pcrypt template is used multiple times in an algorithm, then a deadlock occurs because all pcrypt instances share the same padata_instance, which completes requests in the order submitted. That is, the inner pcrypt request waits for the outer pcrypt request while the outer request is already waiting for the inner. This patch fixes this by allocating a set of queues for each pcrypt instance instead of using two global queues. In order to maintain the existing user-space interface, the pinst structure remains global so any sysfs modifications will apply to every pcrypt instance. Note that when an update occurs we have to allocate memory for every pcrypt instance. Should one of the allocations fail we will abort the update without rolling back changes already made. The new per-instance data structure is called padata_shell and is essentially a wrapper around parallel_data. Reproducer: #include <linux/if_alg.h> #include <sys/socket.h> #include <unistd.h> int main() { struct sockaddr_alg addr = { .salg_type = "aead", .salg_name = "pcrypt(pcrypt(rfc4106-gcm-aesni))" }; int algfd, reqfd; char buf[32] = { 0 }; algfd = socket(AF_ALG, SOCK_SEQPACKET, 0); bind(algfd, (void *)&addr, sizeof(addr)); setsockopt(algfd, SOL_ALG, ALG_SET_KEY, buf, 20); reqfd = accept(algfd, 0, 0); write(reqfd, buf, 32); read(reqfd, buf, 16); } Reported-by: syzbot+56c7151cad94eec37c521f0e47d2eee53f9361c4@syzkaller.appspotmail.com Fixes: 5068c7a ("crypto: pcrypt - Add pcrypt crypto parallelization wrapper") Signed-off-by: Herbert Xu <[email protected]> Tested-by: Eric Biggers <[email protected]> Signed-off-by: Herbert Xu <[email protected]>
1 parent 45a536e commit bbefa1d

File tree

3 files changed

+227
-79
lines changed

3 files changed

+227
-79
lines changed

crypto/pcrypt.c

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ static struct kset *pcrypt_kset;
2424

2525
struct pcrypt_instance_ctx {
2626
struct crypto_aead_spawn spawn;
27+
struct padata_shell *psenc;
28+
struct padata_shell *psdec;
2729
atomic_t tfm_count;
2830
};
2931

@@ -32,6 +34,12 @@ struct pcrypt_aead_ctx {
3234
unsigned int cb_cpu;
3335
};
3436

37+
static inline struct pcrypt_instance_ctx *pcrypt_tfm_ictx(
38+
struct crypto_aead *tfm)
39+
{
40+
return aead_instance_ctx(aead_alg_instance(tfm));
41+
}
42+
3543
static int pcrypt_aead_setkey(struct crypto_aead *parent,
3644
const u8 *key, unsigned int keylen)
3745
{
@@ -90,6 +98,9 @@ static int pcrypt_aead_encrypt(struct aead_request *req)
9098
struct crypto_aead *aead = crypto_aead_reqtfm(req);
9199
struct pcrypt_aead_ctx *ctx = crypto_aead_ctx(aead);
92100
u32 flags = aead_request_flags(req);
101+
struct pcrypt_instance_ctx *ictx;
102+
103+
ictx = pcrypt_tfm_ictx(aead);
93104

94105
memset(padata, 0, sizeof(struct padata_priv));
95106

@@ -103,7 +114,7 @@ static int pcrypt_aead_encrypt(struct aead_request *req)
103114
req->cryptlen, req->iv);
104115
aead_request_set_ad(creq, req->assoclen);
105116

106-
err = padata_do_parallel(pencrypt, padata, &ctx->cb_cpu);
117+
err = padata_do_parallel(ictx->psenc, padata, &ctx->cb_cpu);
107118
if (!err)
108119
return -EINPROGRESS;
109120

@@ -132,6 +143,9 @@ static int pcrypt_aead_decrypt(struct aead_request *req)
132143
struct crypto_aead *aead = crypto_aead_reqtfm(req);
133144
struct pcrypt_aead_ctx *ctx = crypto_aead_ctx(aead);
134145
u32 flags = aead_request_flags(req);
146+
struct pcrypt_instance_ctx *ictx;
147+
148+
ictx = pcrypt_tfm_ictx(aead);
135149

136150
memset(padata, 0, sizeof(struct padata_priv));
137151

@@ -145,7 +159,7 @@ static int pcrypt_aead_decrypt(struct aead_request *req)
145159
req->cryptlen, req->iv);
146160
aead_request_set_ad(creq, req->assoclen);
147161

148-
err = padata_do_parallel(pdecrypt, padata, &ctx->cb_cpu);
162+
err = padata_do_parallel(ictx->psdec, padata, &ctx->cb_cpu);
149163
if (!err)
150164
return -EINPROGRESS;
151165

@@ -192,6 +206,8 @@ static void pcrypt_free(struct aead_instance *inst)
192206
struct pcrypt_instance_ctx *ctx = aead_instance_ctx(inst);
193207

194208
crypto_drop_aead(&ctx->spawn);
209+
padata_free_shell(ctx->psdec);
210+
padata_free_shell(ctx->psenc);
195211
kfree(inst);
196212
}
197213

@@ -233,12 +249,22 @@ static int pcrypt_create_aead(struct crypto_template *tmpl, struct rtattr **tb,
233249
if (!inst)
234250
return -ENOMEM;
235251

252+
err = -ENOMEM;
253+
236254
ctx = aead_instance_ctx(inst);
255+
ctx->psenc = padata_alloc_shell(pencrypt);
256+
if (!ctx->psenc)
257+
goto out_free_inst;
258+
259+
ctx->psdec = padata_alloc_shell(pdecrypt);
260+
if (!ctx->psdec)
261+
goto out_free_psenc;
262+
237263
crypto_set_aead_spawn(&ctx->spawn, aead_crypto_instance(inst));
238264

239265
err = crypto_grab_aead(&ctx->spawn, name, 0, 0);
240266
if (err)
241-
goto out_free_inst;
267+
goto out_free_psdec;
242268

243269
alg = crypto_spawn_aead_alg(&ctx->spawn);
244270
err = pcrypt_init_instance(aead_crypto_instance(inst), &alg->base);
@@ -271,6 +297,10 @@ static int pcrypt_create_aead(struct crypto_template *tmpl, struct rtattr **tb,
271297

272298
out_drop_aead:
273299
crypto_drop_aead(&ctx->spawn);
300+
out_free_psdec:
301+
padata_free_shell(ctx->psdec);
302+
out_free_psenc:
303+
padata_free_shell(ctx->psenc);
274304
out_free_inst:
275305
kfree(inst);
276306
goto out;

include/linux/padata.h

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#ifndef PADATA_H
1010
#define PADATA_H
1111

12+
#include <linux/compiler_types.h>
1213
#include <linux/workqueue.h>
1314
#include <linux/spinlock.h>
1415
#include <linux/list.h>
@@ -98,7 +99,7 @@ struct padata_cpumask {
9899
* struct parallel_data - Internal control structure, covers everything
99100
* that depends on the cpumask in use.
100101
*
101-
* @pinst: padata instance.
102+
* @sh: padata_shell object.
102103
* @pqueue: percpu padata queues used for parallelization.
103104
* @squeue: percpu padata queues used for serialuzation.
104105
* @reorder_objects: Number of objects waiting in the reorder queues.
@@ -111,7 +112,7 @@ struct padata_cpumask {
111112
* @lock: Reorder lock.
112113
*/
113114
struct parallel_data {
114-
struct padata_instance *pinst;
115+
struct padata_shell *ps;
115116
struct padata_parallel_queue __percpu *pqueue;
116117
struct padata_serial_queue __percpu *squeue;
117118
atomic_t reorder_objects;
@@ -124,14 +125,33 @@ struct parallel_data {
124125
spinlock_t lock ____cacheline_aligned;
125126
};
126127

128+
/**
129+
* struct padata_shell - Wrapper around struct parallel_data, its
130+
* purpose is to allow the underlying control structure to be replaced
131+
* on the fly using RCU.
132+
*
133+
* @pinst: padat instance.
134+
* @pd: Actual parallel_data structure which may be substituted on the fly.
135+
* @opd: Pointer to old pd to be freed by padata_replace.
136+
* @list: List entry in padata_instance list.
137+
*/
138+
struct padata_shell {
139+
struct padata_instance *pinst;
140+
struct parallel_data __rcu *pd;
141+
struct parallel_data *opd;
142+
struct list_head list;
143+
};
144+
127145
/**
128146
* struct padata_instance - The overall control structure.
129147
*
130148
* @cpu_notifier: cpu hotplug notifier.
131149
* @parallel_wq: The workqueue used for parallel work.
132150
* @serial_wq: The workqueue used for serial work.
133-
* @pd: The internal control structure.
151+
* @pslist: List of padata_shell objects attached to this instance.
134152
* @cpumask: User supplied cpumasks for parallel and serial works.
153+
* @rcpumask: Actual cpumasks based on user cpumask and cpu_online_mask.
154+
* @omask: Temporary storage used to compute the notification mask.
135155
* @cpumask_change_notifier: Notifiers chain for user-defined notify
136156
* callbacks that will be called when either @pcpu or @cbcpu
137157
* or both cpumasks change.
@@ -143,8 +163,10 @@ struct padata_instance {
143163
struct hlist_node node;
144164
struct workqueue_struct *parallel_wq;
145165
struct workqueue_struct *serial_wq;
146-
struct parallel_data *pd;
166+
struct list_head pslist;
147167
struct padata_cpumask cpumask;
168+
struct padata_cpumask rcpumask;
169+
cpumask_var_t omask;
148170
struct blocking_notifier_head cpumask_change_notifier;
149171
struct kobject kobj;
150172
struct mutex lock;
@@ -156,7 +178,9 @@ struct padata_instance {
156178

157179
extern struct padata_instance *padata_alloc_possible(const char *name);
158180
extern void padata_free(struct padata_instance *pinst);
159-
extern int padata_do_parallel(struct padata_instance *pinst,
181+
extern struct padata_shell *padata_alloc_shell(struct padata_instance *pinst);
182+
extern void padata_free_shell(struct padata_shell *ps);
183+
extern int padata_do_parallel(struct padata_shell *ps,
160184
struct padata_priv *padata, int *cb_cpu);
161185
extern void padata_do_serial(struct padata_priv *padata);
162186
extern int padata_set_cpumask(struct padata_instance *pinst, int cpumask_type,

0 commit comments

Comments
 (0)