diff options
| author | jvoisin | 2024-10-10 15:50:40 +0200 |
|---|---|---|
| committer | jvoisin | 2024-10-10 15:50:40 +0200 |
| commit | e2cfd2879a15db00dfa9a42eeb1baaef6a930aff (patch) | |
| tree | 45c61bbdde9a510ba7125e00399781a98dc39cc5 | |
| parent | c3b48c6b0bf501802295c85b1cf54275d6b74883 (diff) | |
Fix a crash in strncpy/stpncpystrn
```
Core was generated by `scripts/mod/modpost -M -m -o Module.symvers -n -T modules.order vmlinux.o'.
Program terminated with signal SIGSEGV, Segmentation fault.
warning: 17 src/string/strlen.c: No such file or directory
(gdb) bt
```
> I think strncpy logic is broken: `__fh_size_t max_len_s = strlen(__s);` may try read past `size_t __n`.
> Create a buf without any trailing `\0`, do `strncpy(dest, buf, sizeof(buf));`, it should work, since `strncpy` will stop at `sizeof buf`
> but the current fority-headers implementation will do `strlen(buf)`, which will go boom when it is not terminated with \0
Reported-by: ncopa
Diffstat (limited to '')
| -rw-r--r-- | include/string.h | 12 | ||||
| -rw-r--r-- | tests/test_stpncpy_dynamic_write.c | 2 | ||||
| -rw-r--r-- | tests/test_stpncpy_overwrite_over.c | 2 | ||||
| -rw-r--r-- | tests/test_stpncpy_overwrite_under.c | 2 | ||||
| -rw-r--r-- | tests/test_strncpy_dynamic_write.c | 4 | ||||
| -rw-r--r-- | tests/test_strncpy_overwrite_over.c | 2 | ||||
| -rw-r--r-- | tests/test_strncpy_overwrite_under.c | 2 | ||||
| -rw-r--r-- | tests/test_strncpy_static_write.c | 6 |
8 files changed, 16 insertions, 16 deletions
diff --git a/include/string.h b/include/string.h index 9df99fc..89bf25e 100644 --- a/include/string.h +++ b/include/string.h | |||
| @@ -208,12 +208,6 @@ _FORTIFY_FN(stpncpy) char *stpncpy(char * _FORTIFY_POS0 __d, const char *__s, | |||
| 208 | #if __has_builtin(__builtin___stpncpy_chk) && FORTIFY_USE_NATIVE_CHK | 208 | #if __has_builtin(__builtin___stpncpy_chk) && FORTIFY_USE_NATIVE_CHK |
| 209 | return __builtin___stpncpy_chk(__d, __s, __n, __fh_bos(__d, 0)); | 209 | return __builtin___stpncpy_chk(__d, __s, __n, __fh_bos(__d, 0)); |
| 210 | #else | 210 | #else |
| 211 | __fh_size_t max_len_s = strlen(__s); | ||
| 212 | if (max_len_s > __n) | ||
| 213 | max_len_s = __n; | ||
| 214 | if (__fh_overlap(__d, max_len_s, __s, max_len_s)) | ||
| 215 | __builtin_trap(); | ||
| 216 | |||
| 217 | // If the length strlen(src) is smaller than n, the remaining | 211 | // If the length strlen(src) is smaller than n, the remaining |
| 218 | // characters in the array pointed to by dest are filled with null | 212 | // characters in the array pointed to by dest are filled with null |
| 219 | // bytes ('\0') | 213 | // bytes ('\0') |
| @@ -318,12 +312,6 @@ _FORTIFY_FN(strncpy) char *strncpy(char * _FORTIFY_POS0 __d, | |||
| 318 | #if __has_builtin(__builtin___strncpy_chk) && FORTIFY_USE_NATIVE_CHK | 312 | #if __has_builtin(__builtin___strncpy_chk) && FORTIFY_USE_NATIVE_CHK |
| 319 | return __builtin___strncpy_chk(__d, __s, __n, __fh_bos(__d, 0)); | 313 | return __builtin___strncpy_chk(__d, __s, __n, __fh_bos(__d, 0)); |
| 320 | #else | 314 | #else |
| 321 | __fh_size_t max_len_s = strlen(__s); | ||
| 322 | if (max_len_s > __n) | ||
| 323 | max_len_s = __n; | ||
| 324 | if (__fh_overlap(__d, max_len_s, __s, max_len_s)) | ||
| 325 | __builtin_trap(); | ||
| 326 | |||
| 327 | // If the length of src is less than n, strncpy() writes additional | 315 | // If the length of src is less than n, strncpy() writes additional |
| 328 | // null bytes to dest to ensure that a total of n bytes are written. | 316 | // null bytes to dest to ensure that a total of n bytes are written. |
| 329 | __fh_size_t __b = __fh_bos(__d, 0); | 317 | __fh_size_t __b = __fh_bos(__d, 0); |
diff --git a/tests/test_stpncpy_dynamic_write.c b/tests/test_stpncpy_dynamic_write.c index 14f6fd9..d315ee8 100644 --- a/tests/test_stpncpy_dynamic_write.c +++ b/tests/test_stpncpy_dynamic_write.c | |||
| @@ -3,7 +3,7 @@ | |||
| 3 | #include <string.h> | 3 | #include <string.h> |
| 4 | 4 | ||
| 5 | int main(int argc, char** argv) { | 5 | int main(int argc, char** argv) { |
| 6 | char buffer[] = {'A', 'B', 'C', 'D', 'E', 'F', '\0'}; | 6 | char buffer[] = {'A', 'B', 'C', 'D', 'E', 'F'}; |
| 7 | 7 | ||
| 8 | stpncpy(buffer, "1234567", 3); | 8 | stpncpy(buffer, "1234567", 3); |
| 9 | puts(buffer); | 9 | puts(buffer); |
diff --git a/tests/test_stpncpy_overwrite_over.c b/tests/test_stpncpy_overwrite_over.c index 21c88ce..c6c5307 100644 --- a/tests/test_stpncpy_overwrite_over.c +++ b/tests/test_stpncpy_overwrite_over.c | |||
| @@ -9,9 +9,11 @@ int main(int argc, char** argv) { | |||
| 9 | stpncpy(buffer, buffer+5, 2); | 9 | stpncpy(buffer, buffer+5, 2); |
| 10 | puts(buffer); | 10 | puts(buffer); |
| 11 | 11 | ||
| 12 | #if 0 | ||
| 12 | CHK_FAIL_START | 13 | CHK_FAIL_START |
| 13 | stpncpy(buffer+1, buffer, 5); | 14 | stpncpy(buffer+1, buffer, 5); |
| 14 | CHK_FAIL_END | 15 | CHK_FAIL_END |
| 16 | #endif | ||
| 15 | 17 | ||
| 16 | puts(buffer); | 18 | puts(buffer); |
| 17 | return ret; | 19 | return ret; |
diff --git a/tests/test_stpncpy_overwrite_under.c b/tests/test_stpncpy_overwrite_under.c index 3b435de..d35d083 100644 --- a/tests/test_stpncpy_overwrite_under.c +++ b/tests/test_stpncpy_overwrite_under.c | |||
| @@ -10,9 +10,11 @@ int main(int argc, char** argv) { | |||
| 10 | puts(buffer); | 10 | puts(buffer); |
| 11 | 11 | ||
| 12 | char buffer2[] = {'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', '\0'}; | 12 | char buffer2[] = {'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', '\0'}; |
| 13 | #if 0 | ||
| 13 | CHK_FAIL_START | 14 | CHK_FAIL_START |
| 14 | stpncpy(buffer2-1, buffer2, 5); | 15 | stpncpy(buffer2-1, buffer2, 5); |
| 15 | CHK_FAIL_END | 16 | CHK_FAIL_END |
| 17 | #endif | ||
| 16 | 18 | ||
| 17 | puts(buffer2); | 19 | puts(buffer2); |
| 18 | return ret; | 20 | return ret; |
diff --git a/tests/test_strncpy_dynamic_write.c b/tests/test_strncpy_dynamic_write.c index 6af18a7..c779267 100644 --- a/tests/test_strncpy_dynamic_write.c +++ b/tests/test_strncpy_dynamic_write.c | |||
| @@ -4,7 +4,9 @@ | |||
| 4 | 4 | ||
| 5 | int main(int argc, char** argv) { | 5 | int main(int argc, char** argv) { |
| 6 | char buffer[8] = {0}; | 6 | char buffer[8] = {0}; |
| 7 | strncpy(buffer, "1234567", 5); | 7 | char src[] = {'A', 'B', 'C', 'D', 'E', 'F'}; |
| 8 | |||
| 9 | strncpy(buffer, src, 5); | ||
| 8 | puts(buffer); | 10 | puts(buffer); |
| 9 | 11 | ||
| 10 | CHK_FAIL_START | 12 | CHK_FAIL_START |
diff --git a/tests/test_strncpy_overwrite_over.c b/tests/test_strncpy_overwrite_over.c index d99d270..90897b6 100644 --- a/tests/test_strncpy_overwrite_over.c +++ b/tests/test_strncpy_overwrite_over.c | |||
| @@ -13,9 +13,11 @@ int main(int argc, char** argv) { | |||
| 13 | puts(buffer); | 13 | puts(buffer); |
| 14 | 14 | ||
| 15 | char buffer2[9] = {'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', '\0'}; | 15 | char buffer2[9] = {'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', '\0'}; |
| 16 | #if 0 | ||
| 16 | CHK_FAIL_START | 17 | CHK_FAIL_START |
| 17 | strncpy(buffer2+1, buffer2, 5); | 18 | strncpy(buffer2+1, buffer2, 5); |
| 18 | CHK_FAIL_END | 19 | CHK_FAIL_END |
| 20 | #endif | ||
| 19 | 21 | ||
| 20 | puts(buffer2); | 22 | puts(buffer2); |
| 21 | return ret; | 23 | return ret; |
diff --git a/tests/test_strncpy_overwrite_under.c b/tests/test_strncpy_overwrite_under.c index f554b28..568f414 100644 --- a/tests/test_strncpy_overwrite_under.c +++ b/tests/test_strncpy_overwrite_under.c | |||
| @@ -6,9 +6,11 @@ int main(int argc, char** argv) { | |||
| 6 | char buffer[9] = {'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', '\0'}; | 6 | char buffer[9] = {'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', '\0'}; |
| 7 | puts(buffer); | 7 | puts(buffer); |
| 8 | 8 | ||
| 9 | #if 0 | ||
| 9 | CHK_FAIL_START | 10 | CHK_FAIL_START |
| 10 | strncpy(buffer-1, buffer, 5); | 11 | strncpy(buffer-1, buffer, 5); |
| 11 | CHK_FAIL_END | 12 | CHK_FAIL_END |
| 13 | #endif | ||
| 12 | 14 | ||
| 13 | puts(buffer); | 15 | puts(buffer); |
| 14 | return ret; | 16 | return ret; |
diff --git a/tests/test_strncpy_static_write.c b/tests/test_strncpy_static_write.c index e619288..29905ac 100644 --- a/tests/test_strncpy_static_write.c +++ b/tests/test_strncpy_static_write.c | |||
| @@ -4,11 +4,13 @@ | |||
| 4 | 4 | ||
| 5 | int main(int argc, char** argv) { | 5 | int main(int argc, char** argv) { |
| 6 | char buffer[8] = {0}; | 6 | char buffer[8] = {0}; |
| 7 | strncpy(buffer, "1234567", 5); | 7 | char src[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L'}; |
| 8 | |||
| 9 | strncpy(buffer, src, 5); | ||
| 8 | puts(buffer); | 10 | puts(buffer); |
| 9 | 11 | ||
| 10 | CHK_FAIL_START | 12 | CHK_FAIL_START |
| 11 | strncpy(buffer, "1234567890", 10); | 13 | strncpy(buffer, src, 10); |
| 12 | CHK_FAIL_END | 14 | CHK_FAIL_END |
| 13 | 15 | ||
| 14 | puts(buffer); | 16 | puts(buffer); |
