| From 49c05a2fb0e136f5443314969dee908936d640ce Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Tue, 24 May 2022 01:46:22 +0900 |
| Subject: modpost: fix undefined behavior of is_arm_mapping_symbol() |
| |
| From: Masahiro Yamada <masahiroy@kernel.org> |
| |
| [ Upstream commit d6b732666a1bae0df3c3ae06925043bba34502b1 ] |
| |
| The return value of is_arm_mapping_symbol() is unpredictable when "$" |
| is passed in. |
| |
| strchr(3) says: |
| The strchr() and strrchr() functions return a pointer to the matched |
| character or NULL if the character is not found. The terminating null |
| byte is considered part of the string, so that if c is specified as |
| '\0', these functions return a pointer to the terminator. |
| |
| When str[1] is '\0', strchr("axtd", str[1]) is not NULL, and str[2] is |
| referenced (i.e. buffer overrun). |
| |
| Test code |
| --------- |
| |
| char str1[] = "abc"; |
| char str2[] = "ab"; |
| |
| strcpy(str1, "$"); |
| strcpy(str2, "$"); |
| |
| printf("test1: %d\n", is_arm_mapping_symbol(str1)); |
| printf("test2: %d\n", is_arm_mapping_symbol(str2)); |
| |
| Result |
| ------ |
| |
| test1: 0 |
| test2: 1 |
| |
| Signed-off-by: Masahiro Yamada <masahiroy@kernel.org> |
| Reviewed-by: Nick Desaulniers <ndesaulniers@google.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| scripts/mod/modpost.c | 3 ++- |
| 1 file changed, 2 insertions(+), 1 deletion(-) |
| |
| diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c |
| index 29c3e4d6fc06..c5f3267aa08a 100644 |
| --- a/scripts/mod/modpost.c |
| +++ b/scripts/mod/modpost.c |
| @@ -1212,7 +1212,8 @@ static int secref_whitelist(const struct sectioncheck *mismatch, |
| |
| static inline int is_arm_mapping_symbol(const char *str) |
| { |
| - return str[0] == '$' && strchr("axtd", str[1]) |
| + return str[0] == '$' && |
| + (str[1] == 'a' || str[1] == 'd' || str[1] == 't' || str[1] == 'x') |
| && (str[2] == '\0' || str[2] == '.'); |
| } |
| |
| -- |
| 2.35.1 |
| |