[PATCH 3.16 35/87] s390/crypto: fix possible sleep during spinlock aquired

From: Ben Hutchings
Date: Wed Oct 02 2019 - 15:12:58 EST


3.16.75-rc1 review patch. If anyone has any objections, please let me know.

------------------

From: Harald Freudenberger <freude@xxxxxxxxxxxxx>

commit 1c2c7029c008922d4d48902cc386250502e73d51 upstream.

This patch fixes a complain about possible sleep during
spinlock aquired
"BUG: sleeping function called from invalid context at
include/crypto/algapi.h:426"
for the ctr(aes) and ctr(des) s390 specific ciphers.

Instead of using a spinlock this patch introduces a mutex
which is save to be held in sleeping context. Please note
a deadlock is not possible as mutex_trylock() is used.

Signed-off-by: Harald Freudenberger <freude@xxxxxxxxxxxxx>
Reported-by: Julian Wiedmann <jwi@xxxxxxxxxxxxx>
Signed-off-by: Heiko Carstens <heiko.carstens@xxxxxxxxxx>
[bwh: Backported to 3.16:
- Replace spin_unlock() on all exit paths
- Adjust context]
Signed-off-by: Ben Hutchings <ben@xxxxxxxxxxxxxxx>
---
--- a/arch/s390/crypto/aes_s390.c
+++ b/arch/s390/crypto/aes_s390.c
@@ -25,7 +25,7 @@
#include <linux/err.h>
#include <linux/module.h>
#include <linux/init.h>
-#include <linux/spinlock.h>
+#include <linux/mutex.h>
#include "crypt_s390.h"

#define AES_KEYLEN_128 1
@@ -33,7 +33,7 @@
#define AES_KEYLEN_256 4

static u8 *ctrblk;
-static DEFINE_SPINLOCK(ctrblk_lock);
+static DEFINE_MUTEX(ctrblk_lock);
static char keylen_flag;

struct s390_aes_ctx {
@@ -785,7 +785,7 @@ static int ctr_aes_crypt(struct blkciphe
if (!walk->nbytes)
return ret;

- if (spin_trylock(&ctrblk_lock))
+ if (mutex_trylock(&ctrblk_lock))
ctrptr = ctrblk;

memcpy(ctrptr, walk->iv, AES_BLOCK_SIZE);
@@ -801,7 +801,7 @@ static int ctr_aes_crypt(struct blkciphe
n, ctrptr);
if (ret < 0 || ret != n) {
if (ctrptr == ctrblk)
- spin_unlock(&ctrblk_lock);
+ mutex_unlock(&ctrblk_lock);
return -EIO;
}
if (n > AES_BLOCK_SIZE)
@@ -819,7 +819,7 @@ static int ctr_aes_crypt(struct blkciphe
memcpy(ctrbuf, ctrptr, AES_BLOCK_SIZE);
else
memcpy(walk->iv, ctrptr, AES_BLOCK_SIZE);
- spin_unlock(&ctrblk_lock);
+ mutex_unlock(&ctrblk_lock);
} else {
if (!nbytes)
memcpy(walk->iv, ctrptr, AES_BLOCK_SIZE);
--- a/arch/s390/crypto/des_s390.c
+++ b/arch/s390/crypto/des_s390.c
@@ -17,6 +17,7 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/crypto.h>
+#include <linux/mutex.h>
#include <crypto/algapi.h>
#include <crypto/des.h>

@@ -25,7 +26,7 @@
#define DES3_KEY_SIZE (3 * DES_KEY_SIZE)

static u8 *ctrblk;
-static DEFINE_SPINLOCK(ctrblk_lock);
+static DEFINE_MUTEX(ctrblk_lock);

struct s390_des_ctx {
u8 iv[DES_BLOCK_SIZE];
@@ -394,7 +395,7 @@ static int ctr_desall_crypt(struct blkci
if (!walk->nbytes)
return ret;

- if (spin_trylock(&ctrblk_lock))
+ if (mutex_trylock(&ctrblk_lock))
ctrptr = ctrblk;

memcpy(ctrptr, walk->iv, DES_BLOCK_SIZE);
@@ -410,7 +411,7 @@ static int ctr_desall_crypt(struct blkci
n, ctrptr);
if (ret < 0 || ret != n) {
if (ctrptr == ctrblk)
- spin_unlock(&ctrblk_lock);
+ mutex_unlock(&ctrblk_lock);
return -EIO;
}
if (n > DES_BLOCK_SIZE)
@@ -428,7 +429,7 @@ static int ctr_desall_crypt(struct blkci
memcpy(ctrbuf, ctrptr, DES_BLOCK_SIZE);
else
memcpy(walk->iv, ctrptr, DES_BLOCK_SIZE);
- spin_unlock(&ctrblk_lock);
+ mutex_unlock(&ctrblk_lock);
} else {
if (!nbytes)
memcpy(walk->iv, ctrptr, DES_BLOCK_SIZE);