summaryrefslogtreecommitdiff
path: root/net/bluetooth/l2cap_core.c
diff options
context:
space:
mode:
authorDominik Sliwa <dominik.sliwa@toradex.com>2017-12-22 12:07:34 +0000
committerDominik Sliwa <dominik.sliwa@toradex.com>2018-09-18 17:15:11 +0200
commit69ff0b5709d0d06545fcb2d08c7645b56d3687dd (patch)
tree71f1569cc019e16c1b1be22c1e8d382766daebb3 /net/bluetooth/l2cap_core.c
parentd6a47bfb72f495a72637fbe635220f6af0f4cb6f (diff)
backports: bluetooth: Support 4.9 kernels
Signed-off-by: Dominik Sliwa <dominik.sliwa@toradex.com>
Diffstat (limited to 'net/bluetooth/l2cap_core.c')
-rw-r--r--net/bluetooth/l2cap_core.c38
1 files changed, 37 insertions, 1 deletions
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index d17a473..3bfa43f 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -33,7 +33,7 @@
#include <linux/debugfs.h>
#include <linux/crc16.h>
#include <linux/filter.h>
-
+#include <linux/uio.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
#include <net/bluetooth/l2cap.h>
@@ -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)