@@ -3,6 +3,8 @@
# Cryptographic API
#
+CAPABILITY_ANALYSIS := y
+
obj-$(CONFIG_CRYPTO) += crypto.o
crypto-y := api.o cipher.o compress.o
@@ -230,6 +230,7 @@ EXPORT_SYMBOL_GPL(crypto_remove_spawns);
static void crypto_alg_finish_registration(struct crypto_alg *alg,
struct list_head *algs_to_put)
+ __must_hold(&crypto_alg_sem)
{
struct crypto_alg *q;
@@ -286,6 +287,7 @@ static struct crypto_larval *crypto_alloc_test_larval(struct crypto_alg *alg)
static struct crypto_larval *
__crypto_register_alg(struct crypto_alg *alg, struct list_head *algs_to_put)
+ __must_hold(&crypto_alg_sem)
{
struct crypto_alg *q;
struct crypto_larval *larval;
@@ -57,6 +57,7 @@ EXPORT_SYMBOL_GPL(crypto_mod_put);
static struct crypto_alg *__crypto_alg_lookup(const char *name, u32 type,
u32 mask)
+ __must_hold_shared(&crypto_alg_sem)
{
struct crypto_alg *q, *alg = NULL;
int best = -2;
@@ -514,8 +514,8 @@ struct crypto_engine *crypto_engine_alloc_init_and_set(struct device *dev,
snprintf(engine->name, sizeof(engine->name),
"%s-engine", dev_name(dev));
- crypto_init_queue(&engine->queue, qlen);
spin_lock_init(&engine->queue_lock);
+ crypto_init_queue(&engine->queue, qlen);
engine->kworker = kthread_run_worker(0, "%s", engine->name);
if (IS_ERR(engine->kworker)) {
@@ -231,6 +231,7 @@ static inline unsigned short drbg_sec_strength(drbg_flag_t flags)
*/
static int drbg_fips_continuous_test(struct drbg_state *drbg,
const unsigned char *entropy)
+ __must_hold(&drbg->drbg_mutex)
{
unsigned short entropylen = drbg_sec_strength(drbg->core->flags);
int ret = 0;
@@ -1061,6 +1062,7 @@ static inline int __drbg_seed(struct drbg_state *drbg, struct list_head *seed,
static inline int drbg_get_random_bytes(struct drbg_state *drbg,
unsigned char *entropy,
unsigned int entropylen)
+ __must_hold(&drbg->drbg_mutex)
{
int ret;
@@ -1075,6 +1077,7 @@ static inline int drbg_get_random_bytes(struct drbg_state *drbg,
}
static int drbg_seed_from_random(struct drbg_state *drbg)
+ __must_hold(&drbg->drbg_mutex)
{
struct drbg_string data;
LIST_HEAD(seedlist);
@@ -1132,6 +1135,7 @@ static bool drbg_nopr_reseed_interval_elapsed(struct drbg_state *drbg)
*/
static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
bool reseed)
+ __must_hold(&drbg->drbg_mutex)
{
int ret;
unsigned char entropy[((32 + 16) * 2)];
@@ -1368,6 +1372,7 @@ static inline int drbg_alloc_state(struct drbg_state *drbg)
static int drbg_generate(struct drbg_state *drbg,
unsigned char *buf, unsigned int buflen,
struct drbg_string *addtl)
+ __must_hold(&drbg->drbg_mutex)
{
int len = 0;
LIST_HEAD(addtllist);
@@ -45,8 +45,8 @@ enum {
/* Maximum number of (rtattr) parameters for each template. */
#define CRYPTO_MAX_ATTRS 32
-extern struct list_head crypto_alg_list;
extern struct rw_semaphore crypto_alg_sem;
+extern struct list_head crypto_alg_list __guarded_by(&crypto_alg_sem);
extern struct blocking_notifier_head crypto_chain;
int alg_test(const char *driver, const char *alg, u32 type, u32 mask);
@@ -19,17 +19,20 @@
#include "internal.h"
static void *c_start(struct seq_file *m, loff_t *pos)
+ __acquires_shared(&crypto_alg_sem)
{
down_read(&crypto_alg_sem);
return seq_list_start(&crypto_alg_list, *pos);
}
static void *c_next(struct seq_file *m, void *p, loff_t *pos)
+ __must_hold_shared(&crypto_alg_sem)
{
return seq_list_next(p, &crypto_alg_list, pos);
}
static void c_stop(struct seq_file *m, void *p)
+ __releases_shared(&crypto_alg_sem)
{
up_read(&crypto_alg_sem);
}
@@ -25,8 +25,8 @@
struct scomp_scratch {
spinlock_t lock;
- void *src;
- void *dst;
+ void *src __guarded_by(&lock);
+ void *dst __guarded_by(&lock);
};
static DEFINE_PER_CPU(struct scomp_scratch, scomp_scratch) = {
@@ -34,8 +34,8 @@ static DEFINE_PER_CPU(struct scomp_scratch, scomp_scratch) = {
};
static const struct crypto_type crypto_scomp_type;
-static int scomp_scratch_users;
static DEFINE_MUTEX(scomp_lock);
+static int scomp_scratch_users __guarded_by(&scomp_lock);
static int __maybe_unused crypto_scomp_report(
struct sk_buff *skb, struct crypto_alg *alg)
@@ -59,6 +59,7 @@ static void crypto_scomp_show(struct seq_file *m, struct crypto_alg *alg)
}
static void crypto_scomp_free_scratches(void)
+ __capability_unsafe(/* frees @scratch */)
{
struct scomp_scratch *scratch;
int i;
@@ -74,6 +75,7 @@ static void crypto_scomp_free_scratches(void)
}
static int crypto_scomp_alloc_scratches(void)
+ __capability_unsafe(/* allocates @scratch */)
{
struct scomp_scratch *scratch;
int i;
@@ -54,7 +54,7 @@ struct crypto_engine {
struct list_head list;
spinlock_t queue_lock;
- struct crypto_queue queue;
+ struct crypto_queue queue __guarded_by(&queue_lock);
struct device *dev;
bool rt;
Enable capability analysis for crypto subsystem. This demonstrates a larger conversion to use Clang's capability analysis. The benefit is additional static checking of locking rules, along with better documentation. Signed-off-by: Marco Elver <elver@google.com> Cc: Herbert Xu <herbert@gondor.apana.org.au> Cc: "David S. Miller" <davem@davemloft.net> Cc: linux-crypto@vger.kernel.org --- v2: * New patch. --- crypto/Makefile | 2 ++ crypto/algapi.c | 2 ++ crypto/api.c | 1 + crypto/crypto_engine.c | 2 +- crypto/drbg.c | 5 +++++ crypto/internal.h | 2 +- crypto/proc.c | 3 +++ crypto/scompress.c | 8 +++++--- include/crypto/internal/engine.h | 2 +- 9 files changed, 21 insertions(+), 6 deletions(-)