@@ -571,236 +571,158 @@ FILLER(sys_poll_x, true)
571
571
return bpf_poll_parse_fds (data , false);
572
572
}
573
573
574
- #define MAX_IOVCNT 32
575
- #define MAX_IOVCNT_COMPAT 8
574
+ #ifdef CONFIG_COMPAT
575
+ #define MAX_IOVCNT 8
576
+ #else
577
+ #define MAX_IOVCNT 32
578
+ #endif
576
579
577
- static __always_inline int bpf_parse_readv_writev_bufs_64 (struct filler_data * data ,
580
+ static __always_inline int bpf_parse_readv_writev_bufs (struct filler_data * data ,
578
581
const void __user * iovsrc ,
579
582
unsigned long iovcnt ,
580
583
long retval ,
581
- int flags ,
582
- unsigned long * size )
584
+ int flags )
583
585
{
584
- const struct iovec * iov ;
585
586
int res = PPM_SUCCESS ;
586
587
unsigned long copylen ;
588
+ long size = 0 ;
587
589
int j ;
590
+ unsigned long iov_size = sizeof (struct iovec );
591
+ unsigned long len_off = offsetof(struct iovec , iov_len );
592
+ unsigned long base_off = offsetof(struct iovec , iov_base );
593
+ unsigned long ptr_size = sizeof (void * );
588
594
589
- copylen = iovcnt * sizeof (struct iovec );
590
- iov = (const struct iovec * )data -> tmp_scratch ;
595
+ #ifdef CONFIG_COMPAT
596
+ if (bpf_in_ia32_syscall ())
597
+ {
598
+ iov_size = sizeof (struct compat_iovec );
599
+ len_off = offsetof(struct compat_iovec , iov_len );
600
+ base_off = offsetof(struct compat_iovec , iov_base );
601
+ ptr_size = 4 ;
602
+ }
603
+ #endif
591
604
605
+ copylen = iovcnt * iov_size ;
592
606
if (copylen > SCRATCH_SIZE_MAX )
593
607
{
594
608
return PPM_FAILURE_FRAME_SCRATCH_MAP_FULL ;
595
609
}
596
610
597
611
#ifdef BPF_FORBIDS_ZERO_ACCESS
598
- if (copylen )
599
- if (bpf_probe_read_user (( void * ) iov ,
600
- ((copylen - 1 ) & SCRATCH_SIZE_MAX ) + 1 ,
601
- (void * )iovsrc ))
612
+ if (copylen )
613
+ if (bpf_probe_read_user (data -> tmp_scratch ,
614
+ ((copylen - 1 ) & SCRATCH_SIZE_MAX ) + 1 ,
615
+ (void * )iovsrc ))
602
616
#else
603
- if (bpf_probe_read_user (( void * ) iov ,
604
- copylen & SCRATCH_SIZE_MAX ,
605
- (void * )iovsrc ))
617
+ if (bpf_probe_read_user (data -> tmp_scratch ,
618
+ copylen & SCRATCH_SIZE_MAX ,
619
+ (void * )iovsrc ))
606
620
#endif
607
621
return PPM_FAILURE_INVALID_USER_MEMORY ;
608
622
609
- #pragma unroll
623
+
624
+ #pragma unroll
610
625
for (j = 0 ; j < MAX_IOVCNT ; ++ j ) {
611
626
if (j == iovcnt )
612
627
break ;
613
628
// BPF seems to require a hard limit to avoid overflows
614
- if (* size == LONG_MAX )
629
+ if (size == LONG_MAX )
615
630
break ;
616
631
617
- * size += iov [j ].iov_len ;
632
+ volatile unsigned curr_shift = j * iov_size + len_off ;
633
+ unsigned long shift_bounded = curr_shift & SCRATCH_SIZE_HALF ;
634
+ if (curr_shift > SCRATCH_SIZE_HALF )
635
+ break ;
636
+
637
+ long curr_len ;
638
+ if (ptr_size == 4 )
639
+ {
640
+ curr_len = * ((int * )(data -> tmp_scratch + shift_bounded ));
641
+ }
642
+ else
643
+ {
644
+ curr_len = * ((long * )(data -> tmp_scratch + shift_bounded ));
645
+ }
646
+ size += curr_len ;
618
647
}
619
648
620
649
if ((flags & PRB_FLAG_IS_WRITE ) == 0 )
621
- if (* size > retval )
622
- * size = retval ;
650
+ if (size > retval )
651
+ size = retval ;
623
652
624
- if (flags & PRB_FLAG_PUSH_SIZE && res == PPM_SUCCESS ) {
625
- res = bpf_push_u32_to_ring (data , (uint32_t )* size );
653
+ if (flags & PRB_FLAG_PUSH_SIZE ) {
654
+ res = bpf_push_u32_to_ring (data , (uint32_t )size );
626
655
CHECK_RES (res );
627
656
}
628
657
629
658
if (flags & PRB_FLAG_PUSH_DATA ) {
630
- if (* size > 0 ) {
659
+ if (size > 0 ) {
631
660
unsigned long off = _READ (data -> state -> tail_ctx .curoff );
632
- unsigned long remaining = * size ;
633
- int j ;
661
+ unsigned long remaining = size ;
634
662
635
- #pragma unroll
663
+ #pragma unroll
636
664
for (j = 0 ; j < MAX_IOVCNT ; ++ j ) {
637
665
volatile unsigned int to_read ;
638
-
639
666
if (j == iovcnt )
640
667
break ;
641
-
642
668
unsigned long off_bounded = off & SCRATCH_SIZE_HALF ;
643
669
if (off > SCRATCH_SIZE_HALF )
644
670
break ;
645
671
646
- if (iov [j ].iov_len <= remaining )
647
- to_read = iov [j ].iov_len ;
672
+ volatile unsigned len_curr_shift = j * iov_size + len_off ;
673
+ unsigned long len_shift_bounded = len_curr_shift & SCRATCH_SIZE_HALF ;
674
+ if (len_curr_shift > SCRATCH_SIZE_HALF )
675
+ break ;
676
+
677
+ long curr_len ;
678
+ if (ptr_size == 4 )
679
+ {
680
+ curr_len = * ((int * )(data -> tmp_scratch + len_shift_bounded ));
681
+ }
682
+ else
683
+ {
684
+ curr_len = * ((long * )(data -> tmp_scratch + len_shift_bounded ));
685
+ }
686
+ if (curr_len <= remaining )
687
+ to_read = curr_len ;
648
688
else
649
689
to_read = remaining ;
650
-
651
690
if (to_read > SCRATCH_SIZE_HALF )
652
691
to_read = SCRATCH_SIZE_HALF ;
653
692
654
- #ifdef BPF_FORBIDS_ZERO_ACCESS
655
- if (to_read )
656
- if (bpf_probe_read_user (& data -> buf [off_bounded ],
657
- ((to_read - 1 ) & SCRATCH_SIZE_HALF ) + 1 ,
658
- (void * )iov [j ].iov_base ))
659
- #else
660
- if (bpf_probe_read_user (& data -> buf [off_bounded ],
661
- to_read & SCRATCH_SIZE_HALF ,
662
- (void * )iov [j ].iov_base ))
663
- #endif
664
- return PPM_FAILURE_INVALID_USER_MEMORY ;
665
-
666
- remaining -= to_read ;
667
- off += to_read ;
668
- }
669
- } else {
670
- * size = 0 ;
671
- }
672
- return PPM_SUCCESS ;
673
- }
674
-
675
- return res ;
676
- }
677
-
678
- #ifdef CONFIG_COMPAT
679
- static __always_inline int bpf_parse_readv_writev_bufs_32 (struct filler_data * data ,
680
- const void __user * iovsrc ,
681
- unsigned long iovcnt ,
682
- long retval ,
683
- int flags ,
684
- unsigned long * size )
685
- {
686
- const struct compat_iovec * compat_iov ;
687
- int res = PPM_SUCCESS ;
688
- unsigned long copylen ;
689
- int j ;
690
-
691
- copylen = iovcnt * sizeof (struct compat_iovec );
692
- compat_iov = (const struct compat_iovec * )data -> tmp_scratch ;
693
-
694
- if (copylen > SCRATCH_SIZE_MAX )
695
- {
696
- return PPM_FAILURE_FRAME_SCRATCH_MAP_FULL ;
697
- }
698
-
699
- #ifdef BPF_FORBIDS_ZERO_ACCESS
700
- if (copylen )
701
- if (bpf_probe_read_user ((void * )compat_iov ,
702
- ((copylen - 1 ) & SCRATCH_SIZE_MAX ) + 1 ,
703
- (void * )iovsrc ))
704
- #else
705
- if (bpf_probe_read_user ((void * )compat_iov ,
706
- copylen & SCRATCH_SIZE_MAX ,
707
- (void * )iovsrc ))
708
- #endif
709
- return PPM_FAILURE_INVALID_USER_MEMORY ;
710
-
711
- #pragma unroll
712
- for (j = 0 ; j < MAX_IOVCNT_COMPAT ; ++ j ) {
713
- if (j == iovcnt )
714
- break ;
715
- // BPF seems to require a hard limit to avoid overflows
716
- if (* size == LONG_MAX )
717
- break ;
718
-
719
- * size += compat_iov [j ].iov_len ;
720
- }
721
-
722
- if ((flags & PRB_FLAG_IS_WRITE ) == 0 )
723
- if (* size > retval )
724
- * size = retval ;
725
-
726
- if (flags & PRB_FLAG_PUSH_SIZE && res == PPM_SUCCESS ) {
727
- res = bpf_push_u32_to_ring (data , (uint32_t )* size );
728
- CHECK_RES (res );
729
- }
730
-
731
- if (flags & PRB_FLAG_PUSH_DATA ) {
732
- if (* size > 0 ) {
733
- unsigned long off = _READ (data -> state -> tail_ctx .curoff );
734
- unsigned long remaining = * size ;
735
- int j ;
736
-
737
- // The 14 iovec count limit is due to old kernels verifiers
738
- // complaining.
739
- #pragma unroll
740
- for (j = 0 ; j < MAX_IOVCNT_COMPAT ; ++ j ) {
741
- volatile unsigned int to_read ;
742
-
743
- if (j == iovcnt )
693
+ volatile unsigned base_curr_shift = j * iov_size + base_off ;
694
+ unsigned long base_shift_bounded = base_curr_shift & SCRATCH_SIZE_HALF ;
695
+ if (base_curr_shift > SCRATCH_SIZE_HALF )
744
696
break ;
745
697
746
- unsigned long off_bounded = off & SCRATCH_SIZE_HALF ;
747
- if (off > SCRATCH_SIZE_HALF )
748
- break ;
749
-
750
- if (compat_iov [j ].iov_len <= remaining )
751
- to_read = compat_iov [j ].iov_len ;
698
+ unsigned long curr_base ;
699
+ if (ptr_size == 4 )
700
+ {
701
+ curr_base = * ((unsigned int * )(data -> tmp_scratch + base_shift_bounded ));
702
+ }
752
703
else
753
- to_read = remaining ;
754
-
755
- if (to_read > SCRATCH_SIZE_HALF )
756
- to_read = SCRATCH_SIZE_HALF ;
757
-
758
- #ifdef BPF_FORBIDS_ZERO_ACCESS
759
- if (to_read )
760
- if (bpf_probe_read_user (& data -> buf [off_bounded ],
761
- ((to_read - 1 ) & SCRATCH_SIZE_HALF ) + 1 ,
762
- (void * )compat_iov [j ].iov_base ))
763
- #else
704
+ {
705
+ curr_base = * ((unsigned long * )(data -> tmp_scratch + base_shift_bounded ));
706
+ }
707
+ #ifdef BPF_FORBIDS_ZERO_ACCESS
708
+ if (to_read )
764
709
if (bpf_probe_read_user (& data -> buf [off_bounded ],
765
- to_read & SCRATCH_SIZE_HALF ,
766
- (void * )compat_iov [j ].iov_base ))
767
- #endif
710
+ ((to_read - 1 ) & SCRATCH_SIZE_HALF ) + 1 ,
711
+ (void * )curr_base ))
712
+ #else
713
+ if (bpf_probe_read_user (& data -> buf [off_bounded ],
714
+ to_read & SCRATCH_SIZE_HALF ,
715
+ (void * )curr_base ))
716
+ #endif
768
717
return PPM_FAILURE_INVALID_USER_MEMORY ;
769
718
770
719
remaining -= to_read ;
771
720
off += to_read ;
772
721
}
773
722
} else {
774
- * size = 0 ;
723
+ size = 0 ;
775
724
}
776
725
777
- return PPM_SUCCESS ;
778
- }
779
- return res ;
780
- }
781
- #endif
782
-
783
- static __always_inline int bpf_parse_readv_writev_bufs (struct filler_data * data ,
784
- const void __user * iovsrc ,
785
- unsigned long iovcnt ,
786
- long retval ,
787
- int flags )
788
- {
789
- unsigned long size = 0 ;
790
- int res = PPM_SUCCESS ;
791
- if (!bpf_in_ia32_syscall ())
792
- {
793
- res = bpf_parse_readv_writev_bufs_64 (data , iovsrc , iovcnt , retval , flags , & size );
794
- }
795
- else
796
- {
797
- #ifdef CONFIG_COMPAT
798
- res = bpf_parse_readv_writev_bufs_32 (data , iovsrc , iovcnt , retval , flags , & size );
799
- #endif
800
- }
801
-
802
- if (flags & PRB_FLAG_PUSH_DATA && res == PPM_SUCCESS )
803
- {
804
726
data -> fd = bpf_syscall_get_argument (data , 0 );
805
727
data -> curarg_already_on_frame = true;
806
728
return __bpf_val_to_ring (data , 0 , size , PT_BYTEBUF , -1 , true, KERNEL );
@@ -4312,10 +4234,12 @@ FILLER(sys_recvfrom_x, true)
4312
4234
unsigned long val ;
4313
4235
uint16_t size = 0 ;
4314
4236
long retval ;
4315
- int addrlen ;
4237
+ int addrlen = 0 ;
4316
4238
int err = 0 ;
4317
4239
int res ;
4318
4240
int fd ;
4241
+ bool push = true;
4242
+ bool from_usr = false;
4319
4243
4320
4244
/*
4321
4245
* Push the common params to the ring
@@ -4324,6 +4248,7 @@ FILLER(sys_recvfrom_x, true)
4324
4248
res = f_sys_recv_x_common (data , retval );
4325
4249
CHECK_RES (res );
4326
4250
4251
+
4327
4252
if (retval >= 0 ) {
4328
4253
/*
4329
4254
* Get the fd
@@ -4350,29 +4275,26 @@ FILLER(sys_recvfrom_x, true)
4350
4275
*/
4351
4276
err = bpf_addr_to_kernel (usrsockaddr , addrlen ,
4352
4277
(struct sockaddr * )data -> tmp_scratch );
4353
- if (err >= 0 ) {
4278
+ if (err >= 0 )
4279
+ {
4354
4280
/*
4355
- * Convert the fd into socket endpoint information
4281
+ * Convert the fd into socket endpoint information
4356
4282
*/
4357
- size = bpf_fd_to_socktuple (data ,
4358
- fd ,
4359
- (struct sockaddr * )data -> tmp_scratch ,
4360
- addrlen ,
4361
- true,
4362
- true,
4363
- data -> tmp_scratch + sizeof (struct sockaddr_storage ));
4283
+ from_usr = true;
4364
4284
}
4365
- } else {
4285
+ else
4286
+ {
4287
+ // Do not send any socket endpoint info.
4288
+ push = false;
4289
+ }
4290
+ }
4291
+ if (push )
4292
+ {
4366
4293
/*
4367
- * Get socket endpoint information from fd if the user-provided *sockaddr is NULL
4368
- */
4369
- size = bpf_fd_to_socktuple (data ,
4370
- fd ,
4371
- NULL ,
4372
- 0 ,
4373
- false,
4374
- true,
4375
- data -> tmp_scratch + sizeof (struct sockaddr_storage ));
4294
+ * Get socket endpoint information from fd if the user-provided *sockaddr is NULL
4295
+ */
4296
+ size = bpf_fd_to_socktuple (data , fd , (struct sockaddr * )data -> tmp_scratch , addrlen , from_usr ,
4297
+ true, data -> tmp_scratch + sizeof (struct sockaddr_storage ));
4376
4298
}
4377
4299
}
4378
4300
0 commit comments