diff options
Diffstat (limited to 'net/bluetooth')
| -rw-r--r-- | net/bluetooth/af_bluetooth.c | 6 | ||||
| -rw-r--r-- | net/bluetooth/bnep/bnep.h | 1 | ||||
| -rw-r--r-- | net/bluetooth/bnep/core.c | 13 | ||||
| -rw-r--r-- | net/bluetooth/cmtp/capi.c | 3 | ||||
| -rw-r--r-- | net/bluetooth/cmtp/cmtp.h | 1 | ||||
| -rw-r--r-- | net/bluetooth/cmtp/core.c | 20 | ||||
| -rw-r--r-- | net/bluetooth/hci_core.c | 8 | ||||
| -rw-r--r-- | net/bluetooth/hci_event.c | 17 | ||||
| -rw-r--r-- | net/bluetooth/hidp/core.c | 19 | ||||
| -rw-r--r-- | net/bluetooth/l2cap_core.c | 6 | ||||
| -rw-r--r-- | net/bluetooth/l2cap_sock.c | 34 | ||||
| -rw-r--r-- | net/bluetooth/rfcomm/core.c | 17 | ||||
| -rw-r--r-- | net/bluetooth/rfcomm/sock.c | 31 | ||||
| -rw-r--r-- | net/bluetooth/sco.c | 33 | 
14 files changed, 113 insertions, 96 deletions
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 8add9b49991..117e0d16178 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -494,9 +494,8 @@ int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo)  	BT_DBG("sk %p", sk);  	add_wait_queue(sk_sleep(sk), &wait); +	set_current_state(TASK_INTERRUPTIBLE);  	while (sk->sk_state != state) { -		set_current_state(TASK_INTERRUPTIBLE); -  		if (!timeo) {  			err = -EINPROGRESS;  			break; @@ -510,12 +509,13 @@ int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo)  		release_sock(sk);  		timeo = schedule_timeout(timeo);  		lock_sock(sk); +		set_current_state(TASK_INTERRUPTIBLE);  		err = sock_error(sk);  		if (err)  			break;  	} -	set_current_state(TASK_RUNNING); +	__set_current_state(TASK_RUNNING);  	remove_wait_queue(sk_sleep(sk), &wait);  	return err;  } diff --git a/net/bluetooth/bnep/bnep.h b/net/bluetooth/bnep/bnep.h index 8e6c06158f8..e7ee5314f39 100644 --- a/net/bluetooth/bnep/bnep.h +++ b/net/bluetooth/bnep/bnep.h @@ -155,6 +155,7 @@ struct bnep_session {  	unsigned int  role;  	unsigned long state;  	unsigned long flags; +	atomic_t      terminate;  	struct task_struct *task;  	struct ethhdr eh; diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c index ca39fcf010c..d9edfe8bf9d 100644 --- a/net/bluetooth/bnep/core.c +++ b/net/bluetooth/bnep/core.c @@ -484,9 +484,11 @@ static int bnep_session(void *arg)  	init_waitqueue_entry(&wait, current);  	add_wait_queue(sk_sleep(sk), &wait); -	while (!kthread_should_stop()) { +	while (1) {  		set_current_state(TASK_INTERRUPTIBLE); +		if (atomic_read(&s->terminate)) +			break;  		/* RX */  		while ((skb = skb_dequeue(&sk->sk_receive_queue))) {  			skb_orphan(skb); @@ -504,7 +506,7 @@ static int bnep_session(void *arg)  		schedule();  	} -	set_current_state(TASK_RUNNING); +	__set_current_state(TASK_RUNNING);  	remove_wait_queue(sk_sleep(sk), &wait);  	/* Cleanup session */ @@ -640,9 +642,10 @@ int bnep_del_connection(struct bnep_conndel_req *req)  	down_read(&bnep_session_sem);  	s = __bnep_get_session(req->dst); -	if (s) -		kthread_stop(s->task); -	else +	if (s) { +		atomic_inc(&s->terminate); +		wake_up_process(s->task); +	} else  		err = -ENOENT;  	up_read(&bnep_session_sem); diff --git a/net/bluetooth/cmtp/capi.c b/net/bluetooth/cmtp/capi.c index 040f67b1297..50f0d135eb8 100644 --- a/net/bluetooth/cmtp/capi.c +++ b/net/bluetooth/cmtp/capi.c @@ -386,7 +386,8 @@ static void cmtp_reset_ctr(struct capi_ctr *ctrl)  	capi_ctr_down(ctrl); -	kthread_stop(session->task); +	atomic_inc(&session->terminate); +	wake_up_process(session->task);  }  static void cmtp_register_appl(struct capi_ctr *ctrl, __u16 appl, capi_register_params *rp) diff --git a/net/bluetooth/cmtp/cmtp.h b/net/bluetooth/cmtp/cmtp.h index db43b54ac9a..c32638dddbf 100644 --- a/net/bluetooth/cmtp/cmtp.h +++ b/net/bluetooth/cmtp/cmtp.h @@ -81,6 +81,7 @@ struct cmtp_session {  	char name[BTNAMSIZ]; +	atomic_t terminate;  	struct task_struct *task;  	wait_queue_head_t wait; diff --git a/net/bluetooth/cmtp/core.c b/net/bluetooth/cmtp/core.c index c5b11af908b..521baa4fe83 100644 --- a/net/bluetooth/cmtp/core.c +++ b/net/bluetooth/cmtp/core.c @@ -292,9 +292,11 @@ static int cmtp_session(void *arg)  	init_waitqueue_entry(&wait, current);  	add_wait_queue(sk_sleep(sk), &wait); -	while (!kthread_should_stop()) { +	while (1) {  		set_current_state(TASK_INTERRUPTIBLE); +		if (atomic_read(&session->terminate)) +			break;  		if (sk->sk_state != BT_CONNECTED)  			break; @@ -307,7 +309,7 @@ static int cmtp_session(void *arg)  		schedule();  	} -	set_current_state(TASK_RUNNING); +	__set_current_state(TASK_RUNNING);  	remove_wait_queue(sk_sleep(sk), &wait);  	down_write(&cmtp_session_sem); @@ -380,16 +382,17 @@ int cmtp_add_connection(struct cmtp_connadd_req *req, struct socket *sock)  	if (!(session->flags & (1 << CMTP_LOOPBACK))) {  		err = cmtp_attach_device(session); -		if (err < 0) -			goto detach; +		if (err < 0) { +			atomic_inc(&session->terminate); +			wake_up_process(session->task); +			up_write(&cmtp_session_sem); +			return err; +		}  	}  	up_write(&cmtp_session_sem);  	return 0; -detach: -	cmtp_detach_device(session); -  unlink:  	__cmtp_unlink_session(session); @@ -414,7 +417,8 @@ int cmtp_del_connection(struct cmtp_conndel_req *req)  		skb_queue_purge(&session->transmit);  		/* Stop session thread */ -		kthread_stop(session->task); +		atomic_inc(&session->terminate); +		wake_up_process(session->task);  	} else  		err = -ENOENT; diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index ec0bc3f60f2..56943add45c 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1209,7 +1209,6 @@ static void hci_cmd_timer(unsigned long arg)  	BT_ERR("%s command tx timeout", hdev->name);  	atomic_set(&hdev->cmd_cnt, 1); -	clear_bit(HCI_RESET, &hdev->flags);  	tasklet_schedule(&hdev->cmd_task);  } @@ -1327,7 +1326,7 @@ int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr)  	entry = kzalloc(sizeof(struct bdaddr_list), GFP_KERNEL);  	if (!entry) { -		return -ENOMEM; +		err = -ENOMEM;  		goto err;  	} @@ -2408,7 +2407,10 @@ static void hci_cmd_task(unsigned long arg)  		if (hdev->sent_cmd) {  			atomic_dec(&hdev->cmd_cnt);  			hci_send_frame(skb); -			mod_timer(&hdev->cmd_timer, +			if (test_bit(HCI_RESET, &hdev->flags)) +				del_timer(&hdev->cmd_timer); +			else +				mod_timer(&hdev->cmd_timer,  				  jiffies + msecs_to_jiffies(HCI_CMD_TIMEOUT));  		} else {  			skb_queue_head(&hdev->cmd_q, skb); diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index a40170e022e..7ef4eb4435f 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -58,8 +58,8 @@ static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb)  	if (status)  		return; -	if (test_bit(HCI_MGMT, &hdev->flags) && -				test_and_clear_bit(HCI_INQUIRY, &hdev->flags)) +	if (test_and_clear_bit(HCI_INQUIRY, &hdev->flags) && +			test_bit(HCI_MGMT, &hdev->flags))  		mgmt_discovering(hdev->id, 0);  	hci_req_complete(hdev, HCI_OP_INQUIRY_CANCEL, status); @@ -76,8 +76,8 @@ static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb)  	if (status)  		return; -	if (test_bit(HCI_MGMT, &hdev->flags) && -				test_and_clear_bit(HCI_INQUIRY, &hdev->flags)) +	if (test_and_clear_bit(HCI_INQUIRY, &hdev->flags) && +				test_bit(HCI_MGMT, &hdev->flags))  		mgmt_discovering(hdev->id, 0);  	hci_conn_check_pending(hdev); @@ -959,9 +959,8 @@ static inline void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)  		return;  	} -	if (test_bit(HCI_MGMT, &hdev->flags) && -					!test_and_set_bit(HCI_INQUIRY, -							&hdev->flags)) +	if (!test_and_set_bit(HCI_INQUIRY, &hdev->flags) && +				test_bit(HCI_MGMT, &hdev->flags))  		mgmt_discovering(hdev->id, 1);  } @@ -1340,8 +1339,8 @@ static inline void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff  	BT_DBG("%s status %d", hdev->name, status); -	if (test_bit(HCI_MGMT, &hdev->flags) && -				test_and_clear_bit(HCI_INQUIRY, &hdev->flags)) +	if (test_and_clear_bit(HCI_INQUIRY, &hdev->flags) && +				test_bit(HCI_MGMT, &hdev->flags))  		mgmt_discovering(hdev->id, 0);  	hci_req_complete(hdev, HCI_OP_INQUIRY, status); diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index 43b4c2deb7c..fb68f344c34 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c @@ -764,6 +764,7 @@ static int hidp_session(void *arg)  	up_write(&hidp_session_sem); +	kfree(session->rd_data);  	kfree(session);  	return 0;  } @@ -841,7 +842,8 @@ static int hidp_setup_input(struct hidp_session *session,  	err = input_register_device(input);  	if (err < 0) { -		hci_conn_put_device(session->conn); +		input_free_device(input); +		session->input = NULL;  		return err;  	} @@ -1044,8 +1046,12 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,  	}  	err = hid_add_device(session->hid); -	if (err < 0) -		goto err_add_device; +	if (err < 0) { +		atomic_inc(&session->terminate); +		wake_up_process(session->task); +		up_write(&hidp_session_sem); +		return err; +	}  	if (session->input) {  		hidp_send_ctrl_message(session, @@ -1059,12 +1065,6 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,  	up_write(&hidp_session_sem);  	return 0; -err_add_device: -	hid_destroy_device(session->hid); -	session->hid = NULL; -	atomic_inc(&session->terminate); -	wake_up_process(session->task); -  unlink:  	hidp_del_timer(session); @@ -1090,7 +1090,6 @@ purge:  failed:  	up_write(&hidp_session_sem); -	input_free_device(session->input);  	kfree(session);  	return err;  } diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 3204ba8a701..b3bdb482bbe 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -1159,9 +1159,8 @@ int __l2cap_wait_ack(struct sock *sk)  	int timeo = HZ/5;  	add_wait_queue(sk_sleep(sk), &wait); -	while ((chan->unacked_frames > 0 && chan->conn)) { -		set_current_state(TASK_INTERRUPTIBLE); - +	set_current_state(TASK_INTERRUPTIBLE); +	while (chan->unacked_frames > 0 && chan->conn) {  		if (!timeo)  			timeo = HZ/5; @@ -1173,6 +1172,7 @@ int __l2cap_wait_ack(struct sock *sk)  		release_sock(sk);  		timeo = schedule_timeout(timeo);  		lock_sock(sk); +		set_current_state(TASK_INTERRUPTIBLE);  		err = sock_error(sk);  		if (err) diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 5c36b3e8739..e8292369cdc 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -26,6 +26,8 @@  /* Bluetooth L2CAP sockets. */ +#include <linux/security.h> +  #include <net/bluetooth/bluetooth.h>  #include <net/bluetooth/hci_core.h>  #include <net/bluetooth/l2cap.h> @@ -235,30 +237,26 @@ static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int fl  	lock_sock_nested(sk, SINGLE_DEPTH_NESTING); -	if (sk->sk_state != BT_LISTEN) { -		err = -EBADFD; -		goto done; -	} -  	timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);  	BT_DBG("sk %p timeo %ld", sk, timeo);  	/* Wait for an incoming connection. (wake-one). */  	add_wait_queue_exclusive(sk_sleep(sk), &wait); -	while (!(nsk = bt_accept_dequeue(sk, newsock))) { +	while (1) {  		set_current_state(TASK_INTERRUPTIBLE); -		if (!timeo) { -			err = -EAGAIN; + +		if (sk->sk_state != BT_LISTEN) { +			err = -EBADFD;  			break;  		} -		release_sock(sk); -		timeo = schedule_timeout(timeo); -		lock_sock_nested(sk, SINGLE_DEPTH_NESTING); +		nsk = bt_accept_dequeue(sk, newsock); +		if (nsk) +			break; -		if (sk->sk_state != BT_LISTEN) { -			err = -EBADFD; +		if (!timeo) { +			err = -EAGAIN;  			break;  		} @@ -266,8 +264,12 @@ static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int fl  			err = sock_intr_errno(timeo);  			break;  		} + +		release_sock(sk); +		timeo = schedule_timeout(timeo); +		lock_sock_nested(sk, SINGLE_DEPTH_NESTING);  	} -	set_current_state(TASK_RUNNING); +	__set_current_state(TASK_RUNNING);  	remove_wait_queue(sk_sleep(sk), &wait);  	if (err) @@ -933,6 +935,8 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent)  		chan->force_reliable = pchan->force_reliable;  		chan->flushable = pchan->flushable;  		chan->force_active = pchan->force_active; + +		security_sk_clone(parent, sk);  	} else {  		switch (sk->sk_type) { @@ -993,7 +997,7 @@ static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int p  	INIT_LIST_HEAD(&bt_sk(sk)->accept_q);  	sk->sk_destruct = l2cap_sock_destruct; -	sk->sk_sndtimeo = msecs_to_jiffies(L2CAP_CONN_TIMEOUT); +	sk->sk_sndtimeo = L2CAP_CONN_TIMEOUT;  	sock_reset_flag(sk, SOCK_ZAPPED); diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 5759bb7054f..5ba3f6df665 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -62,7 +62,6 @@ static DEFINE_MUTEX(rfcomm_mutex);  #define rfcomm_lock()	mutex_lock(&rfcomm_mutex)  #define rfcomm_unlock()	mutex_unlock(&rfcomm_mutex) -static unsigned long rfcomm_event;  static LIST_HEAD(session_list); @@ -120,7 +119,6 @@ static inline void rfcomm_schedule(void)  {  	if (!rfcomm_thread)  		return; -	set_bit(RFCOMM_SCHED_WAKEUP, &rfcomm_event);  	wake_up_process(rfcomm_thread);  } @@ -2038,19 +2036,18 @@ static int rfcomm_run(void *unused)  	rfcomm_add_listener(BDADDR_ANY); -	while (!kthread_should_stop()) { +	while (1) {  		set_current_state(TASK_INTERRUPTIBLE); -		if (!test_bit(RFCOMM_SCHED_WAKEUP, &rfcomm_event)) { -			/* No pending events. Let's sleep. -			 * Incoming connections and data will wake us up. */ -			schedule(); -		} -		set_current_state(TASK_RUNNING); + +		if (kthread_should_stop()) +			break;  		/* Process stuff */ -		clear_bit(RFCOMM_SCHED_WAKEUP, &rfcomm_event);  		rfcomm_process_sessions(); + +		schedule();  	} +	__set_current_state(TASK_RUNNING);  	rfcomm_kill_listener(); diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 8f01e6b11a7..5417f612732 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -42,6 +42,7 @@  #include <linux/device.h>  #include <linux/debugfs.h>  #include <linux/seq_file.h> +#include <linux/security.h>  #include <net/sock.h>  #include <asm/system.h> @@ -264,6 +265,8 @@ static void rfcomm_sock_init(struct sock *sk, struct sock *parent)  		pi->sec_level = rfcomm_pi(parent)->sec_level;  		pi->role_switch = rfcomm_pi(parent)->role_switch; + +		security_sk_clone(parent, sk);  	} else {  		pi->dlc->defer_setup = 0; @@ -485,11 +488,6 @@ static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int f  	lock_sock(sk); -	if (sk->sk_state != BT_LISTEN) { -		err = -EBADFD; -		goto done; -	} -  	if (sk->sk_type != SOCK_STREAM) {  		err = -EINVAL;  		goto done; @@ -501,19 +499,20 @@ static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int f  	/* Wait for an incoming connection. (wake-one). */  	add_wait_queue_exclusive(sk_sleep(sk), &wait); -	while (!(nsk = bt_accept_dequeue(sk, newsock))) { +	while (1) {  		set_current_state(TASK_INTERRUPTIBLE); -		if (!timeo) { -			err = -EAGAIN; + +		if (sk->sk_state != BT_LISTEN) { +			err = -EBADFD;  			break;  		} -		release_sock(sk); -		timeo = schedule_timeout(timeo); -		lock_sock(sk); +		nsk = bt_accept_dequeue(sk, newsock); +		if (nsk) +			break; -		if (sk->sk_state != BT_LISTEN) { -			err = -EBADFD; +		if (!timeo) { +			err = -EAGAIN;  			break;  		} @@ -521,8 +520,12 @@ static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int f  			err = sock_intr_errno(timeo);  			break;  		} + +		release_sock(sk); +		timeo = schedule_timeout(timeo); +		lock_sock(sk);  	} -	set_current_state(TASK_RUNNING); +	__set_current_state(TASK_RUNNING);  	remove_wait_queue(sk_sleep(sk), &wait);  	if (err) diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 4c3621b5e0a..a324b009e34 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -41,6 +41,7 @@  #include <linux/debugfs.h>  #include <linux/seq_file.h>  #include <linux/list.h> +#include <linux/security.h>  #include <net/sock.h>  #include <asm/system.h> @@ -403,8 +404,10 @@ static void sco_sock_init(struct sock *sk, struct sock *parent)  {  	BT_DBG("sk %p", sk); -	if (parent) +	if (parent) {  		sk->sk_type = parent->sk_type; +		security_sk_clone(parent, sk); +	}  }  static struct proto sco_proto = { @@ -564,30 +567,26 @@ static int sco_sock_accept(struct socket *sock, struct socket *newsock, int flag  	lock_sock(sk); -	if (sk->sk_state != BT_LISTEN) { -		err = -EBADFD; -		goto done; -	} -  	timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);  	BT_DBG("sk %p timeo %ld", sk, timeo);  	/* Wait for an incoming connection. (wake-one). */  	add_wait_queue_exclusive(sk_sleep(sk), &wait); -	while (!(ch = bt_accept_dequeue(sk, newsock))) { +	while (1) {  		set_current_state(TASK_INTERRUPTIBLE); -		if (!timeo) { -			err = -EAGAIN; + +		if (sk->sk_state != BT_LISTEN) { +			err = -EBADFD;  			break;  		} -		release_sock(sk); -		timeo = schedule_timeout(timeo); -		lock_sock(sk); +		ch = bt_accept_dequeue(sk, newsock); +		if (ch) +			break; -		if (sk->sk_state != BT_LISTEN) { -			err = -EBADFD; +		if (!timeo) { +			err = -EAGAIN;  			break;  		} @@ -595,8 +594,12 @@ static int sco_sock_accept(struct socket *sock, struct socket *newsock, int flag  			err = sock_intr_errno(timeo);  			break;  		} + +		release_sock(sk); +		timeo = schedule_timeout(timeo); +		lock_sock(sk);  	} -	set_current_state(TASK_RUNNING); +	__set_current_state(TASK_RUNNING);  	remove_wait_queue(sk_sleep(sk), &wait);  	if (err)  |