The core functions of string.c are those that may be implemented by per-architecture functions, or overloaded by FORTIFY_SOURCE. As a result, it needs to be built with __NO_FORTIFY. Without this, macros will collide with function declarations. This was accidentally working due to -ffreestanding (on some architectures). Make this deterministic by explicitly setting __NO_FORTIFY and move all the helper functions into string_helpers.c so that they gain the fortification coverage they had been missing.
Showing the changes to lib/string.c (1 of 7 files). Show all
Unified · Split
| @@ -6,20 +6,15 @@ · 5 unmodified lines | ||
| 6 | 6 | */ |
| 7 | 7 | |
| 8 | 8 | /* |
| 9 | − * stupid library routines.. The optimized versions should generally be found | |
| 10 | − * as inline code in <asm-xx/string.h> | |
| 9 | + * This file should be used only for "library" routines that may have | |
| 10 | + * alternative implementations on specific architectures (generally | |
| 11 | + * found in <asm-xx/string.h>), or get overloaded by FORTIFY_SOURCE. | |
| 12 | + * (Specifically, this file is built with __NO_FORTIFY.) | |
| 11 | 13 | * |
| 12 | − * These are buggy as well.. | |
| 13 | − * | |
| 14 | − * * Fri Jun 25 1999, Ingo Oeser <ioe@informatik.tu-chemnitz.de> | |
| 15 | − * - Added strsep() which will replace strtok() soon (because strsep() is | |
| 16 | − * reentrant and should be faster). Use only strsep() in new code, please. | |
| 17 | − * | |
| 18 | − * * Sat Feb 09 2002, Jason Thomas <jason@topic.com.au>, | |
| 19 | − * Matthew Hawkins <matt@mh.dropbear.id.au> | |
| 20 | − * - Kissed strtok() goodbye | |
| 14 | + * Other helper functions should live in string_helpers.c. | |
| 21 | 15 | */ |
| 22 | 16 | |
| 17 | +#define __NO_FORTIFY | |
| 23 | 18 | #include <linux/types.h> |
| 24 | 19 | #include <linux/string.h> |
| 25 | 20 | #include <linux/ctype.h> |
| @@ -238,40 +233,6 @@ ssize_t strscpy(char *dest, const char *src, size_t count) · 212 unmodified lines | ||
| 238 | 233 | EXPORT_SYMBOL(strscpy); |
| 239 | 234 | #endif |
| 240 | 235 | |
| 241 | −/** | |
| 242 | − * strscpy_pad() - Copy a C-string into a sized buffer | |
| 243 | − * @dest: Where to copy the string to | |
| 244 | − * @src: Where to copy the string from | |
| 245 | − * @count: Size of destination buffer | |
| 246 | − * | |
| 247 | − * Copy the string, or as much of it as fits, into the dest buffer. The | |
| 248 | − * behavior is undefined if the string buffers overlap. The destination | |
| 249 | − * buffer is always %NUL terminated, unless it's zero-sized. | |
| 250 | − * | |
| 251 | − * If the source string is shorter than the destination buffer, zeros | |
| 252 | − * the tail of the destination buffer. | |
| 253 | − * | |
| 254 | − * For full explanation of why you may want to consider using the | |
| 255 | − * 'strscpy' functions please see the function docstring for strscpy(). | |
| 256 | − * | |
| 257 | − * Returns: | |
| 258 | − * * The number of characters copied (not including the trailing %NUL) | |
| 259 | − * * -E2BIG if count is 0 or @src was truncated. | |
| 260 | − */ | |
| 261 | −ssize_t strscpy_pad(char *dest, const char *src, size_t count) | |
| 262 | −{ | |
| 263 | − ssize_t written; | |
| 264 | − | |
| 265 | − written = strscpy(dest, src, count); | |
| 266 | − if (written < 0 || written == count - 1) | |
| 267 | − return written; | |
| 268 | − | |
| 269 | − memset(dest + written + 1, 0, count - written - 1); | |
| 270 | − | |
| 271 | − return written; | |
| 272 | −} | |
| 273 | −EXPORT_SYMBOL(strscpy_pad); | |
| 274 | − | |
| 275 | 236 | /** |
| 276 | 237 | * stpcpy - copy a string from src to dest returning a pointer to the new end |
| 277 | 238 | * of dest, including src's %NUL-terminator. May overrun dest. |
| @@ -514,46 +475,6 @@ char *strnchr(const char *s, size_t count, int c) · 236 unmodified lines | ||
| 514 | 475 | EXPORT_SYMBOL(strnchr); |
| 515 | 476 | #endif |
| 516 | 477 | |
| 517 | −/** | |
| 518 | − * skip_spaces - Removes leading whitespace from @str. | |
| 519 | − * @str: The string to be stripped. | |
| 520 | − * | |
| 521 | − * Returns a pointer to the first non-whitespace character in @str. | |
| 522 | − */ | |
| 523 | −char *skip_spaces(const char *str) | |
| 524 | −{ | |
| 525 | − while (isspace(*str)) | |
| 526 | − ++str; | |
| 527 | − return (char *)str; | |
| 528 | −} | |
| 529 | −EXPORT_SYMBOL(skip_spaces); | |
| 530 | − | |
| 531 | −/** | |
| 532 | − * strim - Removes leading and trailing whitespace from @s. | |
| 533 | − * @s: The string to be stripped. | |
| 534 | − * | |
| 535 | − * Note that the first trailing whitespace is replaced with a %NUL-terminator | |
| 536 | − * in the given string @s. Returns a pointer to the first non-whitespace | |
| 537 | − * character in @s. | |
| 538 | − */ | |
| 539 | −char *strim(char *s) | |
| 540 | −{ | |
| 541 | − size_t size; | |
| 542 | − char *end; | |
| 543 | − | |
| 544 | − size = strlen(s); | |
| 545 | − if (!size) | |
| 546 | − return s; | |
| 547 | − | |
| 548 | − end = s + size - 1; | |
| 549 | − while (end >= s && isspace(*end)) | |
| 550 | − end--; | |
| 551 | − *(end + 1) = '\0'; | |
| 552 | − | |
| 553 | − return skip_spaces(s); | |
| 554 | −} | |
| 555 | −EXPORT_SYMBOL(strim); | |
| 556 | − | |
| 557 | 478 | #ifndef __HAVE_ARCH_STRLEN |
| 558 | 479 | /** |
| 559 | 480 | * strlen - Find the length of a string |
| @@ -688,101 +609,6 @@ char *strsep(char **s, const char *ct) · 128 unmodified lines | ||
| 688 | 609 | EXPORT_SYMBOL(strsep); |
| 689 | 610 | #endif |
| 690 | 611 | |
| 691 | −/** | |
| 692 | − * sysfs_streq - return true if strings are equal, modulo trailing newline | |
| 693 | − * @s1: one string | |
| 694 | − * @s2: another string | |
| 695 | − * | |
| 696 | − * This routine returns true iff two strings are equal, treating both | |
| 697 | − * NUL and newline-then-NUL as equivalent string terminations. It's | |
| 698 | − * geared for use with sysfs input strings, which generally terminate | |
| 699 | − * with newlines but are compared against values without newlines. | |
| 700 | − */ | |
| 701 | −bool sysfs_streq(const char *s1, const char *s2) | |
| 702 | −{ | |
| 703 | − while (*s1 && *s1 == *s2) { | |
| 704 | − s1++; | |
| 705 | − s2++; | |
| 706 | − } | |
| 707 | − | |
| 708 | − if (*s1 == *s2) | |
| 709 | − return true; | |
| 710 | − if (!*s1 && *s2 == '\n' && !s2[1]) | |
| 711 | − return true; | |
| 712 | − if (*s1 == '\n' && !s1[1] && !*s2) | |
| 713 | − return true; | |
| 714 | − return false; | |
| 715 | −} | |
| 716 | −EXPORT_SYMBOL(sysfs_streq); | |
| 717 | − | |
| 718 | −/** | |
| 719 | − * match_string - matches given string in an array | |
| 720 | − * @array: array of strings | |
| 721 | − * @n: number of strings in the array or -1 for NULL terminated arrays | |
| 722 | − * @string: string to match with | |
| 723 | − * | |
| 724 | − * This routine will look for a string in an array of strings up to the | |
| 725 | − * n-th element in the array or until the first NULL element. | |
| 726 | − * | |
| 727 | − * Historically the value of -1 for @n, was used to search in arrays that | |
| 728 | − * are NULL terminated. However, the function does not make a distinction | |
| 729 | − * when finishing the search: either @n elements have been compared OR | |
| 730 | − * the first NULL element was found. | |
| 731 | − * | |
| 732 | − * Return: | |
| 733 | − * index of a @string in the @array if matches, or %-EINVAL otherwise. | |
| 734 | − */ | |
| 735 | −int match_string(const char * const *array, size_t n, const char *string) | |
| 736 | −{ | |
| 737 | − int index; | |
| 738 | − const char *item; | |
| 739 | − | |
| 740 | − for (index = 0; index < n; index++) { | |
| 741 | − item = array[index]; | |
| 742 | − if (!item) | |
| 743 | − break; | |
| 744 | − if (!strcmp(item, string)) | |
| 745 | − return index; | |
| 746 | − } | |
| 747 | − | |
| 748 | − return -EINVAL; | |
| 749 | −} | |
| 750 | −EXPORT_SYMBOL(match_string); | |
| 751 | − | |
| 752 | −/** | |
| 753 | − * __sysfs_match_string - matches given string in an array | |
| 754 | − * @array: array of strings | |
| 755 | − * @n: number of strings in the array or -1 for NULL terminated arrays | |
| 756 | − * @str: string to match with | |
| 757 | − * | |
| 758 | − * Returns index of @str in the @array or -EINVAL, just like match_string(). | |
| 759 | − * Uses sysfs_streq instead of strcmp for matching. | |
| 760 | − * | |
| 761 | − * This routine will look for a string in an array of strings up to the | |
| 762 | − * n-th element in the array or until the first NULL element. | |
| 763 | − * | |
| 764 | − * Historically the value of -1 for @n, was used to search in arrays that | |
| 765 | − * are NULL terminated. However, the function does not make a distinction | |
| 766 | − * when finishing the search: either @n elements have been compared OR | |
| 767 | − * the first NULL element was found. | |
| 768 | − */ | |
| 769 | −int __sysfs_match_string(const char * const *array, size_t n, const char *str) | |
| 770 | −{ | |
| 771 | − const char *item; | |
| 772 | − int index; | |
| 773 | − | |
| 774 | − for (index = 0; index < n; index++) { | |
| 775 | − item = array[index]; | |
| 776 | − if (!item) | |
| 777 | − break; | |
| 778 | − if (sysfs_streq(item, str)) | |
| 779 | − return index; | |
| 780 | − } | |
| 781 | − | |
| 782 | − return -EINVAL; | |
| 783 | −} | |
| 784 | −EXPORT_SYMBOL(__sysfs_match_string); | |
| 785 | − | |
| 786 | 612 | #ifndef __HAVE_ARCH_MEMSET |
| 787 | 613 | /** |
| 788 | 614 | * memset - Fill a region of memory with the given value |
| @@ -1141,27 +967,3 @@ void *memchr_inv(const void *start, int c, size_t bytes) · 352 unmodified lines | ||
| 1141 | 967 | return check_bytes8(start, value, bytes % 8); |
| 1142 | 968 | } |
| 1143 | 969 | EXPORT_SYMBOL(memchr_inv); |
| 1144 | − | |
| 1145 | −/** | |
| 1146 | − * strreplace - Replace all occurrences of character in string. | |
| 1147 | − * @s: The string to operate on. | |
| 1148 | − * @old: The character being replaced. | |
| 1149 | − * @new: The character @old is replaced with. | |
| 1150 | − * | |
| 1151 | − * Returns pointer to the nul byte at the end of @s. | |
| 1152 | − */ | |
| 1153 | −char *strreplace(char *s, char old, char new) | |
| 1154 | −{ | |
| 1155 | − for (; *s; ++s) | |
| 1156 | − if (*s == old) | |
| 1157 | − *s = new; | |
| 1158 | − return s; | |
| 1159 | −} | |
| 1160 | −EXPORT_SYMBOL(strreplace); | |
| 1161 | − | |
| 1162 | −void fortify_panic(const char *name) | |
| 1163 | −{ | |
| 1164 | − pr_emerg("detected buffer overflow in %s\n", name); | |
| 1165 | − BUG(); | |
| 1166 | −} | |
| 1167 | −EXPORT_SYMBOL(fortify_panic); | |