Blob Blame History Raw
From: Takashi Iwai <tiwai@suse.de>
Subject: kABI workaround for bluetooth l2cap_ops filter addition
Patch-mainline: Never, kABI workaround for cve/linux-4.12
References: CVE-2020-12351 bsc#1177724

The recent fix for adding a new field to struct l2cap_ops breaks kABI.
We may protect the new field with __GENKSYMS__, but this still needs
some check not to access the unexisting field in the old code.
Fix it by checking a new bit field in caps->flags additionally.

Signed-off-by: Takashi Iwai <tiwai@suse.de>

---
 include/net/bluetooth/l2cap.h |    8 ++++++++
 net/bluetooth/l2cap_core.c    |    4 +++-
 net/bluetooth/l2cap_sock.c    |    2 ++
 3 files changed, 13 insertions(+), 1 deletion(-)

--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -623,8 +623,13 @@ struct l2cap_ops {
 	struct sk_buff		*(*alloc_skb) (struct l2cap_chan *chan,
 					       unsigned long hdr_len,
 					       unsigned long len, int nb);
+#ifndef __GENKSYMS__
+	/* XXX: kABI workaround for SLE15-SP2; for enabling this ops,
+	 * you need to set FLAG_CHAN_OPS_SK_FILTER to chan->flags, too
+	 */
 	int			(*filter) (struct l2cap_chan * chan,
 					   struct sk_buff *skb);
+#endif
 };
 
 struct l2cap_conn {
@@ -730,6 +735,9 @@ enum {
 	FLAG_HOLD_HCI_CONN,
 };
 
+/* XXX: a special flag for SLE15-SP2 kABI workaround */
+#define FLAG_CHAN_OPS_SK_FILTER		30
+
 /* Lock nesting levels for L2CAP channels. We need these because lockdep
  * otherwise considers all channels equal and will e.g. complain about a
  * connection oriented channel triggering SMP procedures or a listening
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -6701,7 +6701,9 @@ static int l2cap_data_rcv(struct l2cap_c
 		goto drop;
 	}
 
-	if (chan->ops->filter) {
+	/* XXX: kABI workaround for SLE15-SP2; checking the special flag */
+	if (test_bit(FLAG_CHAN_OPS_SK_FILTER, &chan->flags) &&
+	    chan->ops->filter) {
 		if (chan->ops->filter(chan, skb))
 			goto drop;
 	}
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -1602,6 +1602,8 @@ static void l2cap_sock_init(struct sock
 
 	chan->data = sk;
 	chan->ops = &l2cap_chan_ops;
+	/* XXX: a special flag for SLE15-SP2 kABI workaround */
+	set_bit(FLAG_CHAN_OPS_SK_FILTER, &chan->flags);
 }
 
 static struct proto l2cap_proto = {