@@ -24,9 +24,11 @@ struct task_struct {};
2424#define STACK_TABLE_EPOCH_SHIFT 20
2525#define STROBE_MAX_STR_LEN 1
2626#define STROBE_MAX_CFGS 32
27+ #define READ_MAP_VAR_PAYLOAD_CAP \
28+ ((1 + STROBE_MAX_MAP_ENTRIES * 2) * STROBE_MAX_STR_LEN)
2729#define STROBE_MAX_PAYLOAD \
2830 (STROBE_MAX_STRS * STROBE_MAX_STR_LEN + \
29- STROBE_MAX_MAPS * (1 + STROBE_MAX_MAP_ENTRIES * 2) * STROBE_MAX_STR_LEN )
31+ STROBE_MAX_MAPS * READ_MAP_VAR_PAYLOAD_CAP )
3032
3133struct strobe_value_header {
3234 /*
@@ -355,7 +357,7 @@ static __always_inline uint64_t read_str_var(struct strobemeta_cfg *cfg,
355357 size_t idx , void * tls_base ,
356358 struct strobe_value_generic * value ,
357359 struct strobemeta_payload * data ,
358- void * payload )
360+ size_t off )
359361{
360362 void * location ;
361363 uint64_t len ;
@@ -366,7 +368,7 @@ static __always_inline uint64_t read_str_var(struct strobemeta_cfg *cfg,
366368 return 0 ;
367369
368370 bpf_probe_read_user (value , sizeof (struct strobe_value_generic ), location );
369- len = bpf_probe_read_user_str (payload , STROBE_MAX_STR_LEN , value -> ptr );
371+ len = bpf_probe_read_user_str (& data -> payload [ off ] , STROBE_MAX_STR_LEN , value -> ptr );
370372 /*
371373 * if bpf_probe_read_user_str returns error (<0), due to casting to
372374 * unsinged int, it will become big number, so next check is
@@ -378,14 +380,14 @@ static __always_inline uint64_t read_str_var(struct strobemeta_cfg *cfg,
378380 return 0 ;
379381
380382 data -> str_lens [idx ] = len ;
381- return len ;
383+ return off + len ;
382384}
383385
384- static __always_inline void * read_map_var (struct strobemeta_cfg * cfg ,
385- size_t idx , void * tls_base ,
386- struct strobe_value_generic * value ,
387- struct strobemeta_payload * data ,
388- void * payload )
386+ static __always_inline uint64_t read_map_var (struct strobemeta_cfg * cfg ,
387+ size_t idx , void * tls_base ,
388+ struct strobe_value_generic * value ,
389+ struct strobemeta_payload * data ,
390+ size_t off )
389391{
390392 struct strobe_map_descr * descr = & data -> map_descrs [idx ];
391393 struct strobe_map_raw map ;
@@ -397,11 +399,11 @@ static __always_inline void *read_map_var(struct strobemeta_cfg *cfg,
397399
398400 location = calc_location (& cfg -> map_locs [idx ], tls_base );
399401 if (!location )
400- return payload ;
402+ return off ;
401403
402404 bpf_probe_read_user (value , sizeof (struct strobe_value_generic ), location );
403405 if (bpf_probe_read_user (& map , sizeof (struct strobe_map_raw ), value -> ptr ))
404- return payload ;
406+ return off ;
405407
406408 descr -> id = map .id ;
407409 descr -> cnt = map .cnt ;
@@ -410,10 +412,10 @@ static __always_inline void *read_map_var(struct strobemeta_cfg *cfg,
410412 data -> req_meta_valid = 1 ;
411413 }
412414
413- len = bpf_probe_read_user_str (payload , STROBE_MAX_STR_LEN , map .tag );
415+ len = bpf_probe_read_user_str (& data -> payload [ off ] , STROBE_MAX_STR_LEN , map .tag );
414416 if (len <= STROBE_MAX_STR_LEN ) {
415417 descr -> tag_len = len ;
416- payload += len ;
418+ off += len ;
417419 }
418420
419421#ifdef NO_UNROLL
@@ -426,22 +428,22 @@ static __always_inline void *read_map_var(struct strobemeta_cfg *cfg,
426428 break ;
427429
428430 descr -> key_lens [i ] = 0 ;
429- len = bpf_probe_read_user_str (payload , STROBE_MAX_STR_LEN ,
431+ len = bpf_probe_read_user_str (& data -> payload [ off ] , STROBE_MAX_STR_LEN ,
430432 map .entries [i ].key );
431433 if (len <= STROBE_MAX_STR_LEN ) {
432434 descr -> key_lens [i ] = len ;
433- payload += len ;
435+ off += len ;
434436 }
435437 descr -> val_lens [i ] = 0 ;
436- len = bpf_probe_read_user_str (payload , STROBE_MAX_STR_LEN ,
438+ len = bpf_probe_read_user_str (& data -> payload [ off ] , STROBE_MAX_STR_LEN ,
437439 map .entries [i ].val );
438440 if (len <= STROBE_MAX_STR_LEN ) {
439441 descr -> val_lens [i ] = len ;
440- payload += len ;
442+ off += len ;
441443 }
442444 }
443445
444- return payload ;
446+ return off ;
445447}
446448
447449#ifdef USE_BPF_LOOP
@@ -455,14 +457,20 @@ struct read_var_ctx {
455457 struct strobemeta_payload * data ;
456458 void * tls_base ;
457459 struct strobemeta_cfg * cfg ;
458- void * payload ;
460+ size_t payload_off ;
459461 /* value gets mutated */
460462 struct strobe_value_generic * value ;
461463 enum read_type type ;
462464};
463465
464- static int read_var_callback (__u32 index , struct read_var_ctx * ctx )
466+ static int read_var_callback (__u64 index , struct read_var_ctx * ctx )
465467{
468+ /* lose precision info for ctx->payload_off, verifier won't track
469+ * double xor, barrier_var() is needed to force clang keep both xors.
470+ */
471+ ctx -> payload_off ^= index ;
472+ barrier_var (ctx -> payload_off );
473+ ctx -> payload_off ^= index ;
466474 switch (ctx -> type ) {
467475 case READ_INT_VAR :
468476 if (index >= STROBE_MAX_INTS )
@@ -472,14 +480,18 @@ static int read_var_callback(__u32 index, struct read_var_ctx *ctx)
472480 case READ_MAP_VAR :
473481 if (index >= STROBE_MAX_MAPS )
474482 return 1 ;
475- ctx -> payload = read_map_var (ctx -> cfg , index , ctx -> tls_base ,
476- ctx -> value , ctx -> data , ctx -> payload );
483+ if (ctx -> payload_off > sizeof (ctx -> data -> payload ) - READ_MAP_VAR_PAYLOAD_CAP )
484+ return 1 ;
485+ ctx -> payload_off = read_map_var (ctx -> cfg , index , ctx -> tls_base ,
486+ ctx -> value , ctx -> data , ctx -> payload_off );
477487 break ;
478488 case READ_STR_VAR :
479489 if (index >= STROBE_MAX_STRS )
480490 return 1 ;
481- ctx -> payload += read_str_var (ctx -> cfg , index , ctx -> tls_base ,
482- ctx -> value , ctx -> data , ctx -> payload );
491+ if (ctx -> payload_off > sizeof (ctx -> data -> payload ) - STROBE_MAX_STR_LEN )
492+ return 1 ;
493+ ctx -> payload_off = read_str_var (ctx -> cfg , index , ctx -> tls_base ,
494+ ctx -> value , ctx -> data , ctx -> payload_off );
483495 break ;
484496 }
485497 return 0 ;
@@ -501,15 +513,16 @@ static void *read_strobe_meta(struct task_struct *task,
501513 pid_t pid = bpf_get_current_pid_tgid () >> 32 ;
502514 struct strobe_value_generic value = {0 };
503515 struct strobemeta_cfg * cfg ;
504- void * tls_base , * payload ;
516+ size_t payload_off ;
517+ void * tls_base ;
505518
506519 cfg = bpf_map_lookup_elem (& strobemeta_cfgs , & pid );
507520 if (!cfg )
508521 return NULL ;
509522
510523 data -> int_vals_set_mask = 0 ;
511524 data -> req_meta_valid = 0 ;
512- payload = data -> payload ;
525+ payload_off = 0 ;
513526 /*
514527 * we don't have struct task_struct definition, it should be:
515528 * tls_base = (void *)task->thread.fsbase;
@@ -522,7 +535,7 @@ static void *read_strobe_meta(struct task_struct *task,
522535 .tls_base = tls_base ,
523536 .value = & value ,
524537 .data = data ,
525- .payload = payload ,
538+ .payload_off = 0 ,
526539 };
527540 int err ;
528541
@@ -540,6 +553,11 @@ static void *read_strobe_meta(struct task_struct *task,
540553 err = bpf_loop (STROBE_MAX_MAPS , read_var_callback , & ctx , 0 );
541554 if (err != STROBE_MAX_MAPS )
542555 return NULL ;
556+
557+ payload_off = ctx .payload_off ;
558+ /* this should not really happen, here only to satisfy verifer */
559+ if (payload_off > sizeof (data -> payload ))
560+ payload_off = sizeof (data -> payload );
543561#else
544562#ifdef NO_UNROLL
545563#pragma clang loop unroll(disable)
@@ -555,23 +573,23 @@ static void *read_strobe_meta(struct task_struct *task,
555573#pragma unroll
556574#endif /* NO_UNROLL */
557575 for (int i = 0 ; i < STROBE_MAX_STRS ; ++ i ) {
558- payload + = read_str_var (cfg , i , tls_base , & value , data , payload );
576+ payload_off = read_str_var (cfg , i , tls_base , & value , data , payload_off );
559577 }
560578#ifdef NO_UNROLL
561579#pragma clang loop unroll(disable)
562580#else
563581#pragma unroll
564582#endif /* NO_UNROLL */
565583 for (int i = 0 ; i < STROBE_MAX_MAPS ; ++ i ) {
566- payload = read_map_var (cfg , i , tls_base , & value , data , payload );
584+ payload_off = read_map_var (cfg , i , tls_base , & value , data , payload_off );
567585 }
568586#endif /* USE_BPF_LOOP */
569587
570588 /*
571589 * return pointer right after end of payload, so it's possible to
572590 * calculate exact amount of useful data that needs to be sent
573591 */
574- return payload ;
592+ return & data -> payload [ payload_off ] ;
575593}
576594
577595SEC ("raw_tracepoint/kfree_skb" )
0 commit comments