Skip to content

Commit 8758233

Browse files
committed
patches: Add fix for clang-19 __bad_copy_from() error
Link: ClangBuiltLinux/linux#2007 Link: https://git.kernel.org/bluetooth/bluetooth-next/c/7d80e7ebf9e333dc5463a48a914f55caef15f62f Signed-off-by: Nathan Chancellor <[email protected]>
1 parent 7c0ad00 commit 8758233

10 files changed

+655
-0
lines changed
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
From 7d80e7ebf9e333dc5463a48a914f55caef15f62f Mon Sep 17 00:00:00 2001
2+
From: Nathan Chancellor <[email protected]>
3+
Date: Mon, 1 Apr 2024 11:24:17 -0700
4+
Subject: Bluetooth: Fix type of len in {l2cap,sco}_sock_getsockopt_old()
5+
6+
After an innocuous optimization change in LLVM main (19.0.0), x86_64
7+
allmodconfig (which enables CONFIG_KCSAN / -fsanitize=thread) fails to
8+
build due to the checks in check_copy_size():
9+
10+
In file included from net/bluetooth/sco.c:27:
11+
In file included from include/linux/module.h:13:
12+
In file included from include/linux/stat.h:19:
13+
In file included from include/linux/time.h:60:
14+
In file included from include/linux/time32.h:13:
15+
In file included from include/linux/timex.h:67:
16+
In file included from arch/x86/include/asm/timex.h:6:
17+
In file included from arch/x86/include/asm/tsc.h:10:
18+
In file included from arch/x86/include/asm/msr.h:15:
19+
In file included from include/linux/percpu.h:7:
20+
In file included from include/linux/smp.h:118:
21+
include/linux/thread_info.h:244:4: error: call to '__bad_copy_from'
22+
declared with 'error' attribute: copy source size is too small
23+
244 | __bad_copy_from();
24+
| ^
25+
26+
The same exact error occurs in l2cap_sock.c. The copy_to_user()
27+
statements that are failing come from l2cap_sock_getsockopt_old() and
28+
sco_sock_getsockopt_old(). This does not occur with GCC with or without
29+
KCSAN or Clang without KCSAN enabled.
30+
31+
len is defined as an 'int' because it is assigned from
32+
'__user int *optlen'. However, it is clamped against the result of
33+
sizeof(), which has a type of 'size_t' ('unsigned long' for 64-bit
34+
platforms). This is done with min_t() because min() requires compatible
35+
types, which results in both len and the result of sizeof() being casted
36+
to 'unsigned int', meaning len changes signs and the result of sizeof()
37+
is truncated. From there, len is passed to copy_to_user(), which has a
38+
third parameter type of 'unsigned long', so it is widened and changes
39+
signs again. This excessive casting in combination with the KCSAN
40+
instrumentation causes LLVM to fail to eliminate the __bad_copy_from()
41+
call, failing the build.
42+
43+
The official recommendation from LLVM developers is to consistently use
44+
long types for all size variables to avoid the unnecessary casting in
45+
the first place. Change the type of len to size_t in both
46+
l2cap_sock_getsockopt_old() and sco_sock_getsockopt_old(). This clears
47+
up the error while allowing min_t() to be replaced with min(), resulting
48+
in simpler code with no casts and fewer implicit conversions. While len
49+
is a different type than optlen now, it should result in no functional
50+
change because the result of sizeof() will clamp all values of optlen in
51+
the same manner as before.
52+
53+
54+
Closes: https://github.com/ClangBuiltLinux/linux/issues/2007
55+
Link: https://github.com/llvm/llvm-project/issues/85647
56+
Signed-off-by: Nathan Chancellor <[email protected]>
57+
Reviewed-by: Justin Stitt <[email protected]>
58+
Signed-off-by: Luiz Augusto von Dentz <[email protected]>
59+
---
60+
net/bluetooth/l2cap_sock.c | 7 ++++---
61+
net/bluetooth/sco.c | 7 ++++---
62+
2 files changed, 8 insertions(+), 6 deletions(-)
63+
64+
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
65+
index 9a9f933a748b8..7846a068bf60b 100644
66+
--- a/net/bluetooth/l2cap_sock.c
67+
+++ b/net/bluetooth/l2cap_sock.c
68+
@@ -439,7 +439,8 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname,
69+
struct l2cap_chan *chan = l2cap_pi(sk)->chan;
70+
struct l2cap_options opts;
71+
struct l2cap_conninfo cinfo;
72+
- int len, err = 0;
73+
+ int err = 0;
74+
+ size_t len;
75+
u32 opt;
76+
77+
BT_DBG("sk %p", sk);
78+
@@ -486,7 +487,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname,
79+
80+
BT_DBG("mode 0x%2.2x", chan->mode);
81+
82+
- len = min_t(unsigned int, len, sizeof(opts));
83+
+ len = min(len, sizeof(opts));
84+
if (copy_to_user(optval, (char *) &opts, len))
85+
err = -EFAULT;
86+
87+
@@ -536,7 +537,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname,
88+
cinfo.hci_handle = chan->conn->hcon->handle;
89+
memcpy(cinfo.dev_class, chan->conn->hcon->dev_class, 3);
90+
91+
- len = min_t(unsigned int, len, sizeof(cinfo));
92+
+ len = min(len, sizeof(cinfo));
93+
if (copy_to_user(optval, (char *) &cinfo, len))
94+
err = -EFAULT;
95+
96+
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
97+
index b3c2af7c7d678..99c2b713d8268 100644
98+
--- a/net/bluetooth/sco.c
99+
+++ b/net/bluetooth/sco.c
100+
@@ -982,7 +982,8 @@ static int sco_sock_getsockopt_old(struct socket *sock, int optname,
101+
struct sock *sk = sock->sk;
102+
struct sco_options opts;
103+
struct sco_conninfo cinfo;
104+
- int len, err = 0;
105+
+ int err = 0;
106+
+ size_t len;
107+
108+
BT_DBG("sk %p", sk);
109+
110+
@@ -1004,7 +1005,7 @@ static int sco_sock_getsockopt_old(struct socket *sock, int optname,
111+
112+
BT_DBG("mtu %u", opts.mtu);
113+
114+
- len = min_t(unsigned int, len, sizeof(opts));
115+
+ len = min(len, sizeof(opts));
116+
if (copy_to_user(optval, (char *)&opts, len))
117+
err = -EFAULT;
118+
119+
@@ -1022,7 +1023,7 @@ static int sco_sock_getsockopt_old(struct socket *sock, int optname,
120+
cinfo.hci_handle = sco_pi(sk)->conn->hcon->handle;
121+
memcpy(cinfo.dev_class, sco_pi(sk)->conn->hcon->dev_class, 3);
122+
123+
- len = min_t(unsigned int, len, sizeof(cinfo));
124+
+ len = min(len, sizeof(cinfo));
125+
if (copy_to_user(optval, (char *)&cinfo, len))
126+
err = -EFAULT;
127+
128+
--
129+
cgit 1.2.3-korg
130+

patches/6.1/series

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
7d80e7ebf9e333dc5463a48a914f55caef15f62f.patch
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
From 7d80e7ebf9e333dc5463a48a914f55caef15f62f Mon Sep 17 00:00:00 2001
2+
From: Nathan Chancellor <[email protected]>
3+
Date: Mon, 1 Apr 2024 11:24:17 -0700
4+
Subject: Bluetooth: Fix type of len in {l2cap,sco}_sock_getsockopt_old()
5+
6+
After an innocuous optimization change in LLVM main (19.0.0), x86_64
7+
allmodconfig (which enables CONFIG_KCSAN / -fsanitize=thread) fails to
8+
build due to the checks in check_copy_size():
9+
10+
In file included from net/bluetooth/sco.c:27:
11+
In file included from include/linux/module.h:13:
12+
In file included from include/linux/stat.h:19:
13+
In file included from include/linux/time.h:60:
14+
In file included from include/linux/time32.h:13:
15+
In file included from include/linux/timex.h:67:
16+
In file included from arch/x86/include/asm/timex.h:6:
17+
In file included from arch/x86/include/asm/tsc.h:10:
18+
In file included from arch/x86/include/asm/msr.h:15:
19+
In file included from include/linux/percpu.h:7:
20+
In file included from include/linux/smp.h:118:
21+
include/linux/thread_info.h:244:4: error: call to '__bad_copy_from'
22+
declared with 'error' attribute: copy source size is too small
23+
244 | __bad_copy_from();
24+
| ^
25+
26+
The same exact error occurs in l2cap_sock.c. The copy_to_user()
27+
statements that are failing come from l2cap_sock_getsockopt_old() and
28+
sco_sock_getsockopt_old(). This does not occur with GCC with or without
29+
KCSAN or Clang without KCSAN enabled.
30+
31+
len is defined as an 'int' because it is assigned from
32+
'__user int *optlen'. However, it is clamped against the result of
33+
sizeof(), which has a type of 'size_t' ('unsigned long' for 64-bit
34+
platforms). This is done with min_t() because min() requires compatible
35+
types, which results in both len and the result of sizeof() being casted
36+
to 'unsigned int', meaning len changes signs and the result of sizeof()
37+
is truncated. From there, len is passed to copy_to_user(), which has a
38+
third parameter type of 'unsigned long', so it is widened and changes
39+
signs again. This excessive casting in combination with the KCSAN
40+
instrumentation causes LLVM to fail to eliminate the __bad_copy_from()
41+
call, failing the build.
42+
43+
The official recommendation from LLVM developers is to consistently use
44+
long types for all size variables to avoid the unnecessary casting in
45+
the first place. Change the type of len to size_t in both
46+
l2cap_sock_getsockopt_old() and sco_sock_getsockopt_old(). This clears
47+
up the error while allowing min_t() to be replaced with min(), resulting
48+
in simpler code with no casts and fewer implicit conversions. While len
49+
is a different type than optlen now, it should result in no functional
50+
change because the result of sizeof() will clamp all values of optlen in
51+
the same manner as before.
52+
53+
54+
Closes: https://github.com/ClangBuiltLinux/linux/issues/2007
55+
Link: https://github.com/llvm/llvm-project/issues/85647
56+
Signed-off-by: Nathan Chancellor <[email protected]>
57+
Reviewed-by: Justin Stitt <[email protected]>
58+
Signed-off-by: Luiz Augusto von Dentz <[email protected]>
59+
---
60+
net/bluetooth/l2cap_sock.c | 7 ++++---
61+
net/bluetooth/sco.c | 7 ++++---
62+
2 files changed, 8 insertions(+), 6 deletions(-)
63+
64+
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
65+
index 9a9f933a748b8..7846a068bf60b 100644
66+
--- a/net/bluetooth/l2cap_sock.c
67+
+++ b/net/bluetooth/l2cap_sock.c
68+
@@ -439,7 +439,8 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname,
69+
struct l2cap_chan *chan = l2cap_pi(sk)->chan;
70+
struct l2cap_options opts;
71+
struct l2cap_conninfo cinfo;
72+
- int len, err = 0;
73+
+ int err = 0;
74+
+ size_t len;
75+
u32 opt;
76+
77+
BT_DBG("sk %p", sk);
78+
@@ -486,7 +487,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname,
79+
80+
BT_DBG("mode 0x%2.2x", chan->mode);
81+
82+
- len = min_t(unsigned int, len, sizeof(opts));
83+
+ len = min(len, sizeof(opts));
84+
if (copy_to_user(optval, (char *) &opts, len))
85+
err = -EFAULT;
86+
87+
@@ -536,7 +537,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname,
88+
cinfo.hci_handle = chan->conn->hcon->handle;
89+
memcpy(cinfo.dev_class, chan->conn->hcon->dev_class, 3);
90+
91+
- len = min_t(unsigned int, len, sizeof(cinfo));
92+
+ len = min(len, sizeof(cinfo));
93+
if (copy_to_user(optval, (char *) &cinfo, len))
94+
err = -EFAULT;
95+
96+
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
97+
index b3c2af7c7d678..99c2b713d8268 100644
98+
--- a/net/bluetooth/sco.c
99+
+++ b/net/bluetooth/sco.c
100+
@@ -982,7 +982,8 @@ static int sco_sock_getsockopt_old(struct socket *sock, int optname,
101+
struct sock *sk = sock->sk;
102+
struct sco_options opts;
103+
struct sco_conninfo cinfo;
104+
- int len, err = 0;
105+
+ int err = 0;
106+
+ size_t len;
107+
108+
BT_DBG("sk %p", sk);
109+
110+
@@ -1004,7 +1005,7 @@ static int sco_sock_getsockopt_old(struct socket *sock, int optname,
111+
112+
BT_DBG("mtu %u", opts.mtu);
113+
114+
- len = min_t(unsigned int, len, sizeof(opts));
115+
+ len = min(len, sizeof(opts));
116+
if (copy_to_user(optval, (char *)&opts, len))
117+
err = -EFAULT;
118+
119+
@@ -1022,7 +1023,7 @@ static int sco_sock_getsockopt_old(struct socket *sock, int optname,
120+
cinfo.hci_handle = sco_pi(sk)->conn->hcon->handle;
121+
memcpy(cinfo.dev_class, sco_pi(sk)->conn->hcon->dev_class, 3);
122+
123+
- len = min_t(unsigned int, len, sizeof(cinfo));
124+
+ len = min(len, sizeof(cinfo));
125+
if (copy_to_user(optval, (char *)&cinfo, len))
126+
err = -EFAULT;
127+
128+
--
129+
cgit 1.2.3-korg
130+

patches/6.6/series

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1+
7d80e7ebf9e333dc5463a48a914f55caef15f62f.patch
12
v2_20240305_nathan_media_mxl5xx_move_xpt_structures_off_stack.patch
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
From 7d80e7ebf9e333dc5463a48a914f55caef15f62f Mon Sep 17 00:00:00 2001
2+
From: Nathan Chancellor <[email protected]>
3+
Date: Mon, 1 Apr 2024 11:24:17 -0700
4+
Subject: Bluetooth: Fix type of len in {l2cap,sco}_sock_getsockopt_old()
5+
6+
After an innocuous optimization change in LLVM main (19.0.0), x86_64
7+
allmodconfig (which enables CONFIG_KCSAN / -fsanitize=thread) fails to
8+
build due to the checks in check_copy_size():
9+
10+
In file included from net/bluetooth/sco.c:27:
11+
In file included from include/linux/module.h:13:
12+
In file included from include/linux/stat.h:19:
13+
In file included from include/linux/time.h:60:
14+
In file included from include/linux/time32.h:13:
15+
In file included from include/linux/timex.h:67:
16+
In file included from arch/x86/include/asm/timex.h:6:
17+
In file included from arch/x86/include/asm/tsc.h:10:
18+
In file included from arch/x86/include/asm/msr.h:15:
19+
In file included from include/linux/percpu.h:7:
20+
In file included from include/linux/smp.h:118:
21+
include/linux/thread_info.h:244:4: error: call to '__bad_copy_from'
22+
declared with 'error' attribute: copy source size is too small
23+
244 | __bad_copy_from();
24+
| ^
25+
26+
The same exact error occurs in l2cap_sock.c. The copy_to_user()
27+
statements that are failing come from l2cap_sock_getsockopt_old() and
28+
sco_sock_getsockopt_old(). This does not occur with GCC with or without
29+
KCSAN or Clang without KCSAN enabled.
30+
31+
len is defined as an 'int' because it is assigned from
32+
'__user int *optlen'. However, it is clamped against the result of
33+
sizeof(), which has a type of 'size_t' ('unsigned long' for 64-bit
34+
platforms). This is done with min_t() because min() requires compatible
35+
types, which results in both len and the result of sizeof() being casted
36+
to 'unsigned int', meaning len changes signs and the result of sizeof()
37+
is truncated. From there, len is passed to copy_to_user(), which has a
38+
third parameter type of 'unsigned long', so it is widened and changes
39+
signs again. This excessive casting in combination with the KCSAN
40+
instrumentation causes LLVM to fail to eliminate the __bad_copy_from()
41+
call, failing the build.
42+
43+
The official recommendation from LLVM developers is to consistently use
44+
long types for all size variables to avoid the unnecessary casting in
45+
the first place. Change the type of len to size_t in both
46+
l2cap_sock_getsockopt_old() and sco_sock_getsockopt_old(). This clears
47+
up the error while allowing min_t() to be replaced with min(), resulting
48+
in simpler code with no casts and fewer implicit conversions. While len
49+
is a different type than optlen now, it should result in no functional
50+
change because the result of sizeof() will clamp all values of optlen in
51+
the same manner as before.
52+
53+
54+
Closes: https://github.com/ClangBuiltLinux/linux/issues/2007
55+
Link: https://github.com/llvm/llvm-project/issues/85647
56+
Signed-off-by: Nathan Chancellor <[email protected]>
57+
Reviewed-by: Justin Stitt <[email protected]>
58+
Signed-off-by: Luiz Augusto von Dentz <[email protected]>
59+
---
60+
net/bluetooth/l2cap_sock.c | 7 ++++---
61+
net/bluetooth/sco.c | 7 ++++---
62+
2 files changed, 8 insertions(+), 6 deletions(-)
63+
64+
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
65+
index 9a9f933a748b8..7846a068bf60b 100644
66+
--- a/net/bluetooth/l2cap_sock.c
67+
+++ b/net/bluetooth/l2cap_sock.c
68+
@@ -439,7 +439,8 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname,
69+
struct l2cap_chan *chan = l2cap_pi(sk)->chan;
70+
struct l2cap_options opts;
71+
struct l2cap_conninfo cinfo;
72+
- int len, err = 0;
73+
+ int err = 0;
74+
+ size_t len;
75+
u32 opt;
76+
77+
BT_DBG("sk %p", sk);
78+
@@ -486,7 +487,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname,
79+
80+
BT_DBG("mode 0x%2.2x", chan->mode);
81+
82+
- len = min_t(unsigned int, len, sizeof(opts));
83+
+ len = min(len, sizeof(opts));
84+
if (copy_to_user(optval, (char *) &opts, len))
85+
err = -EFAULT;
86+
87+
@@ -536,7 +537,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname,
88+
cinfo.hci_handle = chan->conn->hcon->handle;
89+
memcpy(cinfo.dev_class, chan->conn->hcon->dev_class, 3);
90+
91+
- len = min_t(unsigned int, len, sizeof(cinfo));
92+
+ len = min(len, sizeof(cinfo));
93+
if (copy_to_user(optval, (char *) &cinfo, len))
94+
err = -EFAULT;
95+
96+
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
97+
index b3c2af7c7d678..99c2b713d8268 100644
98+
--- a/net/bluetooth/sco.c
99+
+++ b/net/bluetooth/sco.c
100+
@@ -982,7 +982,8 @@ static int sco_sock_getsockopt_old(struct socket *sock, int optname,
101+
struct sock *sk = sock->sk;
102+
struct sco_options opts;
103+
struct sco_conninfo cinfo;
104+
- int len, err = 0;
105+
+ int err = 0;
106+
+ size_t len;
107+
108+
BT_DBG("sk %p", sk);
109+
110+
@@ -1004,7 +1005,7 @@ static int sco_sock_getsockopt_old(struct socket *sock, int optname,
111+
112+
BT_DBG("mtu %u", opts.mtu);
113+
114+
- len = min_t(unsigned int, len, sizeof(opts));
115+
+ len = min(len, sizeof(opts));
116+
if (copy_to_user(optval, (char *)&opts, len))
117+
err = -EFAULT;
118+
119+
@@ -1022,7 +1023,7 @@ static int sco_sock_getsockopt_old(struct socket *sock, int optname,
120+
cinfo.hci_handle = sco_pi(sk)->conn->hcon->handle;
121+
memcpy(cinfo.dev_class, sco_pi(sk)->conn->hcon->dev_class, 3);
122+
123+
- len = min_t(unsigned int, len, sizeof(cinfo));
124+
+ len = min(len, sizeof(cinfo));
125+
if (copy_to_user(optval, (char *)&cinfo, len))
126+
err = -EFAULT;
127+
128+
--
129+
cgit 1.2.3-korg
130+

0 commit comments

Comments
 (0)