@@ -10,6 +10,20 @@ void __read_overflow(void) __compiletime_error("detected read beyond size of obj
1010void __read_overflow2 (void ) __compiletime_error ("detected read beyond size of object (2nd parameter)" );
1111void __write_overflow (void ) __compiletime_error ("detected write beyond size of object (1st parameter)" );
1212
13+ #define __compiletime_strlen (p ) \
14+ ({ \
15+ unsigned char *__p = (unsigned char *)(p); \
16+ size_t ret = (size_t)-1; \
17+ size_t p_size = __builtin_object_size(p, 1); \
18+ if (p_size != (size_t)-1) { \
19+ size_t p_len = p_size - 1; \
20+ if (__builtin_constant_p(__p[p_len]) && \
21+ __p[p_len] == '\0') \
22+ ret = __builtin_strlen(__p); \
23+ } \
24+ ret; \
25+ })
26+
1327#if defined(CONFIG_KASAN_GENERIC ) || defined(CONFIG_KASAN_SW_TAGS )
1428extern void * __underlying_memchr (const void * p , int c , __kernel_size_t size ) __RENAME (memchr );
1529extern int __underlying_memcmp (const void * p , const void * q , __kernel_size_t size ) __RENAME (memcmp );
@@ -60,21 +74,31 @@ extern __kernel_size_t __real_strnlen(const char *, __kernel_size_t) __RENAME(st
6074__FORTIFY_INLINE __kernel_size_t strnlen (const char * p , __kernel_size_t maxlen )
6175{
6276 size_t p_size = __builtin_object_size (p , 1 );
63- __kernel_size_t ret = __real_strnlen (p , maxlen < p_size ? maxlen : p_size );
77+ size_t p_len = __compiletime_strlen (p );
78+ size_t ret ;
79+
80+ /* We can take compile-time actions when maxlen is const. */
81+ if (__builtin_constant_p (maxlen ) && p_len != (size_t )-1 ) {
82+ /* If p is const, we can use its compile-time-known len. */
83+ if (maxlen >= p_size )
84+ return p_len ;
85+ }
6486
87+ /* Do not check characters beyond the end of p. */
88+ ret = __real_strnlen (p , maxlen < p_size ? maxlen : p_size );
6589 if (p_size <= ret && maxlen != ret )
6690 fortify_panic (__func__ );
6791 return ret ;
6892}
6993
94+ /* defined after fortified strnlen to reuse it. */
7095__FORTIFY_INLINE __kernel_size_t strlen (const char * p )
7196{
7297 __kernel_size_t ret ;
7398 size_t p_size = __builtin_object_size (p , 1 );
7499
75- /* Work around gcc excess stack consumption issue */
76- if (p_size == (size_t )-1 ||
77- (__builtin_constant_p (p [p_size - 1 ]) && p [p_size - 1 ] == '\0' ))
100+ /* Give up if we don't know how large p is. */
101+ if (p_size == (size_t )-1 )
78102 return __underlying_strlen (p );
79103 ret = strnlen (p , p_size );
80104 if (p_size <= ret )
@@ -86,24 +110,27 @@ __FORTIFY_INLINE __kernel_size_t strlen(const char *p)
86110extern size_t __real_strlcpy (char * , const char * , size_t ) __RENAME (strlcpy );
87111__FORTIFY_INLINE size_t strlcpy (char * p , const char * q , size_t size )
88112{
89- size_t ret ;
90113 size_t p_size = __builtin_object_size (p , 1 );
91114 size_t q_size = __builtin_object_size (q , 1 );
115+ size_t q_len ; /* Full count of source string length. */
116+ size_t len ; /* Count of characters going into destination. */
92117
93118 if (p_size == (size_t )-1 && q_size == (size_t )-1 )
94119 return __real_strlcpy (p , q , size );
95- ret = strlen (q );
96- if ( size ) {
97- size_t len = ( ret >= size ) ? size - 1 : ret ;
98-
99- if (__builtin_constant_p ( len ) && len >= p_size )
120+ q_len = strlen (q );
121+ len = ( q_len >= size ) ? size - 1 : q_len ;
122+ if ( __builtin_constant_p ( size ) && __builtin_constant_p ( q_len ) && size ) {
123+ /* Write size is always larger than destination. */
124+ if (len >= p_size )
100125 __write_overflow ();
126+ }
127+ if (size ) {
101128 if (len >= p_size )
102129 fortify_panic (__func__ );
103130 __underlying_memcpy (p , q , len );
104131 p [len ] = '\0' ;
105132 }
106- return ret ;
133+ return q_len ;
107134}
108135
109136/* defined after fortified strnlen to reuse it */
0 commit comments