@@ -546,13 +546,22 @@ void bpf_gen__map_create(struct bpf_gen *gen,
546546 default :
547547 break ;
548548 }
549- /* conditionally update max_entries */
550- if (map_idx >= 0 )
549+
550+ /*
551+ * Conditionally update max_entries from the host-supplied loader
552+ * ctx. This sizes the map at runtime, but for a signed loader
553+ * (gen_hash) it would let an untrusted host re-dimension the
554+ * program's maps after emit_signature_match(), outside what the
555+ * signature attests to. Keep the signer-provided max_entries
556+ * baked into the blob in that case.
557+ */
558+ if (map_idx >= 0 && !OPTS_GET (gen -> opts , gen_hash , false))
551559 move_ctx2blob (gen , attr_field (map_create_attr , max_entries ), 4 ,
552560 sizeof (struct bpf_loader_ctx ) +
553561 sizeof (struct bpf_map_desc ) * map_idx +
554562 offsetof(struct bpf_map_desc , max_entries ),
555563 true /* check that max_entries != 0 */ );
564+
556565 /* emit MAP_CREATE command */
557566 emit_sys_bpf (gen , BPF_MAP_CREATE , map_create_attr , attr_size );
558567 debug_ret (gen , "map_create %s idx %d type %d value_size %d value_btf_id %d" ,
@@ -586,6 +595,23 @@ static void emit_signature_match(struct bpf_gen *gen)
586595 __s64 off ;
587596 int i ;
588597
598+ /*
599+ * Reject if the metadata map is not exclusive. Without exclusivity
600+ * the cached map->sha[] verified above can be stale: another BPF
601+ * program with map access could have mutated the contents between
602+ * BPF_OBJ_GET_INFO_BY_FD and loader execution.
603+ */
604+ emit2 (gen , BPF_LD_IMM64_RAW_FULL (BPF_REG_1 , BPF_PSEUDO_MAP_IDX ,
605+ 0 , 0 , 0 , 0 ));
606+ emit (gen , BPF_LDX_MEM (BPF_W , BPF_REG_2 , BPF_REG_1 , SHA256_DIGEST_LENGTH ));
607+ off = - (gen -> insn_cur - gen -> insn_start - gen -> cleanup_label ) / 8 - 2 ;
608+ if (is_simm16 (off )) {
609+ emit (gen , BPF_MOV64_IMM (BPF_REG_7 , - EINVAL ));
610+ emit (gen , BPF_JMP_IMM (BPF_JNE , BPF_REG_2 , 1 , off ));
611+ } else {
612+ gen -> error = - ERANGE ;
613+ }
614+
589615 for (i = 0 ; i < SHA256_DWORD_SIZE ; i ++ ) {
590616 emit2 (gen , BPF_LD_IMM64_RAW_FULL (BPF_REG_1 , BPF_PSEUDO_MAP_IDX ,
591617 0 , 0 , 0 , 0 ));
@@ -1170,27 +1196,36 @@ void bpf_gen__map_update_elem(struct bpf_gen *gen, int map_idx, void *pvalue,
11701196 value = add_data (gen , pvalue , value_size );
11711197 key = add_data (gen , & zero , sizeof (zero ));
11721198
1173- /* if (map_desc[map_idx].initial_value) {
1199+ /*
1200+ * if (map_desc[map_idx].initial_value) {
11741201 * if (ctx->flags & BPF_SKEL_KERNEL)
11751202 * bpf_probe_read_kernel(value, value_size, initial_value);
11761203 * else
11771204 * bpf_copy_from_user(value, value_size, initial_value);
11781205 * }
1206+ *
1207+ * The runtime initial_value comes from the host-supplied loader
1208+ * ctx and would overwrite the blob value after emit_signature_match()
1209+ * has already validated map->sha[]. For a signed loader (gen_hash)
1210+ * the attested blob value must be authoritative, so skip the override
1211+ * and leave the hashed value in place.
11791212 */
1180- emit (gen , BPF_LDX_MEM (BPF_DW , BPF_REG_3 , BPF_REG_6 ,
1181- sizeof (struct bpf_loader_ctx ) +
1182- sizeof (struct bpf_map_desc ) * map_idx +
1183- offsetof(struct bpf_map_desc , initial_value )));
1184- emit (gen , BPF_JMP_IMM (BPF_JEQ , BPF_REG_3 , 0 , 8 ));
1185- emit2 (gen , BPF_LD_IMM64_RAW_FULL (BPF_REG_1 , BPF_PSEUDO_MAP_IDX_VALUE ,
1186- 0 , 0 , 0 , value ));
1187- emit (gen , BPF_MOV64_IMM (BPF_REG_2 , value_size ));
1188- emit (gen , BPF_LDX_MEM (BPF_W , BPF_REG_0 , BPF_REG_6 ,
1189- offsetof(struct bpf_loader_ctx , flags )));
1190- emit (gen , BPF_JMP_IMM (BPF_JSET , BPF_REG_0 , BPF_SKEL_KERNEL , 2 ));
1191- emit (gen , BPF_EMIT_CALL (BPF_FUNC_copy_from_user ));
1192- emit (gen , BPF_JMP_IMM (BPF_JA , 0 , 0 , 1 ));
1193- emit (gen , BPF_EMIT_CALL (BPF_FUNC_probe_read_kernel ));
1213+ if (!OPTS_GET (gen -> opts , gen_hash , false)) {
1214+ emit (gen , BPF_LDX_MEM (BPF_DW , BPF_REG_3 , BPF_REG_6 ,
1215+ sizeof (struct bpf_loader_ctx ) +
1216+ sizeof (struct bpf_map_desc ) * map_idx +
1217+ offsetof(struct bpf_map_desc , initial_value )));
1218+ emit (gen , BPF_JMP_IMM (BPF_JEQ , BPF_REG_3 , 0 , 8 ));
1219+ emit2 (gen , BPF_LD_IMM64_RAW_FULL (BPF_REG_1 , BPF_PSEUDO_MAP_IDX_VALUE ,
1220+ 0 , 0 , 0 , value ));
1221+ emit (gen , BPF_MOV64_IMM (BPF_REG_2 , value_size ));
1222+ emit (gen , BPF_LDX_MEM (BPF_W , BPF_REG_0 , BPF_REG_6 ,
1223+ offsetof(struct bpf_loader_ctx , flags )));
1224+ emit (gen , BPF_JMP_IMM (BPF_JSET , BPF_REG_0 , BPF_SKEL_KERNEL , 2 ));
1225+ emit (gen , BPF_EMIT_CALL (BPF_FUNC_copy_from_user ));
1226+ emit (gen , BPF_JMP_IMM (BPF_JA , 0 , 0 , 1 ));
1227+ emit (gen , BPF_EMIT_CALL (BPF_FUNC_probe_read_kernel ));
1228+ }
11941229
11951230 map_update_attr = add_data (gen , & attr , attr_size );
11961231 pr_debug ("gen: map_update_elem: idx %d, value: off %d size %d, attr: off %d size %d\n" ,
0 commit comments