@@ -3109,6 +3109,148 @@ static int invoke_bpf_mod_ret(const struct btf_func_model *m, u8 **pprog,
31093109 return 0 ;
31103110}
31113111
3112+ static int invoke_bpf_session_entry (const struct btf_func_model * m , u8 * * pprog ,
3113+ struct bpf_tramp_links * tl , int stack_size ,
3114+ int run_ctx_off , int ret_off , int sflags_off ,
3115+ int cookies_off , void * image , void * rw_image )
3116+ {
3117+ int i , j = 0 , cur_cookie_off ;
3118+ u64 session_flags ;
3119+ u8 * prog = * pprog ;
3120+ u8 * jmp_insn ;
3121+
3122+ /* clear the session flags:
3123+ * xor rax, rax
3124+ * mov QWORD PTR [rbp - sflags_off], rax
3125+ */
3126+ EMIT3 (0x48 , 0x31 , 0xC0 );
3127+ emit_stx (& prog , BPF_DW , BPF_REG_FP , BPF_REG_0 , - sflags_off );
3128+ /*
3129+ * clear the return value to make sure bpf_get_func_ret() always
3130+ * get 0 in fentry:
3131+ * mov QWORD PTR [rbp - 0x8], rax
3132+ */
3133+ emit_stx (& prog , BPF_DW , BPF_REG_FP , BPF_REG_0 , - ret_off );
3134+ /* clear all the cookies in the cookie array */
3135+ for (i = 0 ; i < tl -> nr_links ; i ++ ) {
3136+ if (tl -> links [i ]-> link .prog -> call_session_cookie ) {
3137+ cur_cookie_off = - cookies_off + j * 8 ;
3138+ /* mov QWORD PTR [rbp - sflags_off], rax */
3139+ emit_stx (& prog , BPF_DW , BPF_REG_FP , BPF_REG_0 ,
3140+ cur_cookie_off );
3141+ j ++ ;
3142+ }
3143+ }
3144+
3145+ j = 0 ;
3146+ for (i = 0 ; i < tl -> nr_links ; i ++ ) {
3147+ if (tl -> links [i ]-> link .prog -> call_session_cookie ) {
3148+ cur_cookie_off = - cookies_off + j * 8 ;
3149+ /*
3150+ * save the cookie address to rbp - sflags_off + 8:
3151+ * lea rax, [rbp - cur_cookie_off]
3152+ * mov QWORD PTR [rbp - sflags_off + 8], rax
3153+ */
3154+ if (!is_imm8 (cur_cookie_off ))
3155+ EMIT3_off32 (0x48 , 0x8D , 0x85 , cur_cookie_off );
3156+ else
3157+ EMIT4 (0x48 , 0x8D , 0x45 , cur_cookie_off );
3158+ emit_stx (& prog , BPF_DW , BPF_REG_FP , BPF_REG_0 , - sflags_off + 8 );
3159+ j ++ ;
3160+ }
3161+ if (invoke_bpf_prog (m , & prog , tl -> links [i ], stack_size , run_ctx_off , true,
3162+ ret_off , image , rw_image ))
3163+ return - EINVAL ;
3164+
3165+ /* fentry prog stored return value into [rbp - 8]. Emit:
3166+ * if (*(u64 *)(rbp - ret_off) != 0) {
3167+ * *(u64 *)(rbp - sflags_off) |= (1 << (i + 1));
3168+ * *(u64 *)(rbp - ret_off) = 0;
3169+ * }
3170+ */
3171+ /* cmp QWORD PTR [rbp - ret_off], 0x0 */
3172+ EMIT4 (0x48 , 0x83 , 0x7d , - ret_off ); EMIT1 (0x00 );
3173+ /* emit 2 nops that will be replaced with JE insn */
3174+ jmp_insn = prog ;
3175+ emit_nops (& prog , 2 );
3176+
3177+ session_flags = (1ULL << (i + 1 ));
3178+ /* mov rax, $session_flags */
3179+ emit_mov_imm64 (& prog , BPF_REG_0 , session_flags >> 32 , (u32 ) session_flags );
3180+ /* or QWORD PTR [rbp - sflags_off], rax */
3181+ EMIT2 (0x48 , 0x09 );
3182+ emit_insn_suffix (& prog , BPF_REG_FP , BPF_REG_0 , - sflags_off );
3183+
3184+ /* mov QWORD PTR [rbp - ret_off], 0x0 */
3185+ EMIT4 (0x48 , 0xC7 , 0x45 , - ret_off ); EMIT4 (0x00 , 0x00 , 0x00 , 0x00 );
3186+
3187+ jmp_insn [0 ] = X86_JE ;
3188+ jmp_insn [1 ] = prog - jmp_insn - 2 ;
3189+ }
3190+
3191+ * pprog = prog ;
3192+ return 0 ;
3193+ }
3194+
3195+ static int invoke_bpf_session_exit (const struct btf_func_model * m , u8 * * pprog ,
3196+ struct bpf_tramp_links * tl , int stack_size ,
3197+ int run_ctx_off , int ret_off , int sflags_off ,
3198+ int cookies_off , void * image , void * rw_image )
3199+ {
3200+ int i , j = 0 , cur_cookie_off ;
3201+ u64 session_flags ;
3202+ u8 * prog = * pprog ;
3203+ u8 * jmp_insn ;
3204+
3205+ /*
3206+ * set the bpf_trace_is_exit flag to the session flags:
3207+ * mov rax, 1
3208+ * or QWORD PTR [rbp - sflags_off], rax
3209+ */
3210+ emit_mov_imm32 (& prog , false, BPF_REG_0 , 1 );
3211+ EMIT2 (0x48 , 0x09 );
3212+ emit_insn_suffix (& prog , BPF_REG_FP , BPF_REG_0 , - sflags_off );
3213+
3214+ for (i = 0 ; i < tl -> nr_links ; i ++ ) {
3215+ if (tl -> links [i ]-> link .prog -> call_session_cookie ) {
3216+ cur_cookie_off = - cookies_off + j * 8 ;
3217+ /*
3218+ * save the cookie address to rbp - sflags_off + 8:
3219+ * lea rax, [rbp - cur_cookie_off]
3220+ * mov QWORD PTR [rbp - sflags_off + 8], rax
3221+ */
3222+ if (!is_imm8 (cur_cookie_off ))
3223+ EMIT3_off32 (0x48 , 0x8D , 0x85 , cur_cookie_off );
3224+ else
3225+ EMIT4 (0x48 , 0x8D , 0x45 , cur_cookie_off );
3226+ emit_stx (& prog , BPF_DW , BPF_REG_FP , BPF_REG_0 , - sflags_off + 8 );
3227+ j ++ ;
3228+ }
3229+ /* check if (1 << (i+1)) is set in the session flags, and
3230+ * skip the execution of the fexit program if it is.
3231+ */
3232+ session_flags = 1ULL << (i + 1 );
3233+ /* mov rax, $session_flags */
3234+ emit_mov_imm64 (& prog , BPF_REG_0 , session_flags >> 32 , (u32 ) session_flags );
3235+ /* test QWORD PTR [rbp - sflags_off], rax */
3236+ EMIT2 (0x48 , 0x85 );
3237+ emit_insn_suffix (& prog , BPF_REG_FP , BPF_REG_0 , - sflags_off );
3238+ /* emit 2 nops that will be replaced with JE insn */
3239+ jmp_insn = prog ;
3240+ emit_nops (& prog , 2 );
3241+
3242+ if (invoke_bpf_prog (m , & prog , tl -> links [i ], stack_size , run_ctx_off , false,
3243+ ret_off , image , rw_image ))
3244+ return - EINVAL ;
3245+
3246+ jmp_insn [0 ] = X86_JNE ;
3247+ jmp_insn [1 ] = prog - jmp_insn - 2 ;
3248+ }
3249+
3250+ * pprog = prog ;
3251+ return 0 ;
3252+ }
3253+
31123254/* mov rax, qword ptr [rbp - rounded_stack_depth - 8] */
31133255#define LOAD_TRAMP_TAIL_CALL_CNT_PTR (stack ) \
31143256 __LOAD_TCC_PTR(-round_up(stack, 8) - 8)
@@ -3181,8 +3323,9 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
31813323{
31823324 int i , ret , nr_regs = m -> nr_args , stack_size = 0 ;
31833325 int ret_off , regs_off , nregs_off , ip_off , run_ctx_off , arg_stack_off ,
3184- rbx_off ;
3326+ rbx_off , sflags_off = 0 , cookies_off ;
31853327 struct bpf_tramp_links * fentry = & tlinks [BPF_TRAMP_FENTRY ];
3328+ struct bpf_tramp_links * session = & tlinks [BPF_TRAMP_SESSION ];
31863329 struct bpf_tramp_links * fexit = & tlinks [BPF_TRAMP_FEXIT ];
31873330 struct bpf_tramp_links * fmod_ret = & tlinks [BPF_TRAMP_MODIFY_RETURN ];
31883331 void * orig_call = func_addr ;
@@ -3215,6 +3358,9 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
32153358 * RBP + 8 [ return address ]
32163359 * RBP + 0 [ RBP ]
32173360 *
3361+ * [ cookie ptr ] tracing session
3362+ * RBP - sflags_off [ session flags ] tracing session
3363+ *
32183364 * RBP - ret_off [ return value ] BPF_TRAMP_F_CALL_ORIG or
32193365 * BPF_TRAMP_F_RET_FENTRY_RET flags
32203366 *
@@ -3230,13 +3376,23 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
32303376 *
32313377 * RBP - run_ctx_off [ bpf_tramp_run_ctx ]
32323378 *
3379+ * [ session cookieN ]
3380+ * [ ... ]
3381+ * RBP - cookies_off [ session cookie1 ] tracing session
3382+ *
32333383 * [ stack_argN ] BPF_TRAMP_F_CALL_ORIG
32343384 * [ ... ]
32353385 * [ stack_arg2 ]
32363386 * RBP - arg_stack_off [ stack_arg1 ]
32373387 * RSP [ tail_call_cnt_ptr ] BPF_TRAMP_F_TAIL_CALL_CTX
32383388 */
32393389
3390+ /* room for session flags and cookie ptr */
3391+ if (session -> nr_links ) {
3392+ stack_size += 8 + 8 ;
3393+ sflags_off = stack_size ;
3394+ }
3395+
32403396 /* room for return value of orig_call or fentry prog */
32413397 save_ret = flags & (BPF_TRAMP_F_CALL_ORIG | BPF_TRAMP_F_RET_FENTRY_RET );
32423398 if (save_ret )
@@ -3261,6 +3417,14 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
32613417 stack_size += (sizeof (struct bpf_tramp_run_ctx ) + 7 ) & ~0x7 ;
32623418 run_ctx_off = stack_size ;
32633419
3420+ if (session -> nr_links ) {
3421+ for (i = 0 ; i < session -> nr_links ; i ++ ) {
3422+ if (session -> links [i ]-> link .prog -> call_session_cookie )
3423+ stack_size += 8 ;
3424+ }
3425+ }
3426+ cookies_off = stack_size ;
3427+
32643428 if (nr_regs > 6 && (flags & BPF_TRAMP_F_CALL_ORIG )) {
32653429 /* the space that used to pass arguments on-stack */
32663430 stack_size += (nr_regs - get_nr_used_regs (m )) * 8 ;
@@ -3349,6 +3513,13 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
33493513 return - EINVAL ;
33503514 }
33513515
3516+ if (session -> nr_links ) {
3517+ if (invoke_bpf_session_entry (m , & prog , session , regs_off ,
3518+ run_ctx_off , ret_off , sflags_off ,
3519+ cookies_off , image , rw_image ))
3520+ return - EINVAL ;
3521+ }
3522+
33523523 if (fmod_ret -> nr_links ) {
33533524 branches = kcalloc (fmod_ret -> nr_links , sizeof (u8 * ),
33543525 GFP_KERNEL );
@@ -3414,6 +3585,15 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
34143585 }
34153586 }
34163587
3588+ if (session -> nr_links ) {
3589+ if (invoke_bpf_session_exit (m , & prog , session , regs_off ,
3590+ run_ctx_off , ret_off , sflags_off ,
3591+ cookies_off , image , rw_image )) {
3592+ ret = - EINVAL ;
3593+ goto cleanup ;
3594+ }
3595+ }
3596+
34173597 if (flags & BPF_TRAMP_F_RESTORE_REGS )
34183598 restore_regs (m , & prog , regs_off );
34193599
@@ -3483,9 +3663,6 @@ int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image, void *i
34833663 int ret ;
34843664 u32 size = image_end - image ;
34853665
3486- if (tlinks [BPF_TRAMP_SESSION ].nr_links )
3487- return - EOPNOTSUPP ;
3488-
34893666 /* rw_image doesn't need to be in module memory range, so we can
34903667 * use kvmalloc.
34913668 */
0 commit comments