Skip to content

Commit df9d4a1

Browse files
chelsiocryptodavem330
authored andcommitted
net/tls: sleeping function from invalid context
HW unhash within mutex for registered tls devices cause sleep when called from tcp_set_state for TCP_CLOSE. Release lock and re-acquire after function call with ref count incr/dec. defined kref and fp release for tls_device to ensure device is not released outside lock. BUG: sleeping function called from invalid context at kernel/locking/mutex.c:748 in_atomic(): 1, irqs_disabled(): 0, pid: 0, name: swapper/7 INFO: lockdep is turned off. CPU: 7 PID: 0 Comm: swapper/7 Tainted: G W O Call Trace: <IRQ> dump_stack+0x5e/0x8b ___might_sleep+0x222/0x260 __mutex_lock+0x5c/0xa50 ? vprintk_emit+0x1f3/0x440 ? kmem_cache_free+0x22d/0x2a0 ? tls_hw_unhash+0x2f/0x80 ? printk+0x52/0x6e ? tls_hw_unhash+0x2f/0x80 tls_hw_unhash+0x2f/0x80 tcp_set_state+0x5f/0x180 tcp_done+0x2e/0xe0 tcp_rcv_state_process+0x92c/0xdd3 ? lock_acquire+0xf5/0x1f0 ? tcp_v4_rcv+0xa7c/0xbe0 ? tcp_v4_do_rcv+0x70/0x1e0 Signed-off-by: Atul Gupta <atul.gupta@chelsio.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 6c0563e commit df9d4a1

File tree

3 files changed

+61
-36
lines changed

3 files changed

+61
-36
lines changed

drivers/crypto/chelsio/chtls/chtls_main.c

+32-23
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,30 @@ static void chtls_destroy_hash(struct tls_device *dev, struct sock *sk)
149149
chtls_stop_listen(sk);
150150
}
151151

152+
static void chtls_free_uld(struct chtls_dev *cdev)
153+
{
154+
int i;
155+
156+
tls_unregister_device(&cdev->tlsdev);
157+
kvfree(cdev->kmap.addr);
158+
idr_destroy(&cdev->hwtid_idr);
159+
for (i = 0; i < (1 << RSPQ_HASH_BITS); i++)
160+
kfree_skb(cdev->rspq_skb_cache[i]);
161+
kfree(cdev->lldi);
162+
kfree_skb(cdev->askb);
163+
kfree(cdev);
164+
}
165+
166+
static inline void chtls_dev_release(struct kref *kref)
167+
{
168+
struct chtls_dev *cdev;
169+
struct tls_device *dev;
170+
171+
dev = container_of(kref, struct tls_device, kref);
172+
cdev = to_chtls_dev(dev);
173+
chtls_free_uld(cdev);
174+
}
175+
152176
static void chtls_register_dev(struct chtls_dev *cdev)
153177
{
154178
struct tls_device *tlsdev = &cdev->tlsdev;
@@ -159,15 +183,12 @@ static void chtls_register_dev(struct chtls_dev *cdev)
159183
tlsdev->feature = chtls_inline_feature;
160184
tlsdev->hash = chtls_create_hash;
161185
tlsdev->unhash = chtls_destroy_hash;
162-
tls_register_device(&cdev->tlsdev);
186+
tlsdev->release = chtls_dev_release;
187+
kref_init(&tlsdev->kref);
188+
tls_register_device(tlsdev);
163189
cdev->cdev_state = CHTLS_CDEV_STATE_UP;
164190
}
165191

166-
static void chtls_unregister_dev(struct chtls_dev *cdev)
167-
{
168-
tls_unregister_device(&cdev->tlsdev);
169-
}
170-
171192
static void process_deferq(struct work_struct *task_param)
172193
{
173194
struct chtls_dev *cdev = container_of(task_param,
@@ -262,28 +283,16 @@ static void *chtls_uld_add(const struct cxgb4_lld_info *info)
262283
return NULL;
263284
}
264285

265-
static void chtls_free_uld(struct chtls_dev *cdev)
266-
{
267-
int i;
268-
269-
chtls_unregister_dev(cdev);
270-
kvfree(cdev->kmap.addr);
271-
idr_destroy(&cdev->hwtid_idr);
272-
for (i = 0; i < (1 << RSPQ_HASH_BITS); i++)
273-
kfree_skb(cdev->rspq_skb_cache[i]);
274-
kfree(cdev->lldi);
275-
kfree_skb(cdev->askb);
276-
kfree(cdev);
277-
}
278-
279286
static void chtls_free_all_uld(void)
280287
{
281288
struct chtls_dev *cdev, *tmp;
282289

283290
mutex_lock(&cdev_mutex);
284291
list_for_each_entry_safe(cdev, tmp, &cdev_list, list) {
285-
if (cdev->cdev_state == CHTLS_CDEV_STATE_UP)
286-
chtls_free_uld(cdev);
292+
if (cdev->cdev_state == CHTLS_CDEV_STATE_UP) {
293+
list_del(&cdev->list);
294+
kref_put(&cdev->tlsdev.kref, cdev->tlsdev.release);
295+
}
287296
}
288297
mutex_unlock(&cdev_mutex);
289298
}
@@ -304,7 +313,7 @@ static int chtls_uld_state_change(void *handle, enum cxgb4_state new_state)
304313
mutex_lock(&cdev_mutex);
305314
list_del(&cdev->list);
306315
mutex_unlock(&cdev_mutex);
307-
chtls_free_uld(cdev);
316+
kref_put(&cdev->tlsdev.kref, cdev->tlsdev.release);
308317
break;
309318
default:
310319
break;

include/net/tls.h

+6
Original file line numberDiff line numberDiff line change
@@ -76,13 +76,19 @@
7676
*
7777
* void (*unhash)(struct tls_device *device, struct sock *sk);
7878
* This function cleans listen state set by Inline TLS driver
79+
*
80+
* void (*release)(struct kref *kref);
81+
* Release the registered device and allocated resources
82+
* @kref: Number of reference to tls_device
7983
*/
8084
struct tls_device {
8185
char name[TLS_DEVICE_NAME_MAX];
8286
struct list_head dev_list;
8387
int (*feature)(struct tls_device *device);
8488
int (*hash)(struct tls_device *device, struct sock *sk);
8589
void (*unhash)(struct tls_device *device, struct sock *sk);
90+
void (*release)(struct kref *kref);
91+
struct kref kref;
8692
};
8793

8894
enum {

net/tls/tls_main.c

+23-13
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ enum {
5656
static struct proto *saved_tcpv6_prot;
5757
static DEFINE_MUTEX(tcpv6_prot_mutex);
5858
static LIST_HEAD(device_list);
59-
static DEFINE_MUTEX(device_mutex);
59+
static DEFINE_SPINLOCK(device_spinlock);
6060
static struct proto tls_prots[TLS_NUM_PROTS][TLS_NUM_CONFIG][TLS_NUM_CONFIG];
6161
static struct proto_ops tls_sw_proto_ops;
6262

@@ -555,7 +555,7 @@ static int tls_hw_prot(struct sock *sk)
555555
struct tls_device *dev;
556556
int rc = 0;
557557

558-
mutex_lock(&device_mutex);
558+
spin_lock_bh(&device_spinlock);
559559
list_for_each_entry(dev, &device_list, dev_list) {
560560
if (dev->feature && dev->feature(dev)) {
561561
ctx = create_ctx(sk);
@@ -573,7 +573,7 @@ static int tls_hw_prot(struct sock *sk)
573573
}
574574
}
575575
out:
576-
mutex_unlock(&device_mutex);
576+
spin_unlock_bh(&device_spinlock);
577577
return rc;
578578
}
579579

@@ -582,12 +582,17 @@ static void tls_hw_unhash(struct sock *sk)
582582
struct tls_context *ctx = tls_get_ctx(sk);
583583
struct tls_device *dev;
584584

585-
mutex_lock(&device_mutex);
585+
spin_lock_bh(&device_spinlock);
586586
list_for_each_entry(dev, &device_list, dev_list) {
587-
if (dev->unhash)
587+
if (dev->unhash) {
588+
kref_get(&dev->kref);
589+
spin_unlock_bh(&device_spinlock);
588590
dev->unhash(dev, sk);
591+
kref_put(&dev->kref, dev->release);
592+
spin_lock_bh(&device_spinlock);
593+
}
589594
}
590-
mutex_unlock(&device_mutex);
595+
spin_unlock_bh(&device_spinlock);
591596
ctx->unhash(sk);
592597
}
593598

@@ -598,12 +603,17 @@ static int tls_hw_hash(struct sock *sk)
598603
int err;
599604

600605
err = ctx->hash(sk);
601-
mutex_lock(&device_mutex);
606+
spin_lock_bh(&device_spinlock);
602607
list_for_each_entry(dev, &device_list, dev_list) {
603-
if (dev->hash)
608+
if (dev->hash) {
609+
kref_get(&dev->kref);
610+
spin_unlock_bh(&device_spinlock);
604611
err |= dev->hash(dev, sk);
612+
kref_put(&dev->kref, dev->release);
613+
spin_lock_bh(&device_spinlock);
614+
}
605615
}
606-
mutex_unlock(&device_mutex);
616+
spin_unlock_bh(&device_spinlock);
607617

608618
if (err)
609619
tls_hw_unhash(sk);
@@ -699,17 +709,17 @@ static int tls_init(struct sock *sk)
699709

700710
void tls_register_device(struct tls_device *device)
701711
{
702-
mutex_lock(&device_mutex);
712+
spin_lock_bh(&device_spinlock);
703713
list_add_tail(&device->dev_list, &device_list);
704-
mutex_unlock(&device_mutex);
714+
spin_unlock_bh(&device_spinlock);
705715
}
706716
EXPORT_SYMBOL(tls_register_device);
707717

708718
void tls_unregister_device(struct tls_device *device)
709719
{
710-
mutex_lock(&device_mutex);
720+
spin_lock_bh(&device_spinlock);
711721
list_del(&device->dev_list);
712-
mutex_unlock(&device_mutex);
722+
spin_unlock_bh(&device_spinlock);
713723
}
714724
EXPORT_SYMBOL(tls_unregister_device);
715725

0 commit comments

Comments
 (0)