@@ -200,17 +200,56 @@ __FORTIFY_INLINE char *strncat(char *p, const char *q, __kernel_size_t count)
200200 return p ;
201201}
202202
203- __FORTIFY_INLINE void * memset (void * p , int c , __kernel_size_t size )
203+ __FORTIFY_INLINE void fortify_memset_chk (__kernel_size_t size ,
204+ const size_t p_size ,
205+ const size_t p_size_field )
204206{
205- size_t p_size = __builtin_object_size (p , 0 );
207+ if (__builtin_constant_p (size )) {
208+ /*
209+ * Length argument is a constant expression, so we
210+ * can perform compile-time bounds checking where
211+ * buffer sizes are known.
212+ */
206213
207- if (__builtin_constant_p (size ) && p_size < size )
208- __write_overflow ();
209- if (p_size < size )
210- fortify_panic (__func__ );
211- return __underlying_memset (p , c , size );
214+ /* Error when size is larger than enclosing struct. */
215+ if (p_size > p_size_field && p_size < size )
216+ __write_overflow ();
217+
218+ /* Warn when write size is larger than dest field. */
219+ if (p_size_field < size )
220+ __write_overflow_field (p_size_field , size );
221+ }
222+ /*
223+ * At this point, length argument may not be a constant expression,
224+ * so run-time bounds checking can be done where buffer sizes are
225+ * known. (This is not an "else" because the above checks may only
226+ * be compile-time warnings, and we want to still warn for run-time
227+ * overflows.)
228+ */
229+
230+ /*
231+ * Always stop accesses beyond the struct that contains the
232+ * field, when the buffer's remaining size is known.
233+ * (The -1 test is to optimize away checks where the buffer
234+ * lengths are unknown.)
235+ */
236+ if (p_size != (size_t )(-1 ) && p_size < size )
237+ fortify_panic ("memset" );
212238}
213239
240+ #define __fortify_memset_chk (p , c , size , p_size , p_size_field ) ({ \
241+ size_t __fortify_size = (size_t)(size); \
242+ fortify_memset_chk(__fortify_size, p_size, p_size_field), \
243+ __underlying_memset(p, c, __fortify_size); \
244+ })
245+
246+ /*
247+ * __builtin_object_size() must be captured here to avoid evaluating argument
248+ * side-effects further into the macro layers.
249+ */
250+ #define memset (p , c , s ) __fortify_memset_chk(p, c, s, \
251+ __builtin_object_size(p, 0), __builtin_object_size(p, 1))
252+
214253/*
215254 * To make sure the compiler can enforce protection against buffer overflows,
216255 * memcpy(), memmove(), and memset() must not be used beyond individual
@@ -401,7 +440,6 @@ __FORTIFY_INLINE char *strcpy(char *p, const char *q)
401440/* Don't use these outside the FORITFY_SOURCE implementation */
402441#undef __underlying_memchr
403442#undef __underlying_memcmp
404- #undef __underlying_memset
405443#undef __underlying_strcat
406444#undef __underlying_strcpy
407445#undef __underlying_strlen
0 commit comments