Skip to content

Commit 919c917

Browse files
committed
test
1 parent 892566c commit 919c917

File tree

2 files changed

+109
-31
lines changed

2 files changed

+109
-31
lines changed

arch/x86/kernel/uprobes.c

Lines changed: 47 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -645,11 +645,10 @@ static unsigned long find_nearest_page(unsigned long vaddr)
645645
.length = PAGE_SIZE,
646646
.align_mask = ~PAGE_MASK,
647647
};
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;
651651
unsigned long call_end = vaddr + 5;
652-
unsigned long aligned_4GB;
653652

654653
/*
655654
* 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)
658657
* page.
659658
*/
660659

661-
if (vaddr > TASK_SIZE || vaddr < PAGE_SIZE)
662-
return -ENOMEM;
663-
664-
/* Restrict limits to be within [PAGE_SIZE,TASK_SIZE] boundary. */
665660
low_4GB = call_end & MASK_4GB;
666661
high_4GB = low_4GB + __4GB;
667662

663+
/* Restrict limits to be within [PAGE_SIZE,TASK_SIZE] boundary. */
668664
if (!check_add_overflow(call_end, INT_MIN, &limit))
669665
low_limit = limit;
670666
if (low_limit == PAGE_SIZE)
@@ -674,24 +670,20 @@ static unsigned long find_nearest_page(unsigned long vaddr)
674670
if (high_limit > TASK_SIZE)
675671
high_limit = high_4GB = TASK_SIZE;
676672

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+
677679
/* 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;
685682
high_tramp = vm_unmapped_area(&info);
686683

687684
/* 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;
695687
info.flags = VM_UNMAPPED_AREA_TOPDOWN;
696688
low_tramp = vm_unmapped_area(&info);
697689

@@ -702,16 +694,11 @@ static unsigned long find_nearest_page(unsigned long vaddr)
702694
if (IS_ERR_VALUE(low_tramp))
703695
return high_tramp;
704696

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);
712699

713700
/* 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)
715702
return low_tramp;
716703
return high_tramp;
717704
}
@@ -756,6 +743,9 @@ static struct uprobe_trampoline *get_uprobe_trampoline(unsigned long vaddr, bool
756743

757744
printk("get_uprobe_trampoline1 vaddr %lx\n", vaddr);
758745

746+
if (vaddr > TASK_SIZE || vaddr < PAGE_SIZE)
747+
return NULL;
748+
759749
hlist_for_each_entry(tramp, &state->head_tramps, node) {
760750
if (is_reachable_by_call(tramp->vaddr, vaddr)) {
761751
printk("get_uprobe_trampoline2 vaddr %lx -> tramp %lx\n", vaddr, tramp->vaddr);
@@ -907,10 +897,36 @@ asm (
907897

908898
extern u8 uprobe_trampoline_entry[];
909899

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+
910925
static int __init arch_uprobes_init(void)
911926
{
927+
printk("KRAVA TASK_SIZE %lx\n", TASK_SIZE);
912928
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);
914930
}
915931

916932
late_initcall(arch_uprobes_init);

tools/testing/selftests/bpf/prog_tests/uprobe_syscall.c

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,66 @@ static void test_uprobe_sigill(void)
799799
ASSERT_EQ(WTERMSIG(status), SIGILL, "WTERMSIG");
800800
}
801801

802+
#define UPROBE_TRAMPOLINE_TEST_FILE "/sys/kernel/uprobe_trampoline"
803+
804+
static int write_trampoline(unsigned long vaddr)
805+
{
806+
size_t n, ret;
807+
char buf[30];
808+
int fd;
809+
810+
fprintf(stderr, "KRAVA vaddr %lx\n", vaddr);
811+
812+
n = sprintf(buf, "%lu", vaddr);
813+
814+
fd = open(UPROBE_TRAMPOLINE_TEST_FILE, O_WRONLY);
815+
if (fd < 0)
816+
return -errno;
817+
818+
ret = write(fd, buf, n);
819+
close(fd);
820+
return ret != n ? (int) ret : 0;
821+
}
822+
823+
#define TASK_SIZE 0x7ffffffff000
824+
static void test_trampoline(void)
825+
{
826+
int i;
827+
828+
fprintf(stderr, "KRAVA 1\n");
829+
830+
write_trampoline(0x2000);
831+
write_trampoline((1UL << 32) + 0x2000);
832+
write_trampoline((1UL << 32)*10 + 0x1000);
833+
write_trampoline((1UL << 32)*10 - 0x1000);
834+
835+
fprintf(stderr, "KRAVA 2\n");
836+
837+
for (i = 0; i < 10; i++) {
838+
write_trampoline((1UL << 32)*10 - i*1*(1UL << 30));
839+
write_trampoline((1UL << 32)*10 - i*1*(1UL << 30) + 4096);
840+
}
841+
842+
fprintf(stderr, "KRAVA 3\n");
843+
844+
for (i = 0; i < 10; i++) {
845+
write_trampoline((1UL << 32)*10 + i*1*(1UL << 30));
846+
write_trampoline((1UL << 32)*10 + i*1*(1UL << 30) + 4096);
847+
}
848+
849+
fprintf(stderr, "KRAVA 4\n");
850+
851+
write_trampoline(TASK_SIZE - 0x1000);
852+
write_trampoline(TASK_SIZE - 0x2000);
853+
854+
fprintf(stderr, "KRAVA 5\n");
855+
856+
for (i = 0; i < 10; i++) {
857+
write_trampoline(TASK_SIZE + i*1*(1UL << 30));
858+
write_trampoline(TASK_SIZE + i*1*(1UL << 30) + 4096);
859+
}
860+
}
861+
802862
static void __test_uprobe_syscall(void)
803863
{
804864
if (test__start_subtest("uretprobe_regs_equal"))
@@ -823,6 +883,8 @@ static void __test_uprobe_syscall(void)
823883
test_uprobe_regs_equal(false);
824884
if (test__start_subtest("regs_change"))
825885
test_regs_change();
886+
if (test__start_subtest("trampoline"))
887+
test_trampoline();
826888
}
827889
#else
828890
static void __test_uprobe_syscall(void)

0 commit comments

Comments
 (0)