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

Commit 74da626a authored by Marcel Holtmann's avatar Marcel Holtmann Committed by David S. Miller
Browse files

[Bluetooth] Add locking for bt_proto array manipulation



The bt_proto array needs to be protected by some kind of locking to
prevent a race condition between bt_sock_create and bt_sock_register.

And in addition all calls to sk_alloc need to be made GFP_ATOMIC now.

Signed-off-by: default avatarMasatake YAMATO <jet@gyve.org>
Signed-off-by: default avatarFrederik Deweerdt <frederik.deweerdt@gmail.com>
Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
parent cb19d9ea
Loading
Loading
Loading
Loading
+29 −7
Original line number Diff line number Diff line
@@ -53,36 +53,51 @@
/* Bluetooth sockets */
#define BT_MAX_PROTO	8
static struct net_proto_family *bt_proto[BT_MAX_PROTO];
static DEFINE_RWLOCK(bt_proto_lock);

int bt_sock_register(int proto, struct net_proto_family *ops)
{
	int err = 0;

	if (proto < 0 || proto >= BT_MAX_PROTO)
		return -EINVAL;

	if (bt_proto[proto])
		return -EEXIST;
	write_lock(&bt_proto_lock);

	if (bt_proto[proto])
		err = -EEXIST;
	else
		bt_proto[proto] = ops;
	return 0;

	write_unlock(&bt_proto_lock);

	return err;
}
EXPORT_SYMBOL(bt_sock_register);

int bt_sock_unregister(int proto)
{
	int err = 0;

	if (proto < 0 || proto >= BT_MAX_PROTO)
		return -EINVAL;

	if (!bt_proto[proto])
		return -ENOENT;
	write_lock(&bt_proto_lock);

	if (!bt_proto[proto])
		err = -ENOENT;
	else
		bt_proto[proto] = NULL;
	return 0;

	write_unlock(&bt_proto_lock);

	return err;
}
EXPORT_SYMBOL(bt_sock_unregister);

static int bt_sock_create(struct socket *sock, int proto)
{
	int err = 0;
	int err;

	if (proto < 0 || proto >= BT_MAX_PROTO)
		return -EINVAL;
@@ -92,11 +107,18 @@ static int bt_sock_create(struct socket *sock, int proto)
		request_module("bt-proto-%d", proto);
	}
#endif

	err = -EPROTONOSUPPORT;

	read_lock(&bt_proto_lock);

	if (bt_proto[proto] && try_module_get(bt_proto[proto]->owner)) {
		err = bt_proto[proto]->create(sock, proto);
		module_put(bt_proto[proto]->owner);
	}

	read_unlock(&bt_proto_lock);

	return err; 
}

+1 −1
Original line number Diff line number Diff line
@@ -214,7 +214,7 @@ static int bnep_sock_create(struct socket *sock, int protocol)
	if (sock->type != SOCK_RAW)
		return -ESOCKTNOSUPPORT;

	sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, &bnep_proto, 1);
	sk = sk_alloc(PF_BLUETOOTH, GFP_ATOMIC, &bnep_proto, 1);
	if (!sk)
		return -ENOMEM;

+1 −1
Original line number Diff line number Diff line
@@ -205,7 +205,7 @@ static int cmtp_sock_create(struct socket *sock, int protocol)
	if (sock->type != SOCK_RAW)
		return -ESOCKTNOSUPPORT;

	sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, &cmtp_proto, 1);
	sk = sk_alloc(PF_BLUETOOTH, GFP_ATOMIC, &cmtp_proto, 1);
	if (!sk)
		return -ENOMEM;

+1 −1
Original line number Diff line number Diff line
@@ -618,7 +618,7 @@ static int hci_sock_create(struct socket *sock, int protocol)

	sock->ops = &hci_sock_ops;

	sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, &hci_sk_proto, 1);
	sk = sk_alloc(PF_BLUETOOTH, GFP_ATOMIC, &hci_sk_proto, 1);
	if (!sk)
		return -ENOMEM;

+1 −1
Original line number Diff line number Diff line
@@ -256,7 +256,7 @@ static int hidp_sock_create(struct socket *sock, int protocol)
	if (sock->type != SOCK_RAW)
		return -ESOCKTNOSUPPORT;

	sk = sk_alloc(PF_BLUETOOTH, GFP_KERNEL, &hidp_proto, 1);
	sk = sk_alloc(PF_BLUETOOTH, GFP_ATOMIC, &hidp_proto, 1);
	if (!sk)
		return -ENOMEM;

Loading