@@ -645,11 +645,10 @@ static unsigned long find_nearest_page(unsigned long vaddr)
645
645
.length = PAGE_SIZE ,
646
646
.align_mask = ~PAGE_MASK ,
647
647
};
648
- unsigned long low_limit = PAGE_SIZE , high_limit = TASK_SIZE ;
649
- unsigned long low_tramp = ~ 0UL , high_tramp = ~ 0UL ;
650
- unsigned long limit , low_4GB , high_4GB ;
648
+ unsigned long limit , low_limit = PAGE_SIZE , high_limit = TASK_SIZE ;
649
+ unsigned long cross_4GB , low_4GB , high_4GB ;
650
+ unsigned long low_tramp , high_tramp ;
651
651
unsigned long call_end = vaddr + 5 ;
652
- unsigned long aligned_4GB ;
653
652
654
653
/*
655
654
* The idea is to create a trampoline every 4GB, so we need to find
@@ -658,13 +657,10 @@ static unsigned long find_nearest_page(unsigned long vaddr)
658
657
* page.
659
658
*/
660
659
661
- if (vaddr > TASK_SIZE || vaddr < PAGE_SIZE )
662
- return - ENOMEM ;
663
-
664
- /* Restrict limits to be within [PAGE_SIZE,TASK_SIZE] boundary. */
665
660
low_4GB = call_end & MASK_4GB ;
666
661
high_4GB = low_4GB + __4GB ;
667
662
663
+ /* Restrict limits to be within [PAGE_SIZE,TASK_SIZE] boundary. */
668
664
if (!check_add_overflow (call_end , INT_MIN , & limit ))
669
665
low_limit = limit ;
670
666
if (low_limit == PAGE_SIZE )
@@ -674,24 +670,20 @@ static unsigned long find_nearest_page(unsigned long vaddr)
674
670
if (high_limit > TASK_SIZE )
675
671
high_limit = high_4GB = TASK_SIZE ;
676
672
673
+ /* Get 4GB alligned address that's within (call_end - 2GB, call_end + 2GB). */
674
+ if (low_limit <= low_4GB )
675
+ cross_4GB = low_4GB ;
676
+ else
677
+ cross_4GB = high_4GB ;
678
+
677
679
/* Search up from intersecting 4GB alignment address. */
678
- if (low_limit <= low_4GB ) {
679
- info .low_limit = low_4GB ;
680
- info .high_limit = high_limit ;
681
- } else {
682
- info .low_limit = high_4GB ;
683
- info .high_limit = high_limit ;
684
- }
680
+ info .low_limit = cross_4GB ;
681
+ info .high_limit = high_limit ;
685
682
high_tramp = vm_unmapped_area (& info );
686
683
687
684
/* Search down from intersecting 4GB alignment address. */
688
- if (low_limit <= low_4GB ) {
689
- info .low_limit = low_limit ;
690
- info .high_limit = low_4GB ;
691
- } else {
692
- info .low_limit = low_limit ;
693
- info .high_limit = high_4GB ;
694
- }
685
+ info .low_limit = low_limit ;
686
+ info .high_limit = cross_4GB ;
695
687
info .flags = VM_UNMAPPED_AREA_TOPDOWN ;
696
688
low_tramp = vm_unmapped_area (& info );
697
689
@@ -702,16 +694,11 @@ static unsigned long find_nearest_page(unsigned long vaddr)
702
694
if (IS_ERR_VALUE (low_tramp ))
703
695
return high_tramp ;
704
696
705
- if (low_limit <= low_4GB )
706
- aligned_4GB = low_4GB ;
707
- else
708
- aligned_4GB = high_4GB ;
709
-
710
- printk ("KRAVA find_nearest_page vaddr %lx high_tramp %lx low_tramp %lx aligned_4GB %lx\n" ,
711
- vaddr , low_tramp , high_tramp , aligned_4GB );
697
+ printk ("KRAVA find_nearest_page vaddr %lx high_tramp %lx low_tramp %lx cross_4GB %lx\n" ,
698
+ vaddr , high_tramp , low_tramp , cross_4GB );
712
699
713
700
/* Return address that's closest to the 4GB alignment address. */
714
- if (aligned_4GB - low_tramp < high_tramp - aligned_4GB )
701
+ if (cross_4GB - low_tramp < high_tramp - cross_4GB )
715
702
return low_tramp ;
716
703
return high_tramp ;
717
704
}
@@ -756,6 +743,9 @@ static struct uprobe_trampoline *get_uprobe_trampoline(unsigned long vaddr, bool
756
743
757
744
printk ("get_uprobe_trampoline1 vaddr %lx\n" , vaddr );
758
745
746
+ if (vaddr > TASK_SIZE || vaddr < PAGE_SIZE )
747
+ return NULL ;
748
+
759
749
hlist_for_each_entry (tramp , & state -> head_tramps , node ) {
760
750
if (is_reachable_by_call (tramp -> vaddr , vaddr )) {
761
751
printk ("get_uprobe_trampoline2 vaddr %lx -> tramp %lx\n" , vaddr , tramp -> vaddr );
@@ -907,10 +897,36 @@ asm (
907
897
908
898
extern u8 uprobe_trampoline_entry [];
909
899
900
+ static ssize_t
901
+ bpf_uprobe_trampoline_write (struct file * file , struct kobject * kobj ,
902
+ const struct bin_attribute * bin_attr ,
903
+ char * buf , loff_t off , size_t len )
904
+ {
905
+ struct mm_struct * mm = current -> mm ;
906
+ unsigned long vaddr = 0 ;
907
+ bool new = false;
908
+
909
+ if (kstrtoul (buf , 0 , & vaddr ))
910
+ return - EINVAL ;
911
+
912
+ mmap_write_lock (mm );
913
+ get_uprobe_trampoline (vaddr , & new );
914
+ mmap_write_unlock (mm );
915
+
916
+ trace_printk ("vaddr %lx new %d\n" , vaddr , new );
917
+ return strlen (buf );
918
+ }
919
+
920
+ static struct bin_attribute bin_attr_uprobe_trampoline_file __ro_after_init = {
921
+ .attr = { .name = "uprobe_trampoline" , .mode = 0666 , },
922
+ .write = bpf_uprobe_trampoline_write ,
923
+ };
924
+
910
925
static int __init arch_uprobes_init (void )
911
926
{
927
+ printk ("KRAVA TASK_SIZE %lx\n" , TASK_SIZE );
912
928
tramp_mapping_pages [0 ] = virt_to_page (uprobe_trampoline_entry );
913
- return 0 ;
929
+ return sysfs_create_bin_file ( kernel_kobj , & bin_attr_uprobe_trampoline_file ) ;
914
930
}
915
931
916
932
late_initcall (arch_uprobes_init );
0 commit comments