Source
// SPDX-License-Identifier: GPL-2.0
/* Set bits in the first 'n' bytes when loaded from memory */
/*
* Do a strnlen, return length of string *with* final '\0'.
* 'count' is the user-supplied count, while 'max' is the
* address space maximum.
*
* Return 0 for exceptions (which includes hitting the address
* space maximum), or 'count+1' if hitting the user-supplied
* maximum count.
*
* NOTE! We can sometimes overshoot the user-supplied maximum
* if it fits in a aligned 'long'. The caller needs to check
* the return value against "> max".
*/
static inline long do_strnlen_user(const char __user *src, unsigned long count, unsigned long max)
{
const struct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS;
long align, res = 0;
unsigned long c;
/*
* Truncate 'max' to the user-specified limit, so that
* we only have one limit we need to check in the loop
*/
if (max > count)
max = count;
/*
* Do everything aligned. But that means that we
* need to also expand the maximum..
*/
align = (sizeof(long) - 1) & (unsigned long)src;
src -= align;
max += align;
unsafe_get_user(c, (unsigned long __user *)src, efault);
c |= aligned_byte_mask(align);
for (;;) {
unsigned long data;
if (has_zero(c, &data, &constants)) {
data = prep_zero_mask(c, data, &constants);
data = create_zero_mask(data);
return res + find_zero(data) + 1 - align;
}
res += sizeof(unsigned long);
/* We already handled 'unsigned long' bytes. Did we do it all ? */
if (unlikely(max <= sizeof(unsigned long)))
break;
max -= sizeof(unsigned long);