Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 14ebaf81 authored by David S. Miller's avatar David S. Miller
Browse files

x25: Fix sleep from timer on socket destroy.



If socket destuction gets delayed to a timer, we try to
lock_sock() from that timer which won't work.

Use bh_lock_sock() in that case.

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Tested-by: default avatarIngo Molnar <mingo@elte.hu>
parent a1870b9c
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -187,7 +187,7 @@ extern int x25_addr_ntoa(unsigned char *, struct x25_address *,
extern int  x25_addr_aton(unsigned char *, struct x25_address *,
			  struct x25_address *);
extern struct sock *x25_find_socket(unsigned int, struct x25_neigh *);
extern void x25_destroy_socket(struct sock *);
extern void x25_destroy_socket_from_timer(struct sock *);
extern int  x25_rx_call_request(struct sk_buff *, struct x25_neigh *, unsigned int);
extern void x25_kill_by_neigh(struct x25_neigh *);

+18 −5
Original line number Diff line number Diff line
@@ -332,14 +332,14 @@ static unsigned int x25_new_lci(struct x25_neigh *nb)
/*
 *	Deferred destroy.
 */
void x25_destroy_socket(struct sock *);
static void __x25_destroy_socket(struct sock *);

/*
 *	handler for deferred kills.
 */
static void x25_destroy_timer(unsigned long data)
{
	x25_destroy_socket((struct sock *)data);
	x25_destroy_socket_from_timer((struct sock *)data);
}

/*
@@ -349,12 +349,10 @@ static void x25_destroy_timer(unsigned long data)
 *	will touch it and we are (fairly 8-) ) safe.
 *	Not static as it's used by the timer
 */
void x25_destroy_socket(struct sock *sk)
static void __x25_destroy_socket(struct sock *sk)
{
	struct sk_buff *skb;

	sock_hold(sk);
	lock_sock(sk);
	x25_stop_heartbeat(sk);
	x25_stop_timer(sk);

@@ -385,7 +383,22 @@ void x25_destroy_socket(struct sock *sk)
		/* drop last reference so sock_put will free */
		__sock_put(sk);
	}
}

void x25_destroy_socket_from_timer(struct sock *sk)
{
	sock_hold(sk);
	bh_lock_sock(sk);
	__x25_destroy_socket(sk);
	bh_unlock_sock(sk);
	sock_put(sk);
}

static void x25_destroy_socket(struct sock *sk)
{
	sock_hold(sk);
	lock_sock(sk);
	__x25_destroy_socket(sk);
	release_sock(sk);
	sock_put(sk);
}
+1 −1
Original line number Diff line number Diff line
@@ -113,7 +113,7 @@ static void x25_heartbeat_expiry(unsigned long param)
			    (sk->sk_state == TCP_LISTEN &&
			     sock_flag(sk, SOCK_DEAD))) {
				bh_unlock_sock(sk);
				x25_destroy_socket(sk);
				x25_destroy_socket_from_timer(sk);
				return;
			}
			break;