@@ -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