@@ -2968,6 +2968,67 @@ int udp4_seq_show(struct seq_file *seq, void *v)
29682968 return 0 ;
29692969}
29702970
2971+ #ifdef CONFIG_BPF_SYSCALL
2972+ struct bpf_iter__udp {
2973+ __bpf_md_ptr (struct bpf_iter_meta * , meta );
2974+ __bpf_md_ptr (struct udp_sock * , udp_sk );
2975+ uid_t uid __aligned (8 );
2976+ int bucket __aligned (8 );
2977+ };
2978+
2979+ static int udp_prog_seq_show (struct bpf_prog * prog , struct bpf_iter_meta * meta ,
2980+ struct udp_sock * udp_sk , uid_t uid , int bucket )
2981+ {
2982+ struct bpf_iter__udp ctx ;
2983+
2984+ meta -> seq_num -- ; /* skip SEQ_START_TOKEN */
2985+ ctx .meta = meta ;
2986+ ctx .udp_sk = udp_sk ;
2987+ ctx .uid = uid ;
2988+ ctx .bucket = bucket ;
2989+ return bpf_iter_run_prog (prog , & ctx );
2990+ }
2991+
2992+ static int bpf_iter_udp_seq_show (struct seq_file * seq , void * v )
2993+ {
2994+ struct udp_iter_state * state = seq -> private ;
2995+ struct bpf_iter_meta meta ;
2996+ struct bpf_prog * prog ;
2997+ struct sock * sk = v ;
2998+ uid_t uid ;
2999+
3000+ if (v == SEQ_START_TOKEN )
3001+ return 0 ;
3002+
3003+ uid = from_kuid_munged (seq_user_ns (seq ), sock_i_uid (sk ));
3004+ meta .seq = seq ;
3005+ prog = bpf_iter_get_info (& meta , false);
3006+ return udp_prog_seq_show (prog , & meta , v , uid , state -> bucket );
3007+ }
3008+
3009+ static void bpf_iter_udp_seq_stop (struct seq_file * seq , void * v )
3010+ {
3011+ struct bpf_iter_meta meta ;
3012+ struct bpf_prog * prog ;
3013+
3014+ if (!v ) {
3015+ meta .seq = seq ;
3016+ prog = bpf_iter_get_info (& meta , true);
3017+ if (prog )
3018+ (void )udp_prog_seq_show (prog , & meta , v , 0 , 0 );
3019+ }
3020+
3021+ udp_seq_stop (seq , v );
3022+ }
3023+
3024+ static const struct seq_operations bpf_iter_udp_seq_ops = {
3025+ .start = udp_seq_start ,
3026+ .next = udp_seq_next ,
3027+ .stop = bpf_iter_udp_seq_stop ,
3028+ .show = bpf_iter_udp_seq_show ,
3029+ };
3030+ #endif
3031+
29713032const struct seq_operations udp_seq_ops = {
29723033 .start = udp_seq_start ,
29733034 .next = udp_seq_next ,
@@ -3085,6 +3146,57 @@ static struct pernet_operations __net_initdata udp_sysctl_ops = {
30853146 .init = udp_sysctl_init ,
30863147};
30873148
3149+ #if defined(CONFIG_BPF_SYSCALL ) && defined(CONFIG_PROC_FS )
3150+ DEFINE_BPF_ITER_FUNC (udp , struct bpf_iter_meta * meta ,
3151+ struct udp_sock * udp_sk , uid_t uid , int bucket )
3152+
3153+ static int bpf_iter_init_udp (void * priv_data )
3154+ {
3155+ struct udp_iter_state * st = priv_data ;
3156+ struct udp_seq_afinfo * afinfo ;
3157+ int ret ;
3158+
3159+ afinfo = kmalloc (sizeof (* afinfo ), GFP_USER | __GFP_NOWARN );
3160+ if (!afinfo )
3161+ return - ENOMEM ;
3162+
3163+ afinfo -> family = AF_UNSPEC ;
3164+ afinfo -> udp_table = & udp_table ;
3165+ st -> bpf_seq_afinfo = afinfo ;
3166+ ret = bpf_iter_init_seq_net (priv_data );
3167+ if (ret )
3168+ kfree (afinfo );
3169+ return ret ;
3170+ }
3171+
3172+ static void bpf_iter_fini_udp (void * priv_data )
3173+ {
3174+ struct udp_iter_state * st = priv_data ;
3175+
3176+ kfree (st -> bpf_seq_afinfo );
3177+ bpf_iter_fini_seq_net (priv_data );
3178+ }
3179+
3180+ static const struct bpf_iter_reg udp_reg_info = {
3181+ .target = "udp" ,
3182+ .seq_ops = & bpf_iter_udp_seq_ops ,
3183+ .init_seq_private = bpf_iter_init_udp ,
3184+ .fini_seq_private = bpf_iter_fini_udp ,
3185+ .seq_priv_size = sizeof (struct udp_iter_state ),
3186+ .ctx_arg_info_size = 1 ,
3187+ .ctx_arg_info = {
3188+ { offsetof(struct bpf_iter__udp , udp_sk ),
3189+ PTR_TO_BTF_ID_OR_NULL },
3190+ },
3191+ };
3192+
3193+ static void __init bpf_iter_register (void )
3194+ {
3195+ if (bpf_iter_reg_target (& udp_reg_info ))
3196+ pr_warn ("Warning: could not register bpf iterator udp\n" );
3197+ }
3198+ #endif
3199+
30883200void __init udp_init (void )
30893201{
30903202 unsigned long limit ;
@@ -3110,4 +3222,8 @@ void __init udp_init(void)
31103222
31113223 if (register_pernet_subsys (& udp_sysctl_ops ))
31123224 panic ("UDP: failed to init sysctl parameters.\n" );
3225+
3226+ #if defined(CONFIG_BPF_SYSCALL ) && defined(CONFIG_PROC_FS )
3227+ bpf_iter_register ();
3228+ #endif
31133229}
0 commit comments