History

lib/string: Move helper functions out of string.c

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.

Kees Cook committed 5 years ago

Commit cfecea61 parent c80d92f7 files · +208 −204Browse files

Showing the changes to lib/string.c (1 of 7 files). Show all

Unified · Split

lib/string.c+6−204
@@ -6,20 +6,15 @@ · 5 unmodified lines
66 */
77
88 /*
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.)
1113 *
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.
2115 */
2216
17+#define __NO_FORTIFY
2318 #include <linux/types.h>
2419 #include <linux/string.h>
2520 #include <linux/ctype.h>
@@ -238,40 +233,6 @@ ssize_t strscpy(char *dest, const char *src, size_t count) · 212 unmodified lines
238233 EXPORT_SYMBOL(strscpy);
239234 #endif
240235
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−
275236 /**
276237 * stpcpy - copy a string from src to dest returning a pointer to the new end
277238 * 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
514475 EXPORT_SYMBOL(strnchr);
515476 #endif
516477
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−
557478 #ifndef __HAVE_ARCH_STRLEN
558479 /**
559480 * strlen - Find the length of a string
@@ -688,101 +609,6 @@ char *strsep(char **s, const char *ct) · 128 unmodified lines
688609 EXPORT_SYMBOL(strsep);
689610 #endif
690611
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−
786612 #ifndef __HAVE_ARCH_MEMSET
787613 /**
788614 * 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
1141967 return check_bytes8(start, value, bytes % 8);
1142968 }
1143969 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);