@@ -2802,14 +2802,35 @@ static bool is_perfmon_prog_type(enum bpf_prog_type prog_type)
28022802 }
28032803}
28042804
2805+ static inline int bpf_map_get_hash (int map_fd , void * buffer )
2806+ {
2807+ struct bpf_map * map ;
2808+
2809+ CLASS (fd , f )(map_fd );
2810+ map = __bpf_map_get (f );
2811+ if (IS_ERR (map ))
2812+ return PTR_ERR (map );
2813+
2814+ if (!map -> ops -> map_get_hash )
2815+ return - EINVAL ;
2816+
2817+ return map -> ops -> map_get_hash (map , SHA256_DIGEST_SIZE , buffer );
2818+ }
2819+
28052820static int bpf_prog_verify_signature (struct bpf_prog * prog , union bpf_attr * attr ,
28062821 bool is_kernel )
28072822{
28082823 bpfptr_t usig = make_bpfptr (attr -> signature , is_kernel );
2809- struct bpf_dynptr_kern sig_ptr , insns_ptr ;
2824+ bpfptr_t umaps ;
2825+ struct bpf_dynptr_kern sig_ptr , insns_ptr , hash_ptr ;
28102826 struct bpf_key * key = NULL ;
28112827 void * sig ;
2828+ int * maps ;
2829+ int map_fd ;
28122830 int err = 0 ;
2831+ u64 buffer [SHA256_DIGEST_SIZE * 2 / sizeof (u64 )];
2832+ u64 hash [SHA256_DIGEST_SIZE / sizeof (u64 )];
2833+ int n ;
28132834
28142835 if (system_keyring_id_check (attr -> keyring_id ) == 0 )
28152836 key = bpf_lookup_system_key (attr -> keyring_id );
@@ -2830,16 +2851,60 @@ static int bpf_prog_verify_signature(struct bpf_prog *prog, union bpf_attr *attr
28302851 bpf_dynptr_init (& insns_ptr , prog -> insnsi , BPF_DYNPTR_TYPE_LOCAL , 0 ,
28312852 prog -> len * sizeof (struct bpf_insn ));
28322853
2833- err = bpf_verify_pkcs7_signature ((struct bpf_dynptr * )& insns_ptr ,
2834- (struct bpf_dynptr * )& sig_ptr , key );
2854+ if (!attr -> signature_maps_size ) {
2855+ err = bpf_verify_pkcs7_signature ((struct bpf_dynptr * )& insns_ptr ,
2856+ (struct bpf_dynptr * )& sig_ptr , key );
2857+ } else {
2858+ bpf_dynptr_init (& hash_ptr , hash , BPF_DYNPTR_TYPE_LOCAL , 0 ,
2859+ sizeof (hash ));
2860+ umaps = make_bpfptr (attr -> signature_maps , is_kernel );
2861+ maps = kvmemdup_bpfptr (umaps , attr -> signature_maps_size * sizeof (* maps ));
2862+ if (!maps ) {
2863+ err = - ENOMEM ;
2864+ goto out ;
2865+ }
2866+ /* Process the map array in reverse order to generate a hash chain
2867+ * h(n) = sha256(h(n + 1), sha256(map(n)))
2868+ * h(n_len) = sha256(map(n_len))
2869+ */
2870+ for (n = attr -> signature_maps_size - 1 ; n >= 0 ; n -- ) {
2871+ err = copy_from_bpfptr_offset (& map_fd ,
2872+ make_bpfptr (attr -> fd_array , is_kernel ),
2873+ maps [n ] * sizeof (map_fd ),
2874+ sizeof (map_fd ));
2875+ if (err )
2876+ goto free_maps ;
2877+
2878+ if (n == attr -> signature_maps_size - 1 )
2879+ err = bpf_map_get_hash (map_fd , hash );
2880+ else {
2881+ memcpy (buffer , hash , sizeof (hash ));
2882+ err = bpf_map_get_hash (map_fd , buffer + ARRAY_SIZE (hash ));
2883+ sha256 ((u8 * )buffer , sizeof (buffer ), (u8 * )& hash );
2884+ }
2885+ if (err )
2886+ goto free_maps ;
2887+ }
2888+ /* Calculate final hash with program instructions
2889+ * f_hash = sha256(sha256(prog), h(0))
2890+ */
2891+ sha256 ((u8 * )prog -> insnsi , prog -> len * sizeof (struct bpf_insn ), (u8 * )& buffer );
2892+ memcpy (buffer + ARRAY_SIZE (hash ), hash , sizeof (hash ));
2893+ sha256 ((u8 * )buffer , sizeof (buffer ), (u8 * )& hash );
2894+ err = bpf_verify_pkcs7_signature ((struct bpf_dynptr * )& hash_ptr ,
2895+ (struct bpf_dynptr * )& sig_ptr , key );
28352896
2897+ free_maps :
2898+ kvfree (maps );
2899+ }
2900+ out :
28362901 bpf_key_put (key );
28372902 kvfree (sig );
28382903 return err ;
28392904}
28402905
28412906/* last field in 'union bpf_attr' used by this command */
2842- #define BPF_PROG_LOAD_LAST_FIELD keyring_id
2907+ #define BPF_PROG_LOAD_LAST_FIELD signature_maps_size
28432908
28442909static int bpf_prog_load (union bpf_attr * attr , bpfptr_t uattr , u32 uattr_size )
28452910{
0 commit comments