From 198e79f0e8f0b24c1e36ab6032d348f40de20262 Mon Sep 17 00:00:00 2001 From: Dominik Sliwa Date: Fri, 22 Dec 2017 12:07:34 +0000 Subject: backports: bluetooth: Support 4.9 kernels Signed-off-by: Dominik Sliwa --- net/bluetooth/Kconfig | 3 ++- net/bluetooth/a2mp.c | 4 ++-- net/bluetooth/af_bluetooth.c | 3 ++- net/bluetooth/ecdh_helper.c | 4 ++++ net/bluetooth/l2cap_core.c | 38 +++++++++++++++++++++++++++++++++++++- net/bluetooth/l2cap_sock.c | 14 +++++++++++++- net/bluetooth/rfcomm/core.c | 4 ++-- net/bluetooth/rfcomm/sock.c | 6 +++++- net/bluetooth/sco.c | 6 +++++- 9 files changed, 72 insertions(+), 10 deletions(-) (limited to 'net') diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig index 08f5808..0f68a23 100644 --- a/net/bluetooth/Kconfig +++ b/net/bluetooth/Kconfig @@ -14,7 +14,8 @@ menuconfig BT depends on CRYPTO_CMAC depends on CRYPTO_ECB depends on CRYPTO_SHA256 - depends on CRYPTO_ECDH + depends on CRYPTO_ECDH + depends on !KERNEL_4_7 help Bluetooth is low-cost, low-power, short-range wireless technology. It was designed as a replacement for cables and other short-range diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c index ab3bb87..e6d3b82 100644 --- a/net/bluetooth/a2mp.c +++ b/net/bluetooth/a2mp.c @@ -244,7 +244,7 @@ static int a2mp_discover_rsp(struct amp_mgr *mgr, struct sk_buff *skb, } len -= sizeof(*cl); - cl = skb_pull(skb, sizeof(*cl)); + cl = (void *)skb_pull(skb, sizeof(*cl)); } /* Fall back to L2CAP init sequence */ @@ -284,7 +284,7 @@ static int a2mp_change_notify(struct amp_mgr *mgr, struct sk_buff *skb, while (skb->len >= sizeof(*cl)) { BT_DBG("Controller id %d type %d status %d", cl->id, cl->type, cl->status); - cl = skb_pull(skb, sizeof(*cl)); + cl = (void *) skb_pull(skb, sizeof(*cl)); } /* TODO send A2MP_CHANGE_RSP */ diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 91e3ba2..1c10269 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -28,6 +28,7 @@ #include #include #include +#include #include @@ -657,7 +658,7 @@ static int bt_seq_show(struct seq_file *seq, void *v) seq_printf(seq, "%pK %-6d %-6u %-6u %-6u %-6lu %-6lu", sk, - refcount_read(&sk->sk_refcnt), + refcount_read((const refcount_t *)&sk->sk_refcnt), sk_rmem_alloc_get(sk), sk_wmem_alloc_get(sk), from_kuid(seq_user_ns(seq), sock_i_uid(sk)), diff --git a/net/bluetooth/ecdh_helper.c b/net/bluetooth/ecdh_helper.c index c7b1a9a..ce6c546 100644 --- a/net/bluetooth/ecdh_helper.c +++ b/net/bluetooth/ecdh_helper.c @@ -23,7 +23,11 @@ #include "ecdh_helper.h" #include +#if LINUX_VERSION_IS_LESS(4,8,0) +#include +#else #include +#endif #include struct ecdh_completion { diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 9800324..a1a9b4c 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -33,7 +33,7 @@ #include #include #include - +#include #include #include #include @@ -2119,6 +2119,42 @@ static void l2cap_send_ack(struct l2cap_chan *chan) } } +extern void __compiletime_error("copy source size is too small") +__bad_copy_from(void); +extern void __compiletime_error("copy destination size is too small") +__bad_copy_to(void); + +static inline void copy_overflow(int size, unsigned long count) +{ + WARN(1, "Buffer overflow detected (%d < %lu)!\n", size, count); +} + +static __always_inline bool +check_copy_size(const void *addr, size_t bytes, bool is_source) +{ + int sz = __compiletime_object_size(addr); + if (unlikely(sz >= 0 && sz < bytes)) { + if (!__builtin_constant_p(bytes)) + copy_overflow(sz, bytes); + else if (is_source) + __bad_copy_from(); + else + __bad_copy_to(); + return false; + } + check_object_size(addr, bytes, is_source); + return true; +} + +static __always_inline __must_check +bool copy_from_iter_full(void *addr, size_t bytes, struct iov_iter *i) +{ + if (unlikely(!check_copy_size(addr, bytes, false))) + return false; + else + return _copy_from_iter_full(addr, bytes, i); +} + static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan, struct msghdr *msg, int len, int count, struct sk_buff *skb) diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 72022c5..f357d16 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -300,9 +300,13 @@ done: release_sock(sk); return err; } - +#if LINUX_VERSION_IS_LESS(4,12,0) +static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, + int flags) +#else static int l2cap_sock_accept(struct socket *sock, struct socket *newsock, int flags, bool kern) +#endif { DEFINE_WAIT_FUNC(wait, woken_wake_function); struct sock *sk = sock->sk, *nsk; @@ -1028,7 +1032,11 @@ static int l2cap_sock_recvmsg(struct socket *sock, struct msghdr *msg, goto done; if (pi->rx_busy_skb) { +#if LINUX_VERSION_IS_GEQ(4,7,0) if (!__sock_queue_rcv_skb(sk, pi->rx_busy_skb)) +#else + if (!sock_queue_rcv_skb(sk, pi->rx_busy_skb)) +#endif pi->rx_busy_skb = NULL; else goto done; @@ -1297,7 +1305,11 @@ static int l2cap_sock_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb) goto done; } +#if LINUX_VERSION_IS_GEQ(4,7,0) err = __sock_queue_rcv_skb(sk, skb); +#else + err = sock_queue_rcv_skb(sk, skb); +#endif /* For ERTM, handle one skb that doesn't fit into the recv * buffer. This is important to do because the data frames diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 7184dad..20df249 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -351,7 +351,7 @@ static void rfcomm_dlc_unlink(struct rfcomm_dlc *d) { struct rfcomm_session *s = d->session; - BT_DBG("dlc %p refcnt %d session %p", d, refcount_read(&d->refcnt), s); + BT_DBG("dlc %p refcnt %d session %p", d, refcount_read((const refcount_t *)&d->refcnt), s); list_del(&d->list); d->session = NULL; @@ -872,7 +872,7 @@ static int rfcomm_queue_disc(struct rfcomm_dlc *d) if (!skb) return -ENOMEM; - cmd = __skb_put(skb, sizeof(*cmd)); + cmd = (void *)__skb_put(skb, sizeof(*cmd)); cmd->addr = d->addr; cmd->ctrl = __ctrl(RFCOMM_DISC, 1); cmd->len = __len8(0); diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 6b18b56..8b5c51b 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -205,7 +205,7 @@ static void rfcomm_sock_kill(struct sock *sk) if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket) return; - BT_DBG("sk %p state %d refcnt %d", sk, sk->sk_state, refcount_read(&sk->sk_refcnt)); + BT_DBG("sk %p state %d refcnt %d", sk, sk->sk_state, refcount_read((const refcount_t *)&sk->sk_refcnt)); /* Kill poor orphan */ bt_sock_unlink(&rfcomm_sk_list, sk); @@ -480,8 +480,12 @@ done: return err; } +#if LINUX_VERSION_IS_LESS(4,12,0) +static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int flags) +#else static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int flags, bool kern) +#endif { DEFINE_WAIT_FUNC(wait, woken_wake_function); struct sock *sk = sock->sk, *nsk; diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index b1f215c..86a245f 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -623,9 +623,13 @@ done: release_sock(sk); return err; } - +#if LINUX_VERSION_IS_LESS(4,12,0) +static int sco_sock_accept(struct socket *sock, struct socket *newsock, + int flags) +#else static int sco_sock_accept(struct socket *sock, struct socket *newsock, int flags, bool kern) +#endif { DEFINE_WAIT_FUNC(wait, woken_wake_function); struct sock *sk = sock->sk, *ch; -- cgit v1.2.3