Skip to content

Commit f40b780

Browse files
committed
sbpf: simplify calldests handling
1 parent 7bf48ee commit f40b780

File tree

5 files changed

+74
-39
lines changed

5 files changed

+74
-39
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
#ifndef HEADER_fd_src_ballet_sbpf_fd_sbpf_calldests_h
2+
#define HEADER_fd_src_ballet_sbpf_fd_sbpf_calldests_h
3+
4+
/* fd_sbpf_calldests.h provides a bit vector of valid call destinations.
5+
Should be configured to fit any possible program counter. The max
6+
program counter is <size of text section> divided by 8. */
7+
8+
#define SET_NAME fd_sbpf_calldests1
9+
#include "../../util/tmpl/fd_set_dynamic.c"
10+
11+
/* Unfortunately, fd_set_dynamic.c has UB if the set size is zero.
12+
So, wrap set definition to support zero size. Also handle OOB jumps
13+
from malicious programs. */
14+
15+
typedef fd_sbpf_calldests1_t fd_sbpf_calldests_t;
16+
17+
#define fd_sbpf_calldests_align fd_sbpf_calldests1_align
18+
#define fd_sbpf_calldests_join fd_sbpf_calldests1_join
19+
#define fd_sbpf_calldests_leave fd_sbpf_calldests1_leave
20+
#define fd_sbpf_calldests_delete fd_sbpf_calldests1_delete
21+
22+
FD_PROTOTYPES_BEGIN
23+
24+
static inline ulong
25+
fd_sbpf_calldests_footprint( ulong pc_max ) {
26+
return fd_sbpf_calldests1_footprint( fd_ulong_min( pc_max, 1UL ) );
27+
}
28+
29+
static inline void *
30+
fd_sbpf_calldests_new( void * mem,
31+
ulong pc_max ) {
32+
return fd_sbpf_calldests1_new( mem, fd_ulong_min( pc_max, 1UL ) );
33+
}
34+
35+
static inline void
36+
fd_sbpf_calldests_insert( fd_sbpf_calldests_t * calldests,
37+
ulong pc ) {
38+
if( FD_UNLIKELY( !fd_sbpf_calldests1_valid_idx( calldests, pc ) ) ) return;
39+
fd_sbpf_calldests1_insert( calldests, pc );
40+
}
41+
42+
static inline int
43+
fd_sbpf_calldests_test( fd_sbpf_calldests_t const * calldests,
44+
ulong pc ) {
45+
if( FD_UNLIKELY( !fd_sbpf_calldests1_valid_idx( calldests, pc ) ) ) return 0;
46+
return fd_sbpf_calldests1_test( calldests, pc );
47+
}
48+
49+
FD_PROTOTYPES_END
50+
51+
#endif /* HEADER_fd_src_ballet_sbpf_fd_sbpf_calldests_h */

src/ballet/sbpf/fd_sbpf_loader.c

Lines changed: 17 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#include "fd_sbpf_loader.h"
22
#include "fd_sbpf_instr.h"
33
#include "fd_sbpf_opcodes.h"
4-
#include "../../util/fd_util.h"
4+
#include "../elf/fd_elf64.h"
55
#include "../../util/bits/fd_sat.h"
66
#include "../murmur3/fd_murmur3.h"
77

@@ -127,18 +127,17 @@ fd_sbpf_program_align( void ) {
127127
return alignof( fd_sbpf_program_t );
128128
}
129129

130+
static inline ulong
131+
fd_sbpf_program_calldests_max( fd_sbpf_elf_info_t const * info ) {
132+
if( fd_sbpf_enable_stricter_elf_headers_enabled( info->sbpf_version ) ) return 0UL;
133+
return info->text_cnt;
134+
}
135+
130136
ulong
131137
fd_sbpf_program_footprint( fd_sbpf_elf_info_t const * info ) {
132-
FD_COMPILER_UNPREDICTABLE( info ); /* Make this appear as FD_FN_PURE (e.g. footprint might depened on info contents in future) */
133-
if( FD_UNLIKELY( fd_sbpf_enable_stricter_elf_headers_enabled( info->sbpf_version ) ) ) {
134-
/* SBPF v3+ no longer neeeds calldests bitmap */
135-
return FD_LAYOUT_FINI( FD_LAYOUT_APPEND( FD_LAYOUT_INIT,
136-
alignof(fd_sbpf_program_t), sizeof(fd_sbpf_program_t) ),
137-
alignof(fd_sbpf_program_t) );
138-
}
139138
return FD_LAYOUT_FINI( FD_LAYOUT_APPEND( FD_LAYOUT_APPEND( FD_LAYOUT_INIT,
140139
alignof(fd_sbpf_program_t), sizeof(fd_sbpf_program_t) ),
141-
fd_sbpf_calldests_align(), fd_sbpf_calldests_footprint( info->text_cnt ) ), /* calldests bitmap */
140+
fd_sbpf_calldests_align(), fd_sbpf_calldests_footprint( fd_sbpf_program_calldests_max( info ) ) ),
142141
alignof(fd_sbpf_program_t) );
143142
}
144143

@@ -183,19 +182,13 @@ fd_sbpf_program_new( void * prog_mem,
183182
};
184183

185184
/* If the text section is empty, then we do not need a calldests map. */
186-
ulong pc_max = elf_info->text_cnt;
187-
if( FD_UNLIKELY( fd_sbpf_enable_stricter_elf_headers_enabled( elf_info->sbpf_version ) || pc_max==0UL ) ) {
188-
/* No calldests map in SBPF v3+ or if text_cnt is 0. */
189-
prog->calldests_shmem = NULL;
190-
prog->calldests = NULL;
191-
} else {
192-
/* Initialize calldests map. */
193-
prog->calldests_shmem = fd_sbpf_calldests_new(
194-
FD_SCRATCH_ALLOC_APPEND( laddr, fd_sbpf_calldests_align(),
195-
fd_sbpf_calldests_footprint( pc_max ) ),
196-
pc_max );
197-
prog->calldests = fd_sbpf_calldests_join( prog->calldests_shmem );
198-
}
185+
ulong calldests_max = fd_sbpf_program_calldests_max( elf_info );
186+
/* Initialize calldests map. */
187+
prog->calldests_shmem = fd_sbpf_calldests_new(
188+
FD_SCRATCH_ALLOC_APPEND( laddr, fd_sbpf_calldests_align(),
189+
fd_sbpf_calldests_footprint( calldests_max ) ),
190+
fd_sbpf_calldests_footprint( calldests_max ) );
191+
prog->calldests = fd_sbpf_calldests_join( prog->calldests_shmem );
199192

200193
return prog;
201194
}
@@ -215,7 +208,7 @@ fd_sbpf_program_delete( fd_sbpf_program_t * mem ) {
215208

216209
struct fd_sbpf_loader {
217210
/* External objects */
218-
ulong * calldests; /* owned by program. NULL if text_cnt = 0 or SBPF v3+ */
211+
ulong * calldests; /* owned by program */
219212
fd_sbpf_syscalls_t * syscalls; /* owned by caller */
220213
};
221214
typedef struct fd_sbpf_loader fd_sbpf_loader_t;
@@ -361,9 +354,7 @@ fd_sbpf_register_function_hashed_legacy( fd_sbpf_loader_t * loader,
361354
make sure that target_pc <= text_cnt, otherwise the insertion is
362355
UB. It's fine to skip inserting these entries because the calldests
363356
are write-only in the SBPF loader and only queried from the VM. */
364-
if( FD_LIKELY( !is_entrypoint &&
365-
loader->calldests &&
366-
fd_sbpf_calldests_valid_idx( loader->calldests, target_pc ) ) ) {
357+
if( FD_LIKELY( !is_entrypoint ) ) {
367358
fd_sbpf_calldests_insert( loader->calldests, target_pc );
368359
}
369360

src/ballet/sbpf/fd_sbpf_loader.h

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@
99
program header table and instead load specific sections at predefined
1010
addresses. However, it will perform dynamic relocation. */
1111

12-
#include "../../util/fd_util_base.h"
13-
#include "../elf/fd_elf64.h"
12+
#include "fd_sbpf_calldests.h"
1413

1514
/* Error types ********************************************************/
1615

@@ -80,13 +79,6 @@
8079

8180
/* Program struct *****************************************************/
8281

83-
/* fd_sbpf_calldests is a bit vector of valid call destinations.
84-
Should be configured to fit any possible program counter. The max
85-
program counter is <size of ELF binary> divided by 8. */
86-
87-
#define SET_NAME fd_sbpf_calldests
88-
#include "../../util/tmpl/fd_set_dynamic.c"
89-
9082
/* fd_sbpf_syscall_func_t is a callback implementing an sBPF syscall.
9183
vm is a handle to the running VM. Returns 0 on suceess or an integer
9284
error code on failure.

src/ballet/sbpf/fuzz_sbpf_loader.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#error "This target requires FD_HAS_HOSTED"
33
#endif
44

5+
#include "../../util/fd_util.h"
56
#include "../../util/sanitize/fd_fuzz.h"
67
#include "fd_sbpf_loader.h"
78

src/flamenco/runtime/tests/fd_elf_harness.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ fd_solfuzz_elf_loader_run( fd_solfuzz_runner_t * runner,
102102

103103
pb_size_t max_calldests_sz = 1U;
104104
if( FD_LIKELY( prog->calldests ) ) {
105-
max_calldests_sz += (pb_size_t)fd_sbpf_calldests_cnt( prog->calldests);
105+
max_calldests_sz += (pb_size_t)fd_sbpf_calldests1_cnt( prog->calldests );
106106
}
107107

108108
elf_effects->calldests = FD_SCRATCH_ALLOC_APPEND(l, 8UL, max_calldests_sz * sizeof(uint64_t));
@@ -115,9 +115,9 @@ fd_solfuzz_elf_loader_run( fd_solfuzz_runner_t * runner,
115115

116116
/* Add the rest of the calldests */
117117
if( FD_LIKELY( prog->calldests ) ) {
118-
for( ulong target_pc=fd_sbpf_calldests_const_iter_init(prog->calldests);
119-
!fd_sbpf_calldests_const_iter_done(target_pc);
120-
target_pc=fd_sbpf_calldests_const_iter_next(prog->calldests, target_pc) ) {
118+
for( ulong target_pc=fd_sbpf_calldests1_const_iter_init( prog->calldests );
119+
!fd_sbpf_calldests1_const_iter_done( target_pc);
120+
target_pc=fd_sbpf_calldests1_const_iter_next( prog->calldests, target_pc ) ) {
121121
if( FD_LIKELY( target_pc!=prog->entry_pc ) ) {
122122
elf_effects->calldests[elf_effects->calldests_count++] = target_pc;
123123
}

0 commit comments

Comments
 (0)