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

Commit 91cd99f6 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6:
  ipv6: Fix OOPS in ip6_dst_lookup_tail().
  ipsec: Restore larval states and socket policies in dump
  [Bluetooth] Reject L2CAP connections on an insecure ACL link
  [Bluetooth] Enforce correct authentication requirements
  [Bluetooth] Fix reference counting during ACL config stage
parents 5b0dac74 e550dfb0
Loading
Loading
Loading
Loading
+2 −1
Original line number Original line Diff line number Diff line
@@ -325,7 +325,8 @@ int hci_conn_del(struct hci_conn *conn);
void hci_conn_hash_flush(struct hci_dev *hdev);
void hci_conn_hash_flush(struct hci_dev *hdev);
void hci_conn_check_pending(struct hci_dev *hdev);
void hci_conn_check_pending(struct hci_dev *hdev);


struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *src);
struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 auth_type);
int hci_conn_check_link_mode(struct hci_conn *conn);
int hci_conn_auth(struct hci_conn *conn);
int hci_conn_auth(struct hci_conn *conn);
int hci_conn_encrypt(struct hci_conn *conn);
int hci_conn_encrypt(struct hci_conn *conn);
int hci_conn_change_link_key(struct hci_conn *conn);
int hci_conn_change_link_key(struct hci_conn *conn);
+1 −1
Original line number Original line Diff line number Diff line
@@ -49,7 +49,7 @@
#define BT_DBG(D...)
#define BT_DBG(D...)
#endif
#endif


#define VERSION "2.12"
#define VERSION "2.13"


/* Bluetooth sockets */
/* Bluetooth sockets */
#define BT_MAX_PROTO	8
#define BT_MAX_PROTO	8
+18 −3
Original line number Original line Diff line number Diff line
@@ -330,7 +330,7 @@ EXPORT_SYMBOL(hci_get_route);


/* Create SCO or ACL connection.
/* Create SCO or ACL connection.
 * Device _must_ be locked */
 * Device _must_ be locked */
struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst)
struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 auth_type)
{
{
	struct hci_conn *acl;
	struct hci_conn *acl;
	struct hci_conn *sco;
	struct hci_conn *sco;
@@ -344,8 +344,10 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst)


	hci_conn_hold(acl);
	hci_conn_hold(acl);


	if (acl->state == BT_OPEN || acl->state == BT_CLOSED)
	if (acl->state == BT_OPEN || acl->state == BT_CLOSED) {
		acl->auth_type = auth_type;
		hci_acl_connect(acl);
		hci_acl_connect(acl);
	}


	if (type == ACL_LINK)
	if (type == ACL_LINK)
		return acl;
		return acl;
@@ -374,6 +376,19 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst)
}
}
EXPORT_SYMBOL(hci_connect);
EXPORT_SYMBOL(hci_connect);


/* Check link security requirement */
int hci_conn_check_link_mode(struct hci_conn *conn)
{
	BT_DBG("conn %p", conn);

	if (conn->ssp_mode > 0 && conn->hdev->ssp_mode > 0 &&
					!(conn->link_mode & HCI_LM_ENCRYPT))
		return 0;

	return 1;
}
EXPORT_SYMBOL(hci_conn_check_link_mode);

/* Authenticate remote device */
/* Authenticate remote device */
int hci_conn_auth(struct hci_conn *conn)
int hci_conn_auth(struct hci_conn *conn)
{
{
@@ -381,7 +396,7 @@ int hci_conn_auth(struct hci_conn *conn)


	if (conn->ssp_mode > 0 && conn->hdev->ssp_mode > 0) {
	if (conn->ssp_mode > 0 && conn->hdev->ssp_mode > 0) {
		if (!(conn->auth_type & 0x01)) {
		if (!(conn->auth_type & 0x01)) {
			conn->auth_type = HCI_AT_GENERAL_BONDING_MITM;
			conn->auth_type |= 0x01;
			conn->link_mode &= ~HCI_LM_AUTH;
			conn->link_mode &= ~HCI_LM_AUTH;
		}
		}
	}
	}
+4 −7
Original line number Original line Diff line number Diff line
@@ -1605,14 +1605,11 @@ static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_b


		if (conn->state == BT_CONFIG) {
		if (conn->state == BT_CONFIG) {
			if (!ev->status && hdev->ssp_mode > 0 &&
			if (!ev->status && hdev->ssp_mode > 0 &&
							conn->ssp_mode > 0) {
					conn->ssp_mode > 0 && conn->out) {
				if (conn->out) {
				struct hci_cp_auth_requested cp;
				struct hci_cp_auth_requested cp;
				cp.handle = ev->handle;
				cp.handle = ev->handle;
					hci_send_cmd(hdev,
				hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED,
						HCI_OP_AUTH_REQUESTED,
							sizeof(cp), &cp);
							sizeof(cp), &cp);
				}
			} else {
			} else {
				conn->state = BT_CONNECTED;
				conn->state = BT_CONNECTED;
				hci_proto_connect_cfm(conn, ev->status);
				hci_proto_connect_cfm(conn, ev->status);
+28 −6
Original line number Original line Diff line number Diff line
@@ -55,7 +55,7 @@
#define BT_DBG(D...)
#define BT_DBG(D...)
#endif
#endif


#define VERSION "2.10"
#define VERSION "2.11"


static u32 l2cap_feat_mask = 0x0000;
static u32 l2cap_feat_mask = 0x0000;


@@ -778,6 +778,7 @@ static int l2cap_do_connect(struct sock *sk)
	struct l2cap_conn *conn;
	struct l2cap_conn *conn;
	struct hci_conn *hcon;
	struct hci_conn *hcon;
	struct hci_dev *hdev;
	struct hci_dev *hdev;
	__u8 auth_type;
	int err = 0;
	int err = 0;


	BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst), l2cap_pi(sk)->psm);
	BT_DBG("%s -> %s psm 0x%2.2x", batostr(src), batostr(dst), l2cap_pi(sk)->psm);
@@ -789,7 +790,21 @@ static int l2cap_do_connect(struct sock *sk)


	err = -ENOMEM;
	err = -ENOMEM;


	hcon = hci_connect(hdev, ACL_LINK, dst);
	if (l2cap_pi(sk)->link_mode & L2CAP_LM_AUTH ||
			l2cap_pi(sk)->link_mode & L2CAP_LM_ENCRYPT ||
				l2cap_pi(sk)->link_mode & L2CAP_LM_SECURE) {
		if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001))
			auth_type = HCI_AT_NO_BONDING_MITM;
		else
			auth_type = HCI_AT_GENERAL_BONDING_MITM;
	} else {
		if (l2cap_pi(sk)->psm == cpu_to_le16(0x0001))
			auth_type = HCI_AT_NO_BONDING;
		else
			auth_type = HCI_AT_GENERAL_BONDING;
	}

	hcon = hci_connect(hdev, ACL_LINK, dst, auth_type);
	if (!hcon)
	if (!hcon)
		goto done;
		goto done;


@@ -1553,7 +1568,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
	struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
	struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
	struct l2cap_conn_rsp rsp;
	struct l2cap_conn_rsp rsp;
	struct sock *sk, *parent;
	struct sock *sk, *parent;
	int result, status = 0;
	int result, status = L2CAP_CS_NO_INFO;


	u16 dcid = 0, scid = __le16_to_cpu(req->scid);
	u16 dcid = 0, scid = __le16_to_cpu(req->scid);
	__le16 psm = req->psm;
	__le16 psm = req->psm;
@@ -1567,6 +1582,13 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd
		goto sendresp;
		goto sendresp;
	}
	}


	/* Check if the ACL is secure enough (if not SDP) */
	if (psm != cpu_to_le16(0x0001) &&
				!hci_conn_check_link_mode(conn->hcon)) {
		result = L2CAP_CR_SEC_BLOCK;
		goto response;
	}

	result = L2CAP_CR_NO_MEM;
	result = L2CAP_CR_NO_MEM;


	/* Check for backlog size */
	/* Check for backlog size */
@@ -2224,7 +2246,7 @@ static int l2cap_auth_cfm(struct hci_conn *hcon, u8 status)
			rsp.scid   = cpu_to_le16(l2cap_pi(sk)->dcid);
			rsp.scid   = cpu_to_le16(l2cap_pi(sk)->dcid);
			rsp.dcid   = cpu_to_le16(l2cap_pi(sk)->scid);
			rsp.dcid   = cpu_to_le16(l2cap_pi(sk)->scid);
			rsp.result = cpu_to_le16(result);
			rsp.result = cpu_to_le16(result);
			rsp.status = cpu_to_le16(0);
			rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
			l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
			l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
					L2CAP_CONN_RSP, sizeof(rsp), &rsp);
					L2CAP_CONN_RSP, sizeof(rsp), &rsp);
		}
		}
@@ -2296,7 +2318,7 @@ static int l2cap_encrypt_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
			rsp.scid   = cpu_to_le16(l2cap_pi(sk)->dcid);
			rsp.scid   = cpu_to_le16(l2cap_pi(sk)->dcid);
			rsp.dcid   = cpu_to_le16(l2cap_pi(sk)->scid);
			rsp.dcid   = cpu_to_le16(l2cap_pi(sk)->scid);
			rsp.result = cpu_to_le16(result);
			rsp.result = cpu_to_le16(result);
			rsp.status = cpu_to_le16(0);
			rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO);
			l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
			l2cap_send_cmd(conn, l2cap_pi(sk)->ident,
					L2CAP_CONN_RSP, sizeof(rsp), &rsp);
					L2CAP_CONN_RSP, sizeof(rsp), &rsp);
		}
		}
Loading