@@ -982,6 +982,7 @@ static void mark_reg_not_init(struct bpf_verifier_env *env,
982982 __mark_reg_not_init (regs + regno );
983983}
984984
985+ #define DEF_NOT_SUBREG (0)
985986static void init_reg_state (struct bpf_verifier_env * env ,
986987 struct bpf_func_state * state )
987988{
@@ -992,6 +993,7 @@ static void init_reg_state(struct bpf_verifier_env *env,
992993 mark_reg_not_init (env , regs , i );
993994 regs [i ].live = REG_LIVE_NONE ;
994995 regs [i ].parent = NULL ;
996+ regs [i ].subreg_def = DEF_NOT_SUBREG ;
995997 }
996998
997999 /* frame pointer */
@@ -1137,7 +1139,7 @@ static int check_subprogs(struct bpf_verifier_env *env)
11371139 */
11381140static int mark_reg_read (struct bpf_verifier_env * env ,
11391141 const struct bpf_reg_state * state ,
1140- struct bpf_reg_state * parent )
1142+ struct bpf_reg_state * parent , u8 flag )
11411143{
11421144 bool writes = parent == state -> parent ; /* Observe write marks */
11431145 int cnt = 0 ;
@@ -1152,17 +1154,26 @@ static int mark_reg_read(struct bpf_verifier_env *env,
11521154 parent -> var_off .value , parent -> off );
11531155 return - EFAULT ;
11541156 }
1155- if (parent -> live & REG_LIVE_READ )
1157+ /* The first condition is more likely to be true than the
1158+ * second, checked it first.
1159+ */
1160+ if ((parent -> live & REG_LIVE_READ ) == flag ||
1161+ parent -> live & REG_LIVE_READ64 )
11561162 /* The parentage chain never changes and
11571163 * this parent was already marked as LIVE_READ.
11581164 * There is no need to keep walking the chain again and
11591165 * keep re-marking all parents as LIVE_READ.
11601166 * This case happens when the same register is read
11611167 * multiple times without writes into it in-between.
1168+ * Also, if parent has the stronger REG_LIVE_READ64 set,
1169+ * then no need to set the weak REG_LIVE_READ32.
11621170 */
11631171 break ;
11641172 /* ... then we depend on parent's value */
1165- parent -> live |= REG_LIVE_READ ;
1173+ parent -> live |= flag ;
1174+ /* REG_LIVE_READ64 overrides REG_LIVE_READ32. */
1175+ if (flag == REG_LIVE_READ64 )
1176+ parent -> live &= ~REG_LIVE_READ32 ;
11661177 state = parent ;
11671178 parent = state -> parent ;
11681179 writes = true;
@@ -1174,19 +1185,119 @@ static int mark_reg_read(struct bpf_verifier_env *env,
11741185 return 0 ;
11751186}
11761187
1188+ /* This function is supposed to be used by the following 32-bit optimization
1189+ * code only. It returns TRUE if the source or destination register operates
1190+ * on 64-bit, otherwise return FALSE.
1191+ */
1192+ static bool is_reg64 (struct bpf_verifier_env * env , struct bpf_insn * insn ,
1193+ u32 regno , struct bpf_reg_state * reg , enum reg_arg_type t )
1194+ {
1195+ u8 code , class , op ;
1196+
1197+ code = insn -> code ;
1198+ class = BPF_CLASS (code );
1199+ op = BPF_OP (code );
1200+ if (class == BPF_JMP ) {
1201+ /* BPF_EXIT for "main" will reach here. Return TRUE
1202+ * conservatively.
1203+ */
1204+ if (op == BPF_EXIT )
1205+ return true;
1206+ if (op == BPF_CALL ) {
1207+ /* BPF to BPF call will reach here because of marking
1208+ * caller saved clobber with DST_OP_NO_MARK for which we
1209+ * don't care the register def because they are anyway
1210+ * marked as NOT_INIT already.
1211+ */
1212+ if (insn -> src_reg == BPF_PSEUDO_CALL )
1213+ return false;
1214+ /* Helper call will reach here because of arg type
1215+ * check, conservatively return TRUE.
1216+ */
1217+ if (t == SRC_OP )
1218+ return true;
1219+
1220+ return false;
1221+ }
1222+ }
1223+
1224+ if (class == BPF_ALU64 || class == BPF_JMP ||
1225+ /* BPF_END always use BPF_ALU class. */
1226+ (class == BPF_ALU && op == BPF_END && insn -> imm == 64 ))
1227+ return true;
1228+
1229+ if (class == BPF_ALU || class == BPF_JMP32 )
1230+ return false;
1231+
1232+ if (class == BPF_LDX ) {
1233+ if (t != SRC_OP )
1234+ return BPF_SIZE (code ) == BPF_DW ;
1235+ /* LDX source must be ptr. */
1236+ return true;
1237+ }
1238+
1239+ if (class == BPF_STX ) {
1240+ if (reg -> type != SCALAR_VALUE )
1241+ return true;
1242+ return BPF_SIZE (code ) == BPF_DW ;
1243+ }
1244+
1245+ if (class == BPF_LD ) {
1246+ u8 mode = BPF_MODE (code );
1247+
1248+ /* LD_IMM64 */
1249+ if (mode == BPF_IMM )
1250+ return true;
1251+
1252+ /* Both LD_IND and LD_ABS return 32-bit data. */
1253+ if (t != SRC_OP )
1254+ return false;
1255+
1256+ /* Implicit ctx ptr. */
1257+ if (regno == BPF_REG_6 )
1258+ return true;
1259+
1260+ /* Explicit source could be any width. */
1261+ return true;
1262+ }
1263+
1264+ if (class == BPF_ST )
1265+ /* The only source register for BPF_ST is a ptr. */
1266+ return true;
1267+
1268+ /* Conservatively return true at default. */
1269+ return true;
1270+ }
1271+
1272+ static void mark_insn_zext (struct bpf_verifier_env * env ,
1273+ struct bpf_reg_state * reg )
1274+ {
1275+ s32 def_idx = reg -> subreg_def ;
1276+
1277+ if (def_idx == DEF_NOT_SUBREG )
1278+ return ;
1279+
1280+ env -> insn_aux_data [def_idx - 1 ].zext_dst = true;
1281+ /* The dst will be zero extended, so won't be sub-register anymore. */
1282+ reg -> subreg_def = DEF_NOT_SUBREG ;
1283+ }
1284+
11771285static int check_reg_arg (struct bpf_verifier_env * env , u32 regno ,
11781286 enum reg_arg_type t )
11791287{
11801288 struct bpf_verifier_state * vstate = env -> cur_state ;
11811289 struct bpf_func_state * state = vstate -> frame [vstate -> curframe ];
1290+ struct bpf_insn * insn = env -> prog -> insnsi + env -> insn_idx ;
11821291 struct bpf_reg_state * reg , * regs = state -> regs ;
1292+ bool rw64 ;
11831293
11841294 if (regno >= MAX_BPF_REG ) {
11851295 verbose (env , "R%d is invalid\n" , regno );
11861296 return - EINVAL ;
11871297 }
11881298
11891299 reg = & regs [regno ];
1300+ rw64 = is_reg64 (env , insn , regno , reg , t );
11901301 if (t == SRC_OP ) {
11911302 /* check whether register used as source operand can be read */
11921303 if (reg -> type == NOT_INIT ) {
@@ -1197,14 +1308,19 @@ static int check_reg_arg(struct bpf_verifier_env *env, u32 regno,
11971308 if (regno == BPF_REG_FP )
11981309 return 0 ;
11991310
1200- return mark_reg_read (env , reg , reg -> parent );
1311+ if (rw64 )
1312+ mark_insn_zext (env , reg );
1313+
1314+ return mark_reg_read (env , reg , reg -> parent ,
1315+ rw64 ? REG_LIVE_READ64 : REG_LIVE_READ32 );
12011316 } else {
12021317 /* check whether register used as dest operand can be written to */
12031318 if (regno == BPF_REG_FP ) {
12041319 verbose (env , "frame pointer is read only\n" );
12051320 return - EACCES ;
12061321 }
12071322 reg -> live |= REG_LIVE_WRITTEN ;
1323+ reg -> subreg_def = rw64 ? DEF_NOT_SUBREG : env -> insn_idx + 1 ;
12081324 if (t == DST_OP )
12091325 mark_reg_unknown (env , regs , regno );
12101326 }
@@ -1384,7 +1500,8 @@ static int check_stack_read(struct bpf_verifier_env *env,
13841500 state -> regs [value_regno ].live |= REG_LIVE_WRITTEN ;
13851501 }
13861502 mark_reg_read (env , & reg_state -> stack [spi ].spilled_ptr ,
1387- reg_state -> stack [spi ].spilled_ptr .parent );
1503+ reg_state -> stack [spi ].spilled_ptr .parent ,
1504+ REG_LIVE_READ64 );
13881505 return 0 ;
13891506 } else {
13901507 int zeros = 0 ;
@@ -1401,7 +1518,8 @@ static int check_stack_read(struct bpf_verifier_env *env,
14011518 return - EACCES ;
14021519 }
14031520 mark_reg_read (env , & reg_state -> stack [spi ].spilled_ptr ,
1404- reg_state -> stack [spi ].spilled_ptr .parent );
1521+ reg_state -> stack [spi ].spilled_ptr .parent ,
1522+ REG_LIVE_READ64 );
14051523 if (value_regno >= 0 ) {
14061524 if (zeros == size ) {
14071525 /* any size read into register is zero extended,
@@ -2110,6 +2228,12 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn
21102228 value_regno );
21112229 if (reg_type_may_be_null (reg_type ))
21122230 regs [value_regno ].id = ++ env -> id_gen ;
2231+ /* A load of ctx field could have different
2232+ * actual load size with the one encoded in the
2233+ * insn. When the dst is PTR, it is for sure not
2234+ * a sub-register.
2235+ */
2236+ regs [value_regno ].subreg_def = DEF_NOT_SUBREG ;
21132237 }
21142238 regs [value_regno ].type = reg_type ;
21152239 }
@@ -2369,7 +2493,8 @@ static int check_stack_boundary(struct bpf_verifier_env *env, int regno,
23692493 * the whole slot to be marked as 'read'
23702494 */
23712495 mark_reg_read (env , & state -> stack [spi ].spilled_ptr ,
2372- state -> stack [spi ].spilled_ptr .parent );
2496+ state -> stack [spi ].spilled_ptr .parent ,
2497+ REG_LIVE_READ64 );
23732498 }
23742499 return update_stack_depth (env , state , min_off );
23752500}
@@ -3333,6 +3458,9 @@ static int check_helper_call(struct bpf_verifier_env *env, int func_id, int insn
33333458 check_reg_arg (env , caller_saved [i ], DST_OP_NO_MARK );
33343459 }
33353460
3461+ /* helper call returns 64-bit value. */
3462+ regs [BPF_REG_0 ].subreg_def = DEF_NOT_SUBREG ;
3463+
33363464 /* update return register (already marked as written above) */
33373465 if (fn -> ret_type == RET_INTEGER ) {
33383466 /* sets type to SCALAR_VALUE */
@@ -4264,6 +4392,7 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn)
42644392 */
42654393 * dst_reg = * src_reg ;
42664394 dst_reg -> live |= REG_LIVE_WRITTEN ;
4395+ dst_reg -> subreg_def = DEF_NOT_SUBREG ;
42674396 } else {
42684397 /* R1 = (u32) R2 */
42694398 if (is_pointer_value (env , insn -> src_reg )) {
@@ -4274,6 +4403,7 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn)
42744403 } else if (src_reg -> type == SCALAR_VALUE ) {
42754404 * dst_reg = * src_reg ;
42764405 dst_reg -> live |= REG_LIVE_WRITTEN ;
4406+ dst_reg -> subreg_def = env -> insn_idx + 1 ;
42774407 } else {
42784408 mark_reg_unknown (env , regs ,
42794409 insn -> dst_reg );
@@ -5353,6 +5483,8 @@ static int check_ld_abs(struct bpf_verifier_env *env, struct bpf_insn *insn)
53535483 * Already marked as written above.
53545484 */
53555485 mark_reg_unknown (env , regs , BPF_REG_0 );
5486+ /* ld_abs load up to 32-bit skb data. */
5487+ regs [BPF_REG_0 ].subreg_def = env -> insn_idx + 1 ;
53565488 return 0 ;
53575489}
53585490
@@ -6309,20 +6441,33 @@ static bool states_equal(struct bpf_verifier_env *env,
63096441 return true;
63106442}
63116443
6444+ /* Return 0 if no propagation happened. Return negative error code if error
6445+ * happened. Otherwise, return the propagated bit.
6446+ */
63126447static int propagate_liveness_reg (struct bpf_verifier_env * env ,
63136448 struct bpf_reg_state * reg ,
63146449 struct bpf_reg_state * parent_reg )
63156450{
6451+ u8 parent_flag = parent_reg -> live & REG_LIVE_READ ;
6452+ u8 flag = reg -> live & REG_LIVE_READ ;
63166453 int err ;
63176454
6318- if (parent_reg -> live & REG_LIVE_READ || !(reg -> live & REG_LIVE_READ ))
6455+ /* When comes here, read flags of PARENT_REG or REG could be any of
6456+ * REG_LIVE_READ64, REG_LIVE_READ32, REG_LIVE_NONE. There is no need
6457+ * of propagation if PARENT_REG has strongest REG_LIVE_READ64.
6458+ */
6459+ if (parent_flag == REG_LIVE_READ64 ||
6460+ /* Or if there is no read flag from REG. */
6461+ !flag ||
6462+ /* Or if the read flag from REG is the same as PARENT_REG. */
6463+ parent_flag == flag )
63196464 return 0 ;
63206465
6321- err = mark_reg_read (env , reg , parent_reg );
6466+ err = mark_reg_read (env , reg , parent_reg , flag );
63226467 if (err )
63236468 return err ;
63246469
6325- return 0 ;
6470+ return flag ;
63266471}
63276472
63286473/* A write screens off any subsequent reads; but write marks come from the
@@ -6356,8 +6501,10 @@ static int propagate_liveness(struct bpf_verifier_env *env,
63566501 for (i = frame < vstate -> curframe ? BPF_REG_6 : 0 ; i < BPF_REG_FP ; i ++ ) {
63576502 err = propagate_liveness_reg (env , & state_reg [i ],
63586503 & parent_reg [i ]);
6359- if (err )
6504+ if (err < 0 )
63606505 return err ;
6506+ if (err == REG_LIVE_READ64 )
6507+ mark_insn_zext (env , & parent_reg [i ]);
63616508 }
63626509
63636510 /* Propagate stack slots. */
@@ -6367,11 +6514,11 @@ static int propagate_liveness(struct bpf_verifier_env *env,
63676514 state_reg = & state -> stack [i ].spilled_ptr ;
63686515 err = propagate_liveness_reg (env , state_reg ,
63696516 parent_reg );
6370- if (err )
6517+ if (err < 0 )
63716518 return err ;
63726519 }
63736520 }
6374- return err ;
6521+ return 0 ;
63756522}
63766523
63776524static int is_state_visited (struct bpf_verifier_env * env , int insn_idx )
0 commit comments