@@ -4893,7 +4893,23 @@ TEST(tsync_vs_dead_thread_leader)
4893
4893
EXPECT_EQ (0 , status );
4894
4894
}
4895
4895
4896
- noinline int probed (void )
4896
+ #ifdef __x86_64__
4897
+ __attribute__((naked )) noinline int probed_uprobe (void )
4898
+ {
4899
+ /* Optimized uprobe is possible only on top of nop5 instruction. */
4900
+ asm volatile (" \n"
4901
+ ".byte 0x0f, 0x1f, 0x44, 0x00, 0x00 \n"
4902
+ "ret \n"
4903
+ );
4904
+ }
4905
+ #else
4906
+ noinline int probed_uprobe (void )
4907
+ {
4908
+ return 1 ;
4909
+ }
4910
+ #endif
4911
+
4912
+ noinline int probed_uretprobe (void )
4897
4913
{
4898
4914
return 1 ;
4899
4915
}
@@ -4946,35 +4962,46 @@ static ssize_t get_uprobe_offset(const void *addr)
4946
4962
return found ? (uintptr_t )addr - start + base : -1 ;
4947
4963
}
4948
4964
4949
- FIXTURE (URETPROBE ) {
4965
+ FIXTURE (UPROBE ) {
4950
4966
int fd ;
4951
4967
};
4952
4968
4953
- FIXTURE_VARIANT (URETPROBE ) {
4969
+ FIXTURE_VARIANT (UPROBE ) {
4954
4970
/*
4955
- * All of the URETPROBE behaviors can be tested with either
4956
- * uretprobe attached or not
4971
+ * All of the U(RET)PROBE behaviors can be tested with either
4972
+ * u(ret)probe attached or not
4957
4973
*/
4958
4974
bool attach ;
4975
+ /*
4976
+ * Test both uprobe and uretprobe.
4977
+ */
4978
+ bool uretprobe ;
4959
4979
};
4960
4980
4961
- FIXTURE_VARIANT_ADD (URETPROBE , attached ) {
4981
+ FIXTURE_VARIANT_ADD (UPROBE , not_attached ) {
4982
+ .attach = false,
4983
+ .uretprobe = false,
4984
+ };
4985
+
4986
+ FIXTURE_VARIANT_ADD (UPROBE , uprobe_attached ) {
4962
4987
.attach = true,
4988
+ .uretprobe = false,
4963
4989
};
4964
4990
4965
- FIXTURE_VARIANT_ADD (URETPROBE , not_attached ) {
4966
- .attach = false,
4991
+ FIXTURE_VARIANT_ADD (UPROBE , uretprobe_attached ) {
4992
+ .attach = true,
4993
+ .uretprobe = true,
4967
4994
};
4968
4995
4969
- FIXTURE_SETUP (URETPROBE )
4996
+ FIXTURE_SETUP (UPROBE )
4970
4997
{
4971
4998
const size_t attr_sz = sizeof (struct perf_event_attr );
4972
4999
struct perf_event_attr attr ;
4973
5000
ssize_t offset ;
4974
5001
int type , bit ;
4975
5002
4976
- #ifndef __NR_uretprobe
4977
- SKIP (return , "__NR_uretprobe syscall not defined" );
5003
+ #if !defined( __NR_uprobe ) || !defined( __NR_uretprobe )
5004
+ SKIP (return , "__NR_uprobe ot __NR_uretprobe syscalls not defined" );
4978
5005
#endif
4979
5006
4980
5007
if (!variant -> attach )
@@ -4984,12 +5011,17 @@ FIXTURE_SETUP(URETPROBE)
4984
5011
4985
5012
type = determine_uprobe_perf_type ();
4986
5013
ASSERT_GE (type , 0 );
4987
- bit = determine_uprobe_retprobe_bit ();
4988
- ASSERT_GE (bit , 0 );
4989
- offset = get_uprobe_offset (probed );
5014
+
5015
+ if (variant -> uretprobe ) {
5016
+ bit = determine_uprobe_retprobe_bit ();
5017
+ ASSERT_GE (bit , 0 );
5018
+ }
5019
+
5020
+ offset = get_uprobe_offset (variant -> uretprobe ? probed_uretprobe : probed_uprobe );
4990
5021
ASSERT_GE (offset , 0 );
4991
5022
4992
- attr .config |= 1 << bit ;
5023
+ if (variant -> uretprobe )
5024
+ attr .config |= 1 << bit ;
4993
5025
attr .size = attr_sz ;
4994
5026
attr .type = type ;
4995
5027
attr .config1 = ptr_to_u64 ("/proc/self/exe" );
@@ -5000,7 +5032,7 @@ FIXTURE_SETUP(URETPROBE)
5000
5032
PERF_FLAG_FD_CLOEXEC );
5001
5033
}
5002
5034
5003
- FIXTURE_TEARDOWN (URETPROBE )
5035
+ FIXTURE_TEARDOWN (UPROBE )
5004
5036
{
5005
5037
/* we could call close(self->fd), but we'd need extra filter for
5006
5038
* that and since we are calling _exit right away..
@@ -5014,11 +5046,15 @@ static int run_probed_with_filter(struct sock_fprog *prog)
5014
5046
return -1 ;
5015
5047
}
5016
5048
5017
- probed ();
5049
+ /* uprobe is optimized after first hit, so let's hit twice */
5050
+ probed_uprobe ();
5051
+ probed_uprobe ();
5052
+
5053
+ probed_uretprobe ();
5018
5054
return 0 ;
5019
5055
}
5020
5056
5021
- TEST_F (URETPROBE , uretprobe_default_allow )
5057
+ TEST_F (UPROBE , uprobe_default_allow )
5022
5058
{
5023
5059
struct sock_filter filter [] = {
5024
5060
BPF_STMT (BPF_RET |BPF_K , SECCOMP_RET_ALLOW ),
@@ -5031,7 +5067,7 @@ TEST_F(URETPROBE, uretprobe_default_allow)
5031
5067
ASSERT_EQ (0 , run_probed_with_filter (& prog ));
5032
5068
}
5033
5069
5034
- TEST_F (URETPROBE , uretprobe_default_block )
5070
+ TEST_F (UPROBE , uprobe_default_block )
5035
5071
{
5036
5072
struct sock_filter filter [] = {
5037
5073
BPF_STMT (BPF_LD |BPF_W |BPF_ABS ,
@@ -5048,11 +5084,14 @@ TEST_F(URETPROBE, uretprobe_default_block)
5048
5084
ASSERT_EQ (0 , run_probed_with_filter (& prog ));
5049
5085
}
5050
5086
5051
- TEST_F (URETPROBE , uretprobe_block_uretprobe_syscall )
5087
+ TEST_F (UPROBE , uprobe_block_syscall )
5052
5088
{
5053
5089
struct sock_filter filter [] = {
5054
5090
BPF_STMT (BPF_LD |BPF_W |BPF_ABS ,
5055
5091
offsetof(struct seccomp_data , nr )),
5092
+ #ifdef __NR_uprobe
5093
+ BPF_JUMP (BPF_JMP |BPF_JEQ |BPF_K , __NR_uprobe , 1 , 2 ),
5094
+ #endif
5056
5095
#ifdef __NR_uretprobe
5057
5096
BPF_JUMP (BPF_JMP |BPF_JEQ |BPF_K , __NR_uretprobe , 0 , 1 ),
5058
5097
#endif
@@ -5067,11 +5106,14 @@ TEST_F(URETPROBE, uretprobe_block_uretprobe_syscall)
5067
5106
ASSERT_EQ (0 , run_probed_with_filter (& prog ));
5068
5107
}
5069
5108
5070
- TEST_F (URETPROBE , uretprobe_default_block_with_uretprobe_syscall )
5109
+ TEST_F (UPROBE , uprobe_default_block_with_syscall )
5071
5110
{
5072
5111
struct sock_filter filter [] = {
5073
5112
BPF_STMT (BPF_LD |BPF_W |BPF_ABS ,
5074
5113
offsetof(struct seccomp_data , nr )),
5114
+ #ifdef __NR_uprobe
5115
+ BPF_JUMP (BPF_JMP |BPF_JEQ |BPF_K , __NR_uprobe , 3 , 0 ),
5116
+ #endif
5075
5117
#ifdef __NR_uretprobe
5076
5118
BPF_JUMP (BPF_JMP |BPF_JEQ |BPF_K , __NR_uretprobe , 2 , 0 ),
5077
5119
#endif
0 commit comments