/* * Do a strncpy, return length of string without final '\0'. * 'count' is the user-supplied count (return 'count' if we * hit it), 'max' is the address space maximum (and we return * -EFAULT if we hit it).
*/ static __always_inline long do_strncpy_from_user(char *dst, constchar __user *src, unsignedlong count, unsignedlong max)
{ conststruct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS; unsignedlong res = 0;
if (IS_UNALIGNED(src, dst)) goto byte_at_a_time;
while (max >= sizeof(unsignedlong)) { unsignedlong c, data, mask;
/* Fall back to byte-at-a-time if we get a page fault */
unsafe_get_user(c, (unsignedlong __user *)(src+res), byte_at_a_time);
/* * Note that we mask out the bytes following the NUL. This is * important to do because string oblivious code may read past * the NUL. For those routines, we don't want to give them * potentially random bytes after the NUL in `src`. * * One example of such code is BPF map keys. BPF treats map keys * as an opaque set of bytes. Without the post-NUL mask, any BPF * maps keyed by strings returned from strncpy_from_user() may * have multiple entries for semantically identical strings.
*/ if (has_zero(c, &data, &constants)) {
data = prep_zero_mask(c, data, &constants);
data = create_zero_mask(data);
mask = zero_bytemask(data);
*(unsignedlong *)(dst+res) = c & mask; return res + find_zero(data);
}
*(unsignedlong *)(dst+res) = c;
res += sizeof(unsignedlong);
max -= sizeof(unsignedlong);
}
/* * Uhhuh. We hit 'max'. But was that the user-specified maximum * too? If so, that's ok - we got as much as the user asked for.
*/ if (res >= count) return res;
/* * Nope: we hit the address space limit, and we still had more * characters the caller would have wanted. That's an EFAULT.
*/
efault: return -EFAULT;
}
/** * strncpy_from_user: - Copy a NUL terminated string from userspace. * @dst: Destination address, in kernel space. This buffer must be at * least @count bytes long. * @src: Source address, in user space. * @count: Maximum number of bytes to copy, including the trailing NUL. * * Copies a NUL-terminated string from userspace to kernel space. * * On success, returns the length of the string (not including the trailing * NUL). * * If access to userspace fails, returns -EFAULT (some data may have been * copied). * * If @count is smaller than the length of the string, copies @count bytes * and returns @count.
*/ long strncpy_from_user(char *dst, constchar __user *src, long count)
{ unsignedlong max_addr, src_addr;
might_fault(); if (should_fail_usercopy()) return -EFAULT; if (unlikely(count <= 0)) return 0;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.