Message ID | 20211115064914.2345-8-kiran.k@intel.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | [v3,01/13] Bluetooth: Refactor code to read supported codecs in getsockopt | expand |
Context | Check | Description |
---|---|---|
tedd_an/checkpatch | success | Checkpatch PASS |
tedd_an/gitlint | success | Gitlint PASS |
Hi Kiran, On Sun, Nov 14, 2021 at 10:44 PM Kiran K <kiran.k@intel.com> wrote: > > In A2DP offload use case, controller needs to configured > with selected codec capabilities, dcid of media transport > channel and ACL connection handle. > > Controller responds with avdtp handle which needs to be > sent in other avdtp commands like start, suspend and close. > > Signed-off-by: Kiran K <kiran.k@intel.com> > Reviewed-by: Chethan T N <chethan.tumkur.narayan@intel.com> > Reviewed-by: Srivatsa Ravishankar <ravishankar.srivatsa@intel.com> > --- > include/net/bluetooth/bluetooth.h | 2 ++ > include/net/bluetooth/hci.h | 16 ++++++++++++ > net/bluetooth/hci_codec.c | 43 +++++++++++++++++++++++++++++++ > net/bluetooth/hci_codec.h | 4 +++ > net/bluetooth/l2cap_sock.c | 24 +++++++++++++++++ > 5 files changed, 89 insertions(+) > > diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h > index 2f31e571f34c..5e07cfed941d 100644 > --- a/include/net/bluetooth/bluetooth.h > +++ b/include/net/bluetooth/bluetooth.h > @@ -177,6 +177,8 @@ struct bt_codecs { > #define BT_CODEC_TRANSPARENT 0x03 > #define BT_CODEC_MSBC 0x05 > > +#define BT_MSFT_OPEN 20 I rather not have each command as a different sockopt, instead I would suggest just one opcode and a internal header for each command so we don't pollute too much our sockopt space since this only really apply to MSFT I guess calling it BT_MSFT should be fine, also Id make it extensible so we have a header and a flexible payload in case more commands needs to be added. > __printf(1, 2) > void bt_info(const char *fmt, ...); > __printf(1, 2) > diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h > index 7ea1bfce204f..a7dad0125c10 100644 > --- a/include/net/bluetooth/hci.h > +++ b/include/net/bluetooth/hci.h > @@ -2009,6 +2009,22 @@ struct hci_cp_le_reject_cis { > __u8 reason; > } __packed; > > +#define HCI_MSFT_AVDTP_CMD 0xfc1e > + > +#define HCI_MSFT_AVDTP_OPEN 0x08 > +struct hci_media_service_caps { > + __u8 category; > + __u8 len; > + __u8 data[0]; > +} __packed; > + > +struct msft_cp_avdtp_open { > + __u8 sub_opcode; > + __le16 handle; > + __le16 dcid; > + __le16 omtu; > +} __packed; > + > /* ---- HCI Events ---- */ > #define HCI_EV_INQUIRY_COMPLETE 0x01 > > diff --git a/net/bluetooth/hci_codec.c b/net/bluetooth/hci_codec.c > index c6bd934dcf36..e179f3bfb494 100644 > --- a/net/bluetooth/hci_codec.c > +++ b/net/bluetooth/hci_codec.c > @@ -355,3 +355,46 @@ int hci_get_supported_codecs(struct hci_dev *hdev, u8 type, char __user *optval, > error: > return err; > } > + > +int hci_configure_msft_avdtp_open(struct hci_dev *hdev, struct l2cap_chan *chan, > + sockptr_t optval, int optlen) > +{ > + struct msft_cp_avdtp_open *cmd = NULL; > + struct hci_media_service_caps *caps; > + int err; > + > + if (!optlen || optlen < sizeof(*caps)) { > + err = -EINVAL; > + goto fail; > + } > + > + cmd = kzalloc(sizeof(*cmd) + optlen, GFP_KERNEL); > + if (!cmd) { > + err = -ENOMEM; > + goto fail; > + } > + > + cmd->sub_opcode = HCI_MSFT_AVDTP_OPEN; > + cmd->handle = __cpu_to_le16(chan->conn->hcon->handle); > + cmd->dcid = cpu_to_le16(chan->dcid); > + cmd->omtu = cpu_to_le16(chan->omtu); > + caps = (void *)(cmd + 1); > + > + if (copy_from_sockptr(caps, optval, optlen)) { > + err = -EFAULT; > + goto fail; > + } > + > + if (caps->category != 0x07) { > + err = -EINVAL; > + goto fail; > + } > + > + hci_send_cmd(hdev, HCI_MSFT_AVDTP_CMD, sizeof(*cmd) + optlen, cmd); > + > + /* wait until we get avdtp handle or timeout */ > + > +fail: > + kfree(cmd); > + return err; > +} > diff --git a/net/bluetooth/hci_codec.h b/net/bluetooth/hci_codec.h > index 6e849c7d75b9..123b46a6a8ce 100644 > --- a/net/bluetooth/hci_codec.h > +++ b/net/bluetooth/hci_codec.h > @@ -2,8 +2,12 @@ > > /* Copyright (C) 2014 Intel Corporation */ > > +#include <net/bluetooth/l2cap.h> > + > void hci_read_supported_codecs(struct hci_dev *hdev); > void hci_read_supported_codecs_v2(struct hci_dev *hdev); > void hci_codec_list_clear(struct list_head *codec_list); > int hci_get_supported_codecs(struct hci_dev *hdev, u8 type, char __user *optval, > int __user *optlen, int len); > +int hci_configure_msft_avdtp_open(struct hci_dev *hdev, struct l2cap_chan *chan, > + sockptr_t optval, int optlen); Id place this function inside msft.h/msft.c since this is a MSFT extension. > diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c > index a883acf33e3c..fa689e576576 100644 > --- a/net/bluetooth/l2cap_sock.c > +++ b/net/bluetooth/l2cap_sock.c > @@ -909,6 +909,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, > struct l2cap_conn *conn; > int len, err = 0; > u32 opt; > + struct hci_dev *hdev; > > BT_DBG("sk %p", sk); > > @@ -1137,6 +1138,29 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, > > break; > > + case BT_MSFT_OPEN: > + if (sk->sk_state != BT_CONNECTED) { > + err = -ENOTCONN; > + break; > + } > + > + hdev = hci_get_route(BDADDR_ANY, &chan->src, BDADDR_BREDR); > + if (!hdev) { > + err = -EBADFD; > + break; > + } > + > + if (!hci_dev_test_flag(hdev, HCI_OFFLOAD_CODECS_ENABLED) || > + !hdev->get_data_path_id) { > + err = -EOPNOTSUPP; > + hci_dev_put(hdev); > + break; > + } > + > + err = hci_configure_msft_avdtp_open(hdev, chan, optval, optlen); > + hci_dev_put(hdev); > + break; > + > default: > err = -ENOPROTOOPT; > break; > -- > 2.17.1 >
Hi Luiz, > > Hi Kiran, > > On Sun, Nov 14, 2021 at 10:44 PM Kiran K <kiran.k@intel.com> wrote: > > > > In A2DP offload use case, controller needs to configured with selected > > codec capabilities, dcid of media transport channel and ACL connection > > handle. > > > > Controller responds with avdtp handle which needs to be sent in other > > avdtp commands like start, suspend and close. > > > > Signed-off-by: Kiran K <kiran.k@intel.com> > > Reviewed-by: Chethan T N <chethan.tumkur.narayan@intel.com> > > Reviewed-by: Srivatsa Ravishankar <ravishankar.srivatsa@intel.com> > > --- > > include/net/bluetooth/bluetooth.h | 2 ++ > > include/net/bluetooth/hci.h | 16 ++++++++++++ > > net/bluetooth/hci_codec.c | 43 +++++++++++++++++++++++++++++++ > > net/bluetooth/hci_codec.h | 4 +++ > > net/bluetooth/l2cap_sock.c | 24 +++++++++++++++++ > > 5 files changed, 89 insertions(+) > > > > diff --git a/include/net/bluetooth/bluetooth.h > > b/include/net/bluetooth/bluetooth.h > > index 2f31e571f34c..5e07cfed941d 100644 > > --- a/include/net/bluetooth/bluetooth.h > > +++ b/include/net/bluetooth/bluetooth.h > > @@ -177,6 +177,8 @@ struct bt_codecs { > > #define BT_CODEC_TRANSPARENT 0x03 > > #define BT_CODEC_MSBC 0x05 > > > > +#define BT_MSFT_OPEN 20 > > I rather not have each command as a different sockopt, instead I would > suggest just one opcode and a internal header for each command so we > don't pollute too much our sockopt space since this only really apply to MSFT > I guess calling it BT_MSFT should be fine, also Id make it extensible so we > have a header and a flexible payload in case more commands needs to be > added. Agree. I will send an updated patch. > > > __printf(1, 2) > > void bt_info(const char *fmt, ...); > > __printf(1, 2) > > diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h > > index 7ea1bfce204f..a7dad0125c10 100644 > > --- a/include/net/bluetooth/hci.h > > +++ b/include/net/bluetooth/hci.h > > @@ -2009,6 +2009,22 @@ struct hci_cp_le_reject_cis { > > __u8 reason; > > } __packed; > > > > +#define HCI_MSFT_AVDTP_CMD 0xfc1e > > + > > +#define HCI_MSFT_AVDTP_OPEN 0x08 > > +struct hci_media_service_caps { > > + __u8 category; > > + __u8 len; > > + __u8 data[0]; > > +} __packed; > > + > > +struct msft_cp_avdtp_open { > > + __u8 sub_opcode; > > + __le16 handle; > > + __le16 dcid; > > + __le16 omtu; > > +} __packed; > > + > > /* ---- HCI Events ---- */ > > #define HCI_EV_INQUIRY_COMPLETE 0x01 > > > > diff --git a/net/bluetooth/hci_codec.c b/net/bluetooth/hci_codec.c > > index c6bd934dcf36..e179f3bfb494 100644 > > --- a/net/bluetooth/hci_codec.c > > +++ b/net/bluetooth/hci_codec.c > > @@ -355,3 +355,46 @@ int hci_get_supported_codecs(struct hci_dev > > *hdev, u8 type, char __user *optval, > > error: > > return err; > > } > > + > > +int hci_configure_msft_avdtp_open(struct hci_dev *hdev, struct > l2cap_chan *chan, > > + sockptr_t optval, int optlen) { > > + struct msft_cp_avdtp_open *cmd = NULL; > > + struct hci_media_service_caps *caps; > > + int err; > > + > > + if (!optlen || optlen < sizeof(*caps)) { > > + err = -EINVAL; > > + goto fail; > > + } > > + > > + cmd = kzalloc(sizeof(*cmd) + optlen, GFP_KERNEL); > > + if (!cmd) { > > + err = -ENOMEM; > > + goto fail; > > + } > > + > > + cmd->sub_opcode = HCI_MSFT_AVDTP_OPEN; > > + cmd->handle = __cpu_to_le16(chan->conn->hcon->handle); > > + cmd->dcid = cpu_to_le16(chan->dcid); > > + cmd->omtu = cpu_to_le16(chan->omtu); > > + caps = (void *)(cmd + 1); > > + > > + if (copy_from_sockptr(caps, optval, optlen)) { > > + err = -EFAULT; > > + goto fail; > > + } > > + > > + if (caps->category != 0x07) { > > + err = -EINVAL; > > + goto fail; > > + } > > + > > + hci_send_cmd(hdev, HCI_MSFT_AVDTP_CMD, sizeof(*cmd) + optlen, > > + cmd); > > + > > + /* wait until we get avdtp handle or timeout */ > > + > > +fail: > > + kfree(cmd); > > + return err; > > +} > > diff --git a/net/bluetooth/hci_codec.h b/net/bluetooth/hci_codec.h > > index 6e849c7d75b9..123b46a6a8ce 100644 > > --- a/net/bluetooth/hci_codec.h > > +++ b/net/bluetooth/hci_codec.h > > @@ -2,8 +2,12 @@ > > > > /* Copyright (C) 2014 Intel Corporation */ > > > > +#include <net/bluetooth/l2cap.h> > > + > > void hci_read_supported_codecs(struct hci_dev *hdev); void > > hci_read_supported_codecs_v2(struct hci_dev *hdev); void > > hci_codec_list_clear(struct list_head *codec_list); int > > hci_get_supported_codecs(struct hci_dev *hdev, u8 type, char __user > *optval, > > int __user *optlen, int len); > > +int hci_configure_msft_avdtp_open(struct hci_dev *hdev, struct > l2cap_chan *chan, > > + sockptr_t optval, int optlen); > > Id place this function inside msft.h/msft.c since this is a MSFT extension. > > > diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c > > index a883acf33e3c..fa689e576576 100644 > > --- a/net/bluetooth/l2cap_sock.c > > +++ b/net/bluetooth/l2cap_sock.c > > @@ -909,6 +909,7 @@ static int l2cap_sock_setsockopt(struct socket > *sock, int level, int optname, > > struct l2cap_conn *conn; > > int len, err = 0; > > u32 opt; > > + struct hci_dev *hdev; > > > > BT_DBG("sk %p", sk); > > > > @@ -1137,6 +1138,29 @@ static int l2cap_sock_setsockopt(struct socket > > *sock, int level, int optname, > > > > break; > > > > + case BT_MSFT_OPEN: > > + if (sk->sk_state != BT_CONNECTED) { > > + err = -ENOTCONN; > > + break; > > + } > > + > > + hdev = hci_get_route(BDADDR_ANY, &chan->src, > BDADDR_BREDR); > > + if (!hdev) { > > + err = -EBADFD; > > + break; > > + } > > + > > + if (!hci_dev_test_flag(hdev, HCI_OFFLOAD_CODECS_ENABLED) || > > + !hdev->get_data_path_id) { > > + err = -EOPNOTSUPP; > > + hci_dev_put(hdev); > > + break; > > + } > > + > > + err = hci_configure_msft_avdtp_open(hdev, chan, optval, optlen); > > + hci_dev_put(hdev); > > + break; > > + > > default: > > err = -ENOPROTOOPT; > > break; > > -- > > 2.17.1 > > > > > -- > Luiz Augusto von Dentz Thanks, Kiran
Hi Kiran, url: https://github.com/0day-ci/linux/commits/Kiran-K/Bluetooth-Refactor-code-to-read-supported-codecs-in-getsockopt/20211115-144640 base: https://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git master config: i386-randconfig-m021-20211115 (attached as .config) compiler: gcc-9 (Debian 9.3.0-22) 9.3.0 If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp@intel.com> Reported-by: Dan Carpenter <dan.carpenter@oracle.com> New smatch warnings: net/bluetooth/hci_codec.c:388 hci_configure_msft_avdtp_open() warn: is 'cmd + 1' large enough for 'struct hci_media_service_caps'? s32min Old smatch warnings: net/bluetooth/hci_codec.c:399 hci_configure_msft_avdtp_open() error: uninitialized symbol 'err'. vim +388 net/bluetooth/hci_codec.c d9396dc909768b Kiran K 2021-11-15 359 int hci_configure_msft_avdtp_open(struct hci_dev *hdev, struct l2cap_chan *chan, d9396dc909768b Kiran K 2021-11-15 360 sockptr_t optval, int optlen) d9396dc909768b Kiran K 2021-11-15 361 { d9396dc909768b Kiran K 2021-11-15 362 struct msft_cp_avdtp_open *cmd = NULL; d9396dc909768b Kiran K 2021-11-15 363 struct hci_media_service_caps *caps; d9396dc909768b Kiran K 2021-11-15 364 int err; d9396dc909768b Kiran K 2021-11-15 365 d9396dc909768b Kiran K 2021-11-15 366 if (!optlen || optlen < sizeof(*caps)) { The kbuild-bot doesn't use cross function analysis so it doesn't know how this function is called. This check doesn't prevent negative values of "optlen" and the "!optlen" condition is not required. Of course, making "optlen" into an unsigned value changes it from a "negatives are not handled" warning into a "integer overflows are not handled" warning. One idea would be to just make sure this is called with valid values and ignore the warning. It probably should be disabled globally if you don't have the cross function database. Another idea would be to write this as: if (optlen < 0 || optlen < sizeof(*caps)) { Negatives don't really cause a problem though because copy_from_user() has a check for that added in commit 6d13de1489b6 ("uaccess: disallow > INT_MAX copy sizes"). regards, dan carpenter d9396dc909768b Kiran K 2021-11-15 367 err = -EINVAL; d9396dc909768b Kiran K 2021-11-15 368 goto fail; d9396dc909768b Kiran K 2021-11-15 369 } d9396dc909768b Kiran K 2021-11-15 370 d9396dc909768b Kiran K 2021-11-15 371 cmd = kzalloc(sizeof(*cmd) + optlen, GFP_KERNEL); d9396dc909768b Kiran K 2021-11-15 372 if (!cmd) { d9396dc909768b Kiran K 2021-11-15 373 err = -ENOMEM; d9396dc909768b Kiran K 2021-11-15 374 goto fail; d9396dc909768b Kiran K 2021-11-15 375 } d9396dc909768b Kiran K 2021-11-15 376 d9396dc909768b Kiran K 2021-11-15 377 cmd->sub_opcode = HCI_MSFT_AVDTP_OPEN; d9396dc909768b Kiran K 2021-11-15 378 cmd->handle = __cpu_to_le16(chan->conn->hcon->handle); d9396dc909768b Kiran K 2021-11-15 379 cmd->dcid = cpu_to_le16(chan->dcid); d9396dc909768b Kiran K 2021-11-15 380 cmd->omtu = cpu_to_le16(chan->omtu); d9396dc909768b Kiran K 2021-11-15 381 caps = (void *)(cmd + 1); d9396dc909768b Kiran K 2021-11-15 382 d9396dc909768b Kiran K 2021-11-15 383 if (copy_from_sockptr(caps, optval, optlen)) { d9396dc909768b Kiran K 2021-11-15 384 err = -EFAULT; d9396dc909768b Kiran K 2021-11-15 385 goto fail; d9396dc909768b Kiran K 2021-11-15 386 } d9396dc909768b Kiran K 2021-11-15 387 d9396dc909768b Kiran K 2021-11-15 @388 if (caps->category != 0x07) { --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index 2f31e571f34c..5e07cfed941d 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h @@ -177,6 +177,8 @@ struct bt_codecs { #define BT_CODEC_TRANSPARENT 0x03 #define BT_CODEC_MSBC 0x05 +#define BT_MSFT_OPEN 20 + __printf(1, 2) void bt_info(const char *fmt, ...); __printf(1, 2) diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 7ea1bfce204f..a7dad0125c10 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -2009,6 +2009,22 @@ struct hci_cp_le_reject_cis { __u8 reason; } __packed; +#define HCI_MSFT_AVDTP_CMD 0xfc1e + +#define HCI_MSFT_AVDTP_OPEN 0x08 +struct hci_media_service_caps { + __u8 category; + __u8 len; + __u8 data[0]; +} __packed; + +struct msft_cp_avdtp_open { + __u8 sub_opcode; + __le16 handle; + __le16 dcid; + __le16 omtu; +} __packed; + /* ---- HCI Events ---- */ #define HCI_EV_INQUIRY_COMPLETE 0x01 diff --git a/net/bluetooth/hci_codec.c b/net/bluetooth/hci_codec.c index c6bd934dcf36..e179f3bfb494 100644 --- a/net/bluetooth/hci_codec.c +++ b/net/bluetooth/hci_codec.c @@ -355,3 +355,46 @@ int hci_get_supported_codecs(struct hci_dev *hdev, u8 type, char __user *optval, error: return err; } + +int hci_configure_msft_avdtp_open(struct hci_dev *hdev, struct l2cap_chan *chan, + sockptr_t optval, int optlen) +{ + struct msft_cp_avdtp_open *cmd = NULL; + struct hci_media_service_caps *caps; + int err; + + if (!optlen || optlen < sizeof(*caps)) { + err = -EINVAL; + goto fail; + } + + cmd = kzalloc(sizeof(*cmd) + optlen, GFP_KERNEL); + if (!cmd) { + err = -ENOMEM; + goto fail; + } + + cmd->sub_opcode = HCI_MSFT_AVDTP_OPEN; + cmd->handle = __cpu_to_le16(chan->conn->hcon->handle); + cmd->dcid = cpu_to_le16(chan->dcid); + cmd->omtu = cpu_to_le16(chan->omtu); + caps = (void *)(cmd + 1); + + if (copy_from_sockptr(caps, optval, optlen)) { + err = -EFAULT; + goto fail; + } + + if (caps->category != 0x07) { + err = -EINVAL; + goto fail; + } + + hci_send_cmd(hdev, HCI_MSFT_AVDTP_CMD, sizeof(*cmd) + optlen, cmd); + + /* wait until we get avdtp handle or timeout */ + +fail: + kfree(cmd); + return err; +} diff --git a/net/bluetooth/hci_codec.h b/net/bluetooth/hci_codec.h index 6e849c7d75b9..123b46a6a8ce 100644 --- a/net/bluetooth/hci_codec.h +++ b/net/bluetooth/hci_codec.h @@ -2,8 +2,12 @@ /* Copyright (C) 2014 Intel Corporation */ +#include <net/bluetooth/l2cap.h> + void hci_read_supported_codecs(struct hci_dev *hdev); void hci_read_supported_codecs_v2(struct hci_dev *hdev); void hci_codec_list_clear(struct list_head *codec_list); int hci_get_supported_codecs(struct hci_dev *hdev, u8 type, char __user *optval, int __user *optlen, int len); +int hci_configure_msft_avdtp_open(struct hci_dev *hdev, struct l2cap_chan *chan, + sockptr_t optval, int optlen); diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index a883acf33e3c..fa689e576576 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -909,6 +909,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, struct l2cap_conn *conn; int len, err = 0; u32 opt; + struct hci_dev *hdev; BT_DBG("sk %p", sk); @@ -1137,6 +1138,29 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, break; + case BT_MSFT_OPEN: + if (sk->sk_state != BT_CONNECTED) { + err = -ENOTCONN; + break; + } + + hdev = hci_get_route(BDADDR_ANY, &chan->src, BDADDR_BREDR); + if (!hdev) { + err = -EBADFD; + break; + } + + if (!hci_dev_test_flag(hdev, HCI_OFFLOAD_CODECS_ENABLED) || + !hdev->get_data_path_id) { + err = -EOPNOTSUPP; + hci_dev_put(hdev); + break; + } + + err = hci_configure_msft_avdtp_open(hdev, chan, optval, optlen); + hci_dev_put(hdev); + break; + default: err = -ENOPROTOOPT; break;