Skip to content

Commit

Permalink
Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/ker…
Browse files Browse the repository at this point in the history
…nel/git/bluetooth/bluetooth-next

Johan Hedberg says:

====================
pull request: bluetooth-next 2015-04-04

Here's what's probably the last bluetooth-next pull request for 4.1:

 - Fixes for LE advertising data & advertising parameters
 - Fix for race condition with HCI_RESET flag
 - New BNEPGETSUPPFEAT ioctl, needed for certification
 - New HCI request callback type to get the resulting skb
 - Cleanups to use BIT() macro wherever possible
 - Consolidate Broadcom device entries in the btusb HCI driver
 - Check for valid flags in CMTP, HIDP & BNEP
 - Disallow local privacy & OOB data combo to prevent a potential race
 - Expose SMP & ECDH selftest results through debugfs
 - Expose current Device ID info through debugfs

Please let me know if there are any issues pulling. Thanks.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Apr 7, 2015
2 parents c85d697 + 38c8af6 commit 7abccdb
Show file tree
Hide file tree
Showing 22 changed files with 570 additions and 338 deletions.
12 changes: 4 additions & 8 deletions drivers/bluetooth/btusb.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,13 +111,7 @@ static const struct usb_device_id btusb_table[] = {
{ USB_DEVICE(0x0c10, 0x0000) },

/* Broadcom BCM20702A0 */
{ USB_DEVICE(0x0489, 0xe042) },
{ USB_DEVICE(0x04ca, 0x2003) },
{ USB_DEVICE(0x0b05, 0x17b5) },
{ USB_DEVICE(0x0b05, 0x17cb) },
{ USB_DEVICE(0x413c, 0x8197) },
{ USB_DEVICE(0x13d3, 0x3404),
.driver_info = BTUSB_BCM_PATCHRAM },

/* Broadcom BCM20702B0 (Dynex/Insignia) */
{ USB_DEVICE(0x19ff, 0x0239), .driver_info = BTUSB_BCM_PATCHRAM },
Expand All @@ -139,10 +133,12 @@ static const struct usb_device_id btusb_table[] = {
.driver_info = BTUSB_BCM_PATCHRAM },

/* Belkin F8065bf - Broadcom based */
{ USB_VENDOR_AND_INTERFACE_INFO(0x050d, 0xff, 0x01, 0x01) },
{ USB_VENDOR_AND_INTERFACE_INFO(0x050d, 0xff, 0x01, 0x01),
.driver_info = BTUSB_BCM_PATCHRAM },

/* IMC Networks - Broadcom based */
{ USB_VENDOR_AND_INTERFACE_INFO(0x13d3, 0xff, 0x01, 0x01) },
{ USB_VENDOR_AND_INTERFACE_INFO(0x13d3, 0xff, 0x01, 0x01),
.driver_info = BTUSB_BCM_PATCHRAM },

/* Intel Bluetooth USB Bootloader (RAM module) */
{ USB_DEVICE(0x8087, 0x0a5a),
Expand Down
2 changes: 1 addition & 1 deletion drivers/bluetooth/hci_ldisc.c
Original file line number Diff line number Diff line change
Expand Up @@ -499,7 +499,7 @@ static int hci_uart_set_flags(struct hci_uart *hu, unsigned long flags)
BIT(HCI_UART_INIT_PENDING) |
BIT(HCI_UART_EXT_CONFIG);

if ((flags & ~valid_flags))
if (flags & ~valid_flags)
return -EINVAL;

hu->hdev_flags = flags;
Expand Down
2 changes: 2 additions & 0 deletions fs/compat_ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,7 @@ static int mt_ioctl_trans(unsigned int fd, unsigned int cmd, void __user *argp)
#define BNEPCONNDEL _IOW('B', 201, int)
#define BNEPGETCONNLIST _IOR('B', 210, int)
#define BNEPGETCONNINFO _IOR('B', 211, int)
#define BNEPGETSUPPFEAT _IOR('B', 212, int)

#define CMTPCONNADD _IOW('C', 200, int)
#define CMTPCONNDEL _IOW('C', 201, int)
Expand Down Expand Up @@ -1247,6 +1248,7 @@ COMPATIBLE_IOCTL(BNEPCONNADD)
COMPATIBLE_IOCTL(BNEPCONNDEL)
COMPATIBLE_IOCTL(BNEPGETCONNLIST)
COMPATIBLE_IOCTL(BNEPGETCONNINFO)
COMPATIBLE_IOCTL(BNEPGETSUPPFEAT)
COMPATIBLE_IOCTL(CMTPCONNADD)
COMPATIBLE_IOCTL(CMTPCONNDEL)
COMPATIBLE_IOCTL(CMTPGETCONNLIST)
Expand Down
23 changes: 16 additions & 7 deletions include/net/bluetooth/bluetooth.h
Original file line number Diff line number Diff line change
Expand Up @@ -269,25 +269,34 @@ struct l2cap_ctrl {
__u16 reqseq;
__u16 txseq;
__u8 retries;
__le16 psm;
bdaddr_t bdaddr;
struct l2cap_chan *chan;
};

struct hci_dev;

typedef void (*hci_req_complete_t)(struct hci_dev *hdev, u8 status, u16 opcode);
typedef void (*hci_req_complete_skb_t)(struct hci_dev *hdev, u8 status,
u16 opcode, struct sk_buff *skb);

struct req_ctrl {
bool start;
u8 event;
hci_req_complete_t complete;
hci_req_complete_skb_t complete_skb;
};

struct bt_skb_cb {
__u8 pkt_type;
__u8 force_active;
__u16 opcode;
__u16 expect;
__u8 incoming:1;
__u8 req_start:1;
u8 req_event;
hci_req_complete_t req_complete;
struct l2cap_chan *chan;
struct l2cap_ctrl control;
bdaddr_t bdaddr;
__le16 psm;
union {
struct l2cap_ctrl l2cap;
struct req_ctrl req;
};
};
#define bt_cb(skb) ((struct bt_skb_cb *)((skb)->cb))

Expand Down
7 changes: 1 addition & 6 deletions include/net/bluetooth/hci_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -326,14 +326,14 @@ struct hci_dev {
struct sk_buff_head raw_q;
struct sk_buff_head cmd_q;

struct sk_buff *recv_evt;
struct sk_buff *sent_cmd;
struct sk_buff *reassembly[NUM_REASSEMBLY];

struct mutex req_lock;
wait_queue_head_t req_wait_q;
__u32 req_status;
__u32 req_result;
struct sk_buff *req_skb;

void *smp_data;
void *smp_bredr_data;
Expand Down Expand Up @@ -1284,8 +1284,6 @@ static inline int hci_check_conn_params(u16 min, u16 max, u16 latency,
int hci_register_cb(struct hci_cb *hcb);
int hci_unregister_cb(struct hci_cb *hcb);

bool hci_req_pending(struct hci_dev *hdev);

struct sk_buff *__hci_cmd_sync(struct hci_dev *hdev, u16 opcode, u32 plen,
const void *param, u32 timeout);
struct sk_buff *__hci_cmd_sync_ev(struct hci_dev *hdev, u16 opcode, u32 plen,
Expand Down Expand Up @@ -1393,9 +1391,6 @@ void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status);
void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
u8 status);
void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status);
void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
u8 *rand192, u8 *hash256, u8 *rand256,
u8 status);
void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len);
Expand Down
4 changes: 4 additions & 0 deletions net/bluetooth/bnep/bnep.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,10 @@ struct bnep_ext_hdr {
#define BNEPCONNDEL _IOW('B', 201, int)
#define BNEPGETCONNLIST _IOR('B', 210, int)
#define BNEPGETCONNINFO _IOR('B', 211, int)
#define BNEPGETSUPPFEAT _IOR('B', 212, int)

#define BNEP_SETUP_RESPONSE 0
#define BNEP_SETUP_RSP_SENT 10

struct bnep_connadd_req {
int sock; /* Connected socket */
Expand Down
70 changes: 57 additions & 13 deletions net/bluetooth/bnep/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -231,15 +231,22 @@ static int bnep_rx_control(struct bnep_session *s, void *data, int len)
break;

case BNEP_SETUP_CONN_REQ:
err = bnep_send_rsp(s, BNEP_SETUP_CONN_RSP, BNEP_CONN_NOT_ALLOWED);
/* Successful response should be sent only once */
if (test_bit(BNEP_SETUP_RESPONSE, &s->flags) &&
!test_and_set_bit(BNEP_SETUP_RSP_SENT, &s->flags))
err = bnep_send_rsp(s, BNEP_SETUP_CONN_RSP,
BNEP_SUCCESS);
else
err = bnep_send_rsp(s, BNEP_SETUP_CONN_RSP,
BNEP_CONN_NOT_ALLOWED);
break;

default: {
u8 pkt[3];
pkt[0] = BNEP_CONTROL;
pkt[1] = BNEP_CMD_NOT_UNDERSTOOD;
pkt[2] = cmd;
bnep_send(s, pkt, sizeof(pkt));
err = bnep_send(s, pkt, sizeof(pkt));
}
break;
}
Expand Down Expand Up @@ -292,29 +299,55 @@ static int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
{
struct net_device *dev = s->dev;
struct sk_buff *nskb;
u8 type;
u8 type, ctrl_type;

dev->stats.rx_bytes += skb->len;

type = *(u8 *) skb->data;
skb_pull(skb, 1);
ctrl_type = *(u8 *)skb->data;

if ((type & BNEP_TYPE_MASK) >= sizeof(__bnep_rx_hlen))
goto badframe;

if ((type & BNEP_TYPE_MASK) == BNEP_CONTROL) {
bnep_rx_control(s, skb->data, skb->len);
kfree_skb(skb);
return 0;
}
if (bnep_rx_control(s, skb->data, skb->len) < 0) {
dev->stats.tx_errors++;
kfree_skb(skb);
return 0;
}

skb_reset_mac_header(skb);
if (!(type & BNEP_EXT_HEADER)) {
kfree_skb(skb);
return 0;
}

/* Verify and pull out header */
if (!skb_pull(skb, __bnep_rx_hlen[type & BNEP_TYPE_MASK]))
goto badframe;
/* Verify and pull ctrl message since it's already processed */
switch (ctrl_type) {
case BNEP_SETUP_CONN_REQ:
/* Pull: ctrl type (1 b), len (1 b), data (len bytes) */
if (!skb_pull(skb, 2 + *(u8 *)(skb->data + 1) * 2))
goto badframe;
break;
case BNEP_FILTER_MULTI_ADDR_SET:
case BNEP_FILTER_NET_TYPE_SET:
/* Pull: ctrl type (1 b), len (2 b), data (len bytes) */
if (!skb_pull(skb, 3 + *(u16 *)(skb->data + 1) * 2))
goto badframe;
break;
default:
kfree_skb(skb);
return 0;
}
} else {
skb_reset_mac_header(skb);

s->eh.h_proto = get_unaligned((__be16 *) (skb->data - 2));
/* Verify and pull out header */
if (!skb_pull(skb, __bnep_rx_hlen[type & BNEP_TYPE_MASK]))
goto badframe;

s->eh.h_proto = get_unaligned((__be16 *) (skb->data - 2));
}

if (type & BNEP_EXT_HEADER) {
if (bnep_rx_extension(s, skb) < 0)
Expand Down Expand Up @@ -525,6 +558,7 @@ static struct device_type bnep_type = {

int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
{
u32 valid_flags = BIT(BNEP_SETUP_RESPONSE);
struct net_device *dev;
struct bnep_session *s, *ss;
u8 dst[ETH_ALEN], src[ETH_ALEN];
Expand All @@ -535,6 +569,9 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
if (!l2cap_is_socket(sock))
return -EBADFD;

if (req->flags & ~valid_flags)
return -EINVAL;

baswap((void *) dst, &l2cap_pi(sock->sk)->chan->dst);
baswap((void *) src, &l2cap_pi(sock->sk)->chan->src);

Expand Down Expand Up @@ -566,6 +603,7 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)
s->sock = sock;
s->role = req->role;
s->state = BT_CONNECTED;
s->flags = req->flags;

s->msg.msg_flags = MSG_NOSIGNAL;

Expand Down Expand Up @@ -611,11 +649,15 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock)

int bnep_del_connection(struct bnep_conndel_req *req)
{
u32 valid_flags = 0;
struct bnep_session *s;
int err = 0;

BT_DBG("");

if (req->flags & ~valid_flags)
return -EINVAL;

down_read(&bnep_session_sem);

s = __bnep_get_session(req->dst);
Expand All @@ -631,10 +673,12 @@ int bnep_del_connection(struct bnep_conndel_req *req)

static void __bnep_copy_ci(struct bnep_conninfo *ci, struct bnep_session *s)
{
u32 valid_flags = BIT(BNEP_SETUP_RESPONSE);

memset(ci, 0, sizeof(*ci));
memcpy(ci->dst, s->eh.h_source, ETH_ALEN);
strcpy(ci->device, s->dev->name);
ci->flags = s->flags;
ci->flags = s->flags & valid_flags;
ci->state = s->state;
ci->role = s->role;
}
Expand Down
7 changes: 7 additions & 0 deletions net/bluetooth/bnep/sock.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ static int bnep_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long
struct bnep_conninfo ci;
struct socket *nsock;
void __user *argp = (void __user *)arg;
__u32 supp_feat = BIT(BNEP_SETUP_RESPONSE);
int err;

BT_DBG("cmd %x arg %lx", cmd, arg);
Expand Down Expand Up @@ -120,6 +121,12 @@ static int bnep_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long

return err;

case BNEPGETSUPPFEAT:
if (copy_to_user(argp, &supp_feat, sizeof(supp_feat)))
return -EFAULT;

return 0;

default:
return -EINVAL;
}
Expand Down
2 changes: 1 addition & 1 deletion net/bluetooth/cmtp/capi.c
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ void cmtp_recv_capimsg(struct cmtp_session *session, struct sk_buff *skb)
return;
}

if (session->flags & (1 << CMTP_LOOPBACK)) {
if (session->flags & BIT(CMTP_LOOPBACK)) {
kfree_skb(skb);
return;
}
Expand Down
15 changes: 12 additions & 3 deletions net/bluetooth/cmtp/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,11 @@ static void __cmtp_unlink_session(struct cmtp_session *session)

static void __cmtp_copy_session(struct cmtp_session *session, struct cmtp_conninfo *ci)
{
u32 valid_flags = BIT(CMTP_LOOPBACK);
memset(ci, 0, sizeof(*ci));
bacpy(&ci->bdaddr, &session->bdaddr);

ci->flags = session->flags;
ci->flags = session->flags & valid_flags;
ci->state = session->state;

ci->num = session->num;
Expand Down Expand Up @@ -313,7 +314,7 @@ static int cmtp_session(void *arg)

down_write(&cmtp_session_sem);

if (!(session->flags & (1 << CMTP_LOOPBACK)))
if (!(session->flags & BIT(CMTP_LOOPBACK)))
cmtp_detach_device(session);

fput(session->sock->file);
Expand All @@ -329,6 +330,7 @@ static int cmtp_session(void *arg)

int cmtp_add_connection(struct cmtp_connadd_req *req, struct socket *sock)
{
u32 valid_flags = BIT(CMTP_LOOPBACK);
struct cmtp_session *session, *s;
int i, err;

Expand All @@ -337,6 +339,9 @@ int cmtp_add_connection(struct cmtp_connadd_req *req, struct socket *sock)
if (!l2cap_is_socket(sock))
return -EBADFD;

if (req->flags & ~valid_flags)
return -EINVAL;

session = kzalloc(sizeof(struct cmtp_session), GFP_KERNEL);
if (!session)
return -ENOMEM;
Expand Down Expand Up @@ -385,7 +390,7 @@ int cmtp_add_connection(struct cmtp_connadd_req *req, struct socket *sock)
goto unlink;
}

if (!(session->flags & (1 << CMTP_LOOPBACK))) {
if (!(session->flags & BIT(CMTP_LOOPBACK))) {
err = cmtp_attach_device(session);
if (err < 0) {
atomic_inc(&session->terminate);
Expand All @@ -409,11 +414,15 @@ int cmtp_add_connection(struct cmtp_connadd_req *req, struct socket *sock)

int cmtp_del_connection(struct cmtp_conndel_req *req)
{
u32 valid_flags = 0;
struct cmtp_session *session;
int err = 0;

BT_DBG("");

if (req->flags & ~valid_flags)
return -EINVAL;

down_read(&cmtp_session_sem);

session = __cmtp_get_session(&req->bdaddr);
Expand Down
Loading

0 comments on commit 7abccdb

Please sign in to comment.