2019-05-30 06:57:49 +07:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
2010-01-06 15:47:10 +07:00
|
|
|
/*
|
|
|
|
* padata.h - header for the padata parallelization interface
|
|
|
|
*
|
|
|
|
* Copyright (C) 2008, 2009 secunet Security Networks AG
|
|
|
|
* Copyright (C) 2008, 2009 Steffen Klassert <steffen.klassert@secunet.com>
|
2020-06-04 05:59:43 +07:00
|
|
|
*
|
|
|
|
* Copyright (c) 2020 Oracle and/or its affiliates.
|
|
|
|
* Author: Daniel Jordan <daniel.m.jordan@oracle.com>
|
2010-01-06 15:47:10 +07:00
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef PADATA_H
|
|
|
|
#define PADATA_H
|
|
|
|
|
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: 5068c7a883d1 ("crypto: pcrypt - Add pcrypt crypto parallelization wrapper")
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Tested-by: Eric Biggers <ebiggers@kernel.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2019-11-26 14:58:45 +07:00
|
|
|
#include <linux/compiler_types.h>
|
2010-01-06 15:47:10 +07:00
|
|
|
#include <linux/workqueue.h>
|
|
|
|
#include <linux/spinlock.h>
|
|
|
|
#include <linux/list.h>
|
2010-07-14 17:33:08 +07:00
|
|
|
#include <linux/kobject.h>
|
2010-07-14 17:31:57 +07:00
|
|
|
|
|
|
|
#define PADATA_CPU_SERIAL 0x01
|
|
|
|
#define PADATA_CPU_PARALLEL 0x02
|
2010-01-06 15:47:10 +07:00
|
|
|
|
2010-05-19 10:44:27 +07:00
|
|
|
/**
|
2019-12-04 02:31:14 +07:00
|
|
|
* struct padata_priv - Represents one job
|
2010-05-19 10:44:27 +07:00
|
|
|
*
|
|
|
|
* @list: List entry, to attach to the padata lists.
|
|
|
|
* @pd: Pointer to the internal control structure.
|
|
|
|
* @cb_cpu: Callback cpu for serializatioon.
|
|
|
|
* @seq_nr: Sequence number of the parallelized data object.
|
|
|
|
* @info: Used to pass information from the parallel to the serial function.
|
|
|
|
* @parallel: Parallel execution function.
|
|
|
|
* @serial: Serial complete function.
|
|
|
|
*/
|
2010-01-06 15:47:10 +07:00
|
|
|
struct padata_priv {
|
|
|
|
struct list_head list;
|
|
|
|
struct parallel_data *pd;
|
|
|
|
int cb_cpu;
|
2019-09-06 08:40:28 +07:00
|
|
|
unsigned int seq_nr;
|
2010-01-06 15:47:10 +07:00
|
|
|
int info;
|
|
|
|
void (*parallel)(struct padata_priv *padata);
|
|
|
|
void (*serial)(struct padata_priv *padata);
|
|
|
|
};
|
|
|
|
|
2010-05-19 10:44:27 +07:00
|
|
|
/**
|
2019-12-04 02:31:14 +07:00
|
|
|
* struct padata_list - one per work type per CPU
|
2010-05-19 10:44:27 +07:00
|
|
|
*
|
|
|
|
* @list: List head.
|
|
|
|
* @lock: List lock.
|
|
|
|
*/
|
2010-01-06 15:47:10 +07:00
|
|
|
struct padata_list {
|
|
|
|
struct list_head list;
|
|
|
|
spinlock_t lock;
|
|
|
|
};
|
|
|
|
|
2010-05-19 10:44:27 +07:00
|
|
|
/**
|
2010-07-14 17:31:57 +07:00
|
|
|
* struct padata_serial_queue - The percpu padata serial queue
|
|
|
|
*
|
|
|
|
* @serial: List to wait for serialization after reordering.
|
|
|
|
* @work: work struct for serialization.
|
|
|
|
* @pd: Backpointer to the internal control structure.
|
|
|
|
*/
|
|
|
|
struct padata_serial_queue {
|
|
|
|
struct padata_list serial;
|
|
|
|
struct work_struct work;
|
|
|
|
struct parallel_data *pd;
|
|
|
|
};
|
|
|
|
|
2010-07-27 12:15:50 +07:00
|
|
|
/**
|
|
|
|
* struct padata_cpumask - The cpumasks for the parallel/serial workers
|
|
|
|
*
|
|
|
|
* @pcpu: cpumask for the parallel workers.
|
|
|
|
* @cbcpu: cpumask for the serial (callback) workers.
|
|
|
|
*/
|
|
|
|
struct padata_cpumask {
|
|
|
|
cpumask_var_t pcpu;
|
|
|
|
cpumask_var_t cbcpu;
|
|
|
|
};
|
2010-07-14 17:31:57 +07:00
|
|
|
|
2010-05-19 10:44:27 +07:00
|
|
|
/**
|
|
|
|
* struct parallel_data - Internal control structure, covers everything
|
|
|
|
* that depends on the cpumask in use.
|
|
|
|
*
|
2019-12-04 02:31:14 +07:00
|
|
|
* @ps: padata_shell object.
|
2020-07-15 03:13:56 +07:00
|
|
|
* @reorder_list: percpu reorder lists
|
2010-07-14 17:31:57 +07:00
|
|
|
* @squeue: percpu padata queues used for serialuzation.
|
2010-05-19 10:44:27 +07:00
|
|
|
* @refcnt: Number of objects holding a reference on this parallel_data.
|
2019-12-04 02:31:14 +07:00
|
|
|
* @seq_nr: Sequence number of the parallelized data object.
|
2019-09-06 08:40:28 +07:00
|
|
|
* @processed: Number of already processed objects.
|
2019-07-18 22:01:46 +07:00
|
|
|
* @cpu: Next CPU to be processed.
|
2010-07-27 12:15:50 +07:00
|
|
|
* @cpumask: The cpumasks in use for parallel and serial workers.
|
2019-07-18 22:01:46 +07:00
|
|
|
* @reorder_work: work struct for reordering.
|
2010-05-19 10:44:27 +07:00
|
|
|
* @lock: Reorder lock.
|
|
|
|
*/
|
2010-01-06 15:47:10 +07:00
|
|
|
struct parallel_data {
|
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: 5068c7a883d1 ("crypto: pcrypt - Add pcrypt crypto parallelization wrapper")
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Tested-by: Eric Biggers <ebiggers@kernel.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2019-11-26 14:58:45 +07:00
|
|
|
struct padata_shell *ps;
|
2020-07-15 03:13:56 +07:00
|
|
|
struct padata_list __percpu *reorder_list;
|
2010-09-03 18:09:46 +07:00
|
|
|
struct padata_serial_queue __percpu *squeue;
|
2010-07-27 12:15:50 +07:00
|
|
|
atomic_t refcnt;
|
2020-06-04 05:59:39 +07:00
|
|
|
unsigned int seq_nr;
|
2019-09-06 08:40:28 +07:00
|
|
|
unsigned int processed;
|
2019-07-18 22:01:46 +07:00
|
|
|
int cpu;
|
2010-07-27 12:15:50 +07:00
|
|
|
struct padata_cpumask cpumask;
|
2019-07-18 22:01:46 +07:00
|
|
|
struct work_struct reorder_work;
|
2019-12-04 02:31:14 +07:00
|
|
|
spinlock_t ____cacheline_aligned lock;
|
2010-01-06 15:47:10 +07:00
|
|
|
};
|
|
|
|
|
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: 5068c7a883d1 ("crypto: pcrypt - Add pcrypt crypto parallelization wrapper")
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Tested-by: Eric Biggers <ebiggers@kernel.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2019-11-26 14:58:45 +07:00
|
|
|
/**
|
|
|
|
* struct padata_shell - Wrapper around struct parallel_data, its
|
|
|
|
* purpose is to allow the underlying control structure to be replaced
|
|
|
|
* on the fly using RCU.
|
|
|
|
*
|
|
|
|
* @pinst: padat instance.
|
|
|
|
* @pd: Actual parallel_data structure which may be substituted on the fly.
|
|
|
|
* @opd: Pointer to old pd to be freed by padata_replace.
|
|
|
|
* @list: List entry in padata_instance list.
|
|
|
|
*/
|
|
|
|
struct padata_shell {
|
|
|
|
struct padata_instance *pinst;
|
|
|
|
struct parallel_data __rcu *pd;
|
|
|
|
struct parallel_data *opd;
|
|
|
|
struct list_head list;
|
|
|
|
};
|
|
|
|
|
2020-06-04 05:59:43 +07:00
|
|
|
/**
|
|
|
|
* struct padata_mt_job - represents one multithreaded job
|
|
|
|
*
|
|
|
|
* @thread_fn: Called for each chunk of work that a padata thread does.
|
|
|
|
* @fn_arg: The thread function argument.
|
|
|
|
* @start: The start of the job (units are job-specific).
|
|
|
|
* @size: size of this node's work (units are job-specific).
|
|
|
|
* @align: Ranges passed to the thread function fall on this boundary, with the
|
|
|
|
* possible exceptions of the beginning and end of the job.
|
|
|
|
* @min_chunk: The minimum chunk size in job-specific units. This allows
|
|
|
|
* the client to communicate the minimum amount of work that's
|
|
|
|
* appropriate for one worker thread to do at once.
|
|
|
|
* @max_threads: Max threads to use for the job, actual number may be less
|
|
|
|
* depending on task size and minimum chunk size.
|
|
|
|
*/
|
|
|
|
struct padata_mt_job {
|
|
|
|
void (*thread_fn)(unsigned long start, unsigned long end, void *arg);
|
|
|
|
void *fn_arg;
|
|
|
|
unsigned long start;
|
|
|
|
unsigned long size;
|
|
|
|
unsigned long align;
|
|
|
|
unsigned long min_chunk;
|
|
|
|
int max_threads;
|
|
|
|
};
|
|
|
|
|
2010-05-19 10:44:27 +07:00
|
|
|
/**
|
|
|
|
* struct padata_instance - The overall control structure.
|
|
|
|
*
|
2020-04-21 23:34:55 +07:00
|
|
|
* @cpu_online_node: Linkage for CPU online callback.
|
|
|
|
* @cpu_dead_node: Linkage for CPU offline callback.
|
2019-09-06 08:40:27 +07:00
|
|
|
* @parallel_wq: The workqueue used for parallel work.
|
|
|
|
* @serial_wq: The workqueue used for serial work.
|
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: 5068c7a883d1 ("crypto: pcrypt - Add pcrypt crypto parallelization wrapper")
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Tested-by: Eric Biggers <ebiggers@kernel.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2019-11-26 14:58:45 +07:00
|
|
|
* @pslist: List of padata_shell objects attached to this instance.
|
2010-07-27 12:15:50 +07:00
|
|
|
* @cpumask: User supplied cpumasks for parallel and serial works.
|
2010-07-14 17:33:08 +07:00
|
|
|
* @kobj: padata instance kernel object.
|
2010-05-19 10:44:27 +07:00
|
|
|
* @lock: padata instance lock.
|
|
|
|
* @flags: padata flags.
|
|
|
|
*/
|
2010-01-06 15:47:10 +07:00
|
|
|
struct padata_instance {
|
2020-04-21 23:34:55 +07:00
|
|
|
struct hlist_node cpu_online_node;
|
|
|
|
struct hlist_node cpu_dead_node;
|
2019-09-06 08:40:27 +07:00
|
|
|
struct workqueue_struct *parallel_wq;
|
|
|
|
struct workqueue_struct *serial_wq;
|
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: 5068c7a883d1 ("crypto: pcrypt - Add pcrypt crypto parallelization wrapper")
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Tested-by: Eric Biggers <ebiggers@kernel.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2019-11-26 14:58:45 +07:00
|
|
|
struct list_head pslist;
|
2010-07-27 12:15:50 +07:00
|
|
|
struct padata_cpumask cpumask;
|
2010-07-14 17:33:08 +07:00
|
|
|
struct kobject kobj;
|
2010-07-14 17:31:57 +07:00
|
|
|
struct mutex lock;
|
|
|
|
u8 flags;
|
|
|
|
#define PADATA_INIT 1
|
|
|
|
#define PADATA_RESET 2
|
|
|
|
#define PADATA_INVALID 4
|
2010-01-06 15:47:10 +07:00
|
|
|
};
|
|
|
|
|
2020-06-04 05:59:35 +07:00
|
|
|
#ifdef CONFIG_PADATA
|
|
|
|
extern void __init padata_init(void);
|
|
|
|
#else
|
|
|
|
static inline void __init padata_init(void) {}
|
|
|
|
#endif
|
|
|
|
|
2020-07-15 03:13:55 +07:00
|
|
|
extern struct padata_instance *padata_alloc(const char *name);
|
2010-01-06 15:47:10 +07:00
|
|
|
extern void padata_free(struct padata_instance *pinst);
|
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: 5068c7a883d1 ("crypto: pcrypt - Add pcrypt crypto parallelization wrapper")
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Tested-by: Eric Biggers <ebiggers@kernel.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
2019-11-26 14:58:45 +07:00
|
|
|
extern struct padata_shell *padata_alloc_shell(struct padata_instance *pinst);
|
|
|
|
extern void padata_free_shell(struct padata_shell *ps);
|
|
|
|
extern int padata_do_parallel(struct padata_shell *ps,
|
2019-09-06 08:40:24 +07:00
|
|
|
struct padata_priv *padata, int *cb_cpu);
|
2010-01-06 15:47:10 +07:00
|
|
|
extern void padata_do_serial(struct padata_priv *padata);
|
2020-06-04 05:59:43 +07:00
|
|
|
extern void __init padata_do_multithreaded(struct padata_mt_job *job);
|
2010-07-14 17:31:57 +07:00
|
|
|
extern int padata_set_cpumask(struct padata_instance *pinst, int cpumask_type,
|
2010-01-06 15:47:10 +07:00
|
|
|
cpumask_var_t cpumask);
|
|
|
|
#endif
|