Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
patches: Add workaround for cma.c issue in stable
Signed-off-by: Nathan Chancellor <nathan@kernel.org>
- Loading branch information
1 parent
354a8f6
commit fedee2e
Showing
4 changed files
with
164 additions
and
0 deletions.
There are no files selected for viewing
81 changes: 81 additions & 0 deletions
81
...20230208_keescook_rdma_cma_distinguish_between_sockaddr_in_and_sockaddr_in6_by_size.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
From git@z Thu Jan 1 00:00:00 1970 | ||
Subject: [PATCH] RDMA/cma: Distinguish between sockaddr_in and sockaddr_in6 | ||
by size | ||
From: Kees Cook <keescook@chromium.org> | ||
Date: Wed, 08 Feb 2023 15:25:53 -0800 | ||
Message-Id: <20230208232549.never.139-kees@kernel.org> | ||
MIME-Version: 1.0 | ||
Content-Type: text/plain; charset="utf-8" | ||
Content-Transfer-Encoding: 7bit | ||
|
||
Clang can do some aggressive inlining, which provides it with greater | ||
visibility into the sizes of various objects that are passed into | ||
helpers. Specifically, compare_netdev_and_ip() can see through the type | ||
given to the "sa" argument, which means it can generate code for "struct | ||
sockaddr_in" that would have been passed to ipv6_addr_cmp() (that expects | ||
to operate on the larger "struct sockaddr_in6"), which would result in a | ||
compile-time buffer overflow condition detected by memcmp(). Logically, | ||
this state isn't reachable due to the sa_family assignment two callers | ||
above and the check in compare_netdev_and_ip(). Instead, provide a | ||
compile-time check on sizes so the size-mismatched code will be elided | ||
when inlining. Avoids the following warning from Clang: | ||
|
||
../include/linux/fortify-string.h:652:4: error: call to '__read_overflow' declared with 'error' attribute: detected read beyond size of object (1st parameter) | ||
__read_overflow(); | ||
^ | ||
note: In function 'cma_netevent_callback' | ||
note: which inlined function 'node_from_ndev_ip' | ||
1 error generated. | ||
|
||
When the underlying object size is not known (e.g. with GCC and older | ||
Clang), the result of __builtin_object_size() is SIZE_MAX, which | ||
will also compile away, leaving the code as it was originally. | ||
|
||
Link: https://github.com/ClangBuiltLinux/linux/issues/1687 | ||
Cc: Jason Gunthorpe <jgg@ziepe.ca> | ||
Cc: Leon Romanovsky <leon@kernel.org> | ||
Cc: Mark Zhang <markzhang@nvidia.com> | ||
Cc: Patrisious Haddad <phaddad@nvidia.com> | ||
Cc: Nathan Chancellor <nathan@kernel.org> | ||
Cc: Nick Desaulniers <ndesaulniers@google.com> | ||
Cc: linux-rdma@vger.kernel.org | ||
Cc: llvm@lists.linux.dev | ||
Signed-off-by: Kees Cook <keescook@chromium.org> | ||
Link: https://lore.kernel.org/r/20230208232549.never.139-kees@kernel.org | ||
--- | ||
drivers/infiniband/core/cma.c | 17 ++++++++++++----- | ||
1 file changed, 12 insertions(+), 5 deletions(-) | ||
|
||
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c | ||
index 1d2bff91d78b..308155937713 100644 | ||
--- a/drivers/infiniband/core/cma.c | ||
+++ b/drivers/infiniband/core/cma.c | ||
@@ -479,13 +479,20 @@ static int compare_netdev_and_ip(int ifindex_a, struct sockaddr *sa, | ||
if (sa->sa_family != sb->sa_family) | ||
return sa->sa_family - sb->sa_family; | ||
|
||
- if (sa->sa_family == AF_INET) | ||
- return memcmp((char *)&((struct sockaddr_in *)sa)->sin_addr, | ||
- (char *)&((struct sockaddr_in *)sb)->sin_addr, | ||
+ if (sa->sa_family == AF_INET && | ||
+ __builtin_object_size(sa, 0) >= sizeof(struct sockaddr_in)) { | ||
+ return memcmp(&((struct sockaddr_in *)sa)->sin_addr, | ||
+ &((struct sockaddr_in *)sb)->sin_addr, | ||
sizeof(((struct sockaddr_in *)sa)->sin_addr)); | ||
+ } | ||
+ | ||
+ if (sa->sa_family == AF_INET6 && | ||
+ __builtin_object_size(sa, 0) >= sizeof(struct sockaddr_in6)) { | ||
+ return ipv6_addr_cmp(&((struct sockaddr_in6 *)sa)->sin6_addr, | ||
+ &((struct sockaddr_in6 *)sb)->sin6_addr); | ||
+ } | ||
|
||
- return ipv6_addr_cmp(&((struct sockaddr_in6 *)sa)->sin6_addr, | ||
- &((struct sockaddr_in6 *)sb)->sin6_addr); | ||
+ return -1; | ||
} | ||
|
||
static int cma_add_id_to_tree(struct rdma_id_private *node_id_priv) | ||
-- | ||
2.34.1 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
0001-x86-alternatives-Introduce-int3_emulate_jcc.patch | ||
0002-x86-alternatives-Teach-text_poke_bp-to-patch-Jcc.d32.patch | ||
0003-x86-static_call-Add-support-for-Jcc-tail-calls.patch | ||
20230208_keescook_rdma_cma_distinguish_between_sockaddr_in_and_sockaddr_in6_by_size.patch |
81 changes: 81 additions & 0 deletions
81
...20230208_keescook_rdma_cma_distinguish_between_sockaddr_in_and_sockaddr_in6_by_size.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
From git@z Thu Jan 1 00:00:00 1970 | ||
Subject: [PATCH] RDMA/cma: Distinguish between sockaddr_in and sockaddr_in6 | ||
by size | ||
From: Kees Cook <keescook@chromium.org> | ||
Date: Wed, 08 Feb 2023 15:25:53 -0800 | ||
Message-Id: <20230208232549.never.139-kees@kernel.org> | ||
MIME-Version: 1.0 | ||
Content-Type: text/plain; charset="utf-8" | ||
Content-Transfer-Encoding: 7bit | ||
|
||
Clang can do some aggressive inlining, which provides it with greater | ||
visibility into the sizes of various objects that are passed into | ||
helpers. Specifically, compare_netdev_and_ip() can see through the type | ||
given to the "sa" argument, which means it can generate code for "struct | ||
sockaddr_in" that would have been passed to ipv6_addr_cmp() (that expects | ||
to operate on the larger "struct sockaddr_in6"), which would result in a | ||
compile-time buffer overflow condition detected by memcmp(). Logically, | ||
this state isn't reachable due to the sa_family assignment two callers | ||
above and the check in compare_netdev_and_ip(). Instead, provide a | ||
compile-time check on sizes so the size-mismatched code will be elided | ||
when inlining. Avoids the following warning from Clang: | ||
|
||
../include/linux/fortify-string.h:652:4: error: call to '__read_overflow' declared with 'error' attribute: detected read beyond size of object (1st parameter) | ||
__read_overflow(); | ||
^ | ||
note: In function 'cma_netevent_callback' | ||
note: which inlined function 'node_from_ndev_ip' | ||
1 error generated. | ||
|
||
When the underlying object size is not known (e.g. with GCC and older | ||
Clang), the result of __builtin_object_size() is SIZE_MAX, which | ||
will also compile away, leaving the code as it was originally. | ||
|
||
Link: https://github.com/ClangBuiltLinux/linux/issues/1687 | ||
Cc: Jason Gunthorpe <jgg@ziepe.ca> | ||
Cc: Leon Romanovsky <leon@kernel.org> | ||
Cc: Mark Zhang <markzhang@nvidia.com> | ||
Cc: Patrisious Haddad <phaddad@nvidia.com> | ||
Cc: Nathan Chancellor <nathan@kernel.org> | ||
Cc: Nick Desaulniers <ndesaulniers@google.com> | ||
Cc: linux-rdma@vger.kernel.org | ||
Cc: llvm@lists.linux.dev | ||
Signed-off-by: Kees Cook <keescook@chromium.org> | ||
Link: https://lore.kernel.org/r/20230208232549.never.139-kees@kernel.org | ||
--- | ||
drivers/infiniband/core/cma.c | 17 ++++++++++++----- | ||
1 file changed, 12 insertions(+), 5 deletions(-) | ||
|
||
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c | ||
index 1d2bff91d78b..308155937713 100644 | ||
--- a/drivers/infiniband/core/cma.c | ||
+++ b/drivers/infiniband/core/cma.c | ||
@@ -479,13 +479,20 @@ static int compare_netdev_and_ip(int ifindex_a, struct sockaddr *sa, | ||
if (sa->sa_family != sb->sa_family) | ||
return sa->sa_family - sb->sa_family; | ||
|
||
- if (sa->sa_family == AF_INET) | ||
- return memcmp((char *)&((struct sockaddr_in *)sa)->sin_addr, | ||
- (char *)&((struct sockaddr_in *)sb)->sin_addr, | ||
+ if (sa->sa_family == AF_INET && | ||
+ __builtin_object_size(sa, 0) >= sizeof(struct sockaddr_in)) { | ||
+ return memcmp(&((struct sockaddr_in *)sa)->sin_addr, | ||
+ &((struct sockaddr_in *)sb)->sin_addr, | ||
sizeof(((struct sockaddr_in *)sa)->sin_addr)); | ||
+ } | ||
+ | ||
+ if (sa->sa_family == AF_INET6 && | ||
+ __builtin_object_size(sa, 0) >= sizeof(struct sockaddr_in6)) { | ||
+ return ipv6_addr_cmp(&((struct sockaddr_in6 *)sa)->sin6_addr, | ||
+ &((struct sockaddr_in6 *)sb)->sin6_addr); | ||
+ } | ||
|
||
- return ipv6_addr_cmp(&((struct sockaddr_in6 *)sa)->sin6_addr, | ||
- &((struct sockaddr_in6 *)sb)->sin6_addr); | ||
+ return -1; | ||
} | ||
|
||
static int cma_add_id_to_tree(struct rdma_id_private *node_id_priv) | ||
-- | ||
2.34.1 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
0001-x86-alternatives-Introduce-int3_emulate_jcc.patch | ||
0002-x86-alternatives-Teach-text_poke_bp-to-patch-Jcc.d32.patch | ||
0003-x86-static_call-Add-support-for-Jcc-tail-calls.patch | ||
20230208_keescook_rdma_cma_distinguish_between_sockaddr_in_and_sockaddr_in6_by_size.patch |