@@ -1009,19 +1009,6 @@ static int check_stack_write(struct bpf_verifier_env *env,
10091009 cur = env -> cur_state -> frame [env -> cur_state -> curframe ];
10101010 if (value_regno >= 0 )
10111011 reg = & cur -> regs [value_regno ];
1012- if (!env -> allow_ptr_leaks ) {
1013- bool sanitize = reg && is_spillable_regtype (reg -> type );
1014-
1015- for (i = 0 ; i < size ; i ++ ) {
1016- if (state -> stack [spi ].slot_type [i ] == STACK_INVALID ) {
1017- sanitize = true;
1018- break ;
1019- }
1020- }
1021-
1022- if (sanitize )
1023- env -> insn_aux_data [insn_idx ].sanitize_stack_spill = true;
1024- }
10251012
10261013 if (reg && size == BPF_REG_SIZE && register_is_const (reg ) &&
10271014 !register_is_null (reg ) && env -> allow_ptr_leaks ) {
@@ -1032,10 +1019,47 @@ static int check_stack_write(struct bpf_verifier_env *env,
10321019 verbose (env , "invalid size of register spill\n" );
10331020 return - EACCES ;
10341021 }
1022+
10351023 if (state != cur && reg -> type == PTR_TO_STACK ) {
10361024 verbose (env , "cannot spill pointers to stack into stack frame of the caller\n" );
10371025 return - EINVAL ;
10381026 }
1027+
1028+ if (!env -> allow_ptr_leaks ) {
1029+ bool sanitize = false;
1030+
1031+ if (state -> stack [spi ].slot_type [0 ] == STACK_SPILL &&
1032+ register_is_const (& state -> stack [spi ].spilled_ptr ))
1033+ sanitize = true;
1034+ for (i = 0 ; i < BPF_REG_SIZE ; i ++ )
1035+ if (state -> stack [spi ].slot_type [i ] == STACK_MISC ) {
1036+ sanitize = true;
1037+ break ;
1038+ }
1039+ if (sanitize ) {
1040+ int * poff = & env -> insn_aux_data [insn_idx ].sanitize_stack_off ;
1041+ int soff = (- spi - 1 ) * BPF_REG_SIZE ;
1042+
1043+ /* detected reuse of integer stack slot with a pointer
1044+ * which means either llvm is reusing stack slot or
1045+ * an attacker is trying to exploit CVE-2018-3639
1046+ * (speculative store bypass)
1047+ * Have to sanitize that slot with preemptive
1048+ * store of zero.
1049+ */
1050+ if (* poff && * poff != soff ) {
1051+ /* disallow programs where single insn stores
1052+ * into two different stack slots, since verifier
1053+ * cannot sanitize them
1054+ */
1055+ verbose (env ,
1056+ "insn %d cannot access two stack slots fp%d and fp%d" ,
1057+ insn_idx , * poff , soff );
1058+ return - EINVAL ;
1059+ }
1060+ * poff = soff ;
1061+ }
1062+ }
10391063 save_register_state (state , spi , reg );
10401064 } else {
10411065 u8 type = STACK_MISC ;
@@ -5808,33 +5832,34 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env)
58085832 insn = env -> prog -> insnsi + delta ;
58095833
58105834 for (i = 0 ; i < insn_cnt ; i ++ , insn ++ ) {
5811- bool ctx_access ;
5812-
58135835 if (insn -> code == (BPF_LDX | BPF_MEM | BPF_B ) ||
58145836 insn -> code == (BPF_LDX | BPF_MEM | BPF_H ) ||
58155837 insn -> code == (BPF_LDX | BPF_MEM | BPF_W ) ||
5816- insn -> code == (BPF_LDX | BPF_MEM | BPF_DW )) {
5838+ insn -> code == (BPF_LDX | BPF_MEM | BPF_DW ))
58175839 type = BPF_READ ;
5818- ctx_access = true;
5819- } else if (insn -> code == (BPF_STX | BPF_MEM | BPF_B ) ||
5820- insn -> code == (BPF_STX | BPF_MEM | BPF_H ) ||
5821- insn -> code == (BPF_STX | BPF_MEM | BPF_W ) ||
5822- insn -> code == (BPF_STX | BPF_MEM | BPF_DW ) ||
5823- insn -> code == (BPF_ST | BPF_MEM | BPF_B ) ||
5824- insn -> code == (BPF_ST | BPF_MEM | BPF_H ) ||
5825- insn -> code == (BPF_ST | BPF_MEM | BPF_W ) ||
5826- insn -> code == (BPF_ST | BPF_MEM | BPF_DW )) {
5840+ else if (insn -> code == (BPF_STX | BPF_MEM | BPF_B ) ||
5841+ insn -> code == (BPF_STX | BPF_MEM | BPF_H ) ||
5842+ insn -> code == (BPF_STX | BPF_MEM | BPF_W ) ||
5843+ insn -> code == (BPF_STX | BPF_MEM | BPF_DW ))
58275844 type = BPF_WRITE ;
5828- ctx_access = BPF_CLASS (insn -> code ) == BPF_STX ;
5829- } else {
5845+ else
58305846 continue ;
5831- }
58325847
58335848 if (type == BPF_WRITE &&
5834- env -> insn_aux_data [i + delta ].sanitize_stack_spill ) {
5849+ env -> insn_aux_data [i + delta ].sanitize_stack_off ) {
58355850 struct bpf_insn patch [] = {
5851+ /* Sanitize suspicious stack slot with zero.
5852+ * There are no memory dependencies for this store,
5853+ * since it's only using frame pointer and immediate
5854+ * constant of zero
5855+ */
5856+ BPF_ST_MEM (BPF_DW , BPF_REG_FP ,
5857+ env -> insn_aux_data [i + delta ].sanitize_stack_off ,
5858+ 0 ),
5859+ /* the original STX instruction will immediately
5860+ * overwrite the same stack slot with appropriate value
5861+ */
58365862 * insn ,
5837- BPF_ST_NOSPEC (),
58385863 };
58395864
58405865 cnt = ARRAY_SIZE (patch );
@@ -5848,9 +5873,6 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env)
58485873 continue ;
58495874 }
58505875
5851- if (!ctx_access )
5852- continue ;
5853-
58545876 if (env -> insn_aux_data [i + delta ].ptr_type != PTR_TO_CTX )
58555877 continue ;
58565878
0 commit comments