History

bpf: Remove dynptr check in check_stack_range_initialized()

For a MEM_UNINIT ("raw mode") helper argument, check_stack_range_initialized() open-coded a scan that rejected any STACK_DYNPTR slot in the range with "potential write to dynptr". This duplicated, and was stricter than, the handling that runs when the buffer is actually marked initialized. check_helper_call() later replays the write byte by byte via check_mem_access(), which goes through destroy_if_dynptr_stack_slot(), which rejects overwritting a referenced dynptr. Therefore drop the redundant scan and rely on check_mem_access().

Amery Hung committed 4 months ago

Commit c28cbef1 parent f68df522 files · +2 −27Browse files

Showing the changes to kernel (1 of 2 files). Show all

Unified · Split

kernel/bpf/verifier.c+0−25
@@ -6733,31 +6733,6 @@ static int check_stack_range_initialized( · 6732 unmodified lines
6733 }6733 }
6734 6734
6735 if (meta && meta->raw_mode) {6735 if (meta && meta->raw_mode) {
6736 /* Ensure we won't be overwriting dynptrs when simulating byte
6737 * by byte access in check_helper_call using meta.access_size.
6738 * This would be a problem if we have a helper in the future
6739 * which takes:
6740 *
6741 * helper(uninit_mem, len, dynptr)
6742 *
6743 * Now, uninint_mem may overlap with dynptr pointer. Hence, it
6744 * may end up writing to dynptr itself when touching memory from
6745 * arg 1. This can be relaxed on a case by case basis for known
6746 * safe cases, but reject due to the possibilitiy of aliasing by
6747 * default.
6748 */
6749 for (i = min_off; i < max_off + access_size; i++) {
6750 int stack_off = -i - 1;
6751
6752 spi = bpf_get_spi(i);
6753 /* raw_mode may write past allocated_stack */
6754 if (state->allocated_stack <= stack_off)
6755 continue;
6756 if (state->stack[spi].slot_type[stack_off % BPF_REG_SIZE] == STACK_DYNPTR) {
6757 verbose(env, "potential write to dynptr at off=%d disallowed\n", i);
6758 return -EACCES;
6759 }
6760 }
6761 meta->access_size = access_size;6736 meta->access_size = access_size;
6762 meta->regno = reg_from_argno(argno);6737 meta->regno = reg_from_argno(argno);
6763 return 0;6738 return 0;