@@ -10,6 +10,20 @@ void __read_overflow(void) __compiletime_error("detected read beyond size of obj
10
10
void __read_overflow2 (void ) __compiletime_error ("detected read beyond size of object (2nd parameter)" );
11
11
void __write_overflow (void ) __compiletime_error ("detected write beyond size of object (1st parameter)" );
12
12
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
+
13
27
#if defined(CONFIG_KASAN_GENERIC ) || defined(CONFIG_KASAN_SW_TAGS )
14
28
extern void * __underlying_memchr (const void * p , int c , __kernel_size_t size ) __RENAME (memchr );
15
29
extern 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
60
74
__FORTIFY_INLINE __kernel_size_t strnlen (const char * p , __kernel_size_t maxlen )
61
75
{
62
76
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
+ }
64
86
87
+ /* Do not check characters beyond the end of p. */
88
+ ret = __real_strnlen (p , maxlen < p_size ? maxlen : p_size );
65
89
if (p_size <= ret && maxlen != ret )
66
90
fortify_panic (__func__ );
67
91
return ret ;
68
92
}
69
93
94
+ /* defined after fortified strnlen to reuse it. */
70
95
__FORTIFY_INLINE __kernel_size_t strlen (const char * p )
71
96
{
72
97
__kernel_size_t ret ;
73
98
size_t p_size = __builtin_object_size (p , 1 );
74
99
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 )
78
102
return __underlying_strlen (p );
79
103
ret = strnlen (p , p_size );
80
104
if (p_size <= ret )
@@ -86,24 +110,27 @@ __FORTIFY_INLINE __kernel_size_t strlen(const char *p)
86
110
extern size_t __real_strlcpy (char * , const char * , size_t ) __RENAME (strlcpy );
87
111
__FORTIFY_INLINE size_t strlcpy (char * p , const char * q , size_t size )
88
112
{
89
- size_t ret ;
90
113
size_t p_size = __builtin_object_size (p , 1 );
91
114
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. */
92
117
93
118
if (p_size == (size_t )-1 && q_size == (size_t )-1 )
94
119
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 )
100
125
__write_overflow ();
126
+ }
127
+ if (size ) {
101
128
if (len >= p_size )
102
129
fortify_panic (__func__ );
103
130
__underlying_memcpy (p , q , len );
104
131
p [len ] = '\0' ;
105
132
}
106
- return ret ;
133
+ return q_len ;
107
134
}
108
135
109
136
/* defined after fortified strnlen to reuse it */
0 commit comments