Hacktoberfest 2026: los issues que los mantenedores marcaron para octubre, abiertos y aptos para principiantes. Explorar issues de Hacktoberfest

SUPERCALL_KSTORAGE_LIST_IDS writes to an unvalidated userspace pointer with a raw memcpy → kernel KE

Abierto
#308 0 comentarios 0 reacciones 0 asignados Ver en GitHub

Los mantenedores suelen responder en 3 días

Nadie ha tomado este issue todavía.

Evaluación

Dificultad
3/5
Tiempo estimado
1-2 días
Aptitud para principiantes
72/100
Tipo de issue
Error
Claridad
Bien especificado
Estado de actividad
Activo
Stack tecnológico
android, c, linux

Línea de trabajo

Comienza en kernel/patch/common/supercall.c y kernel/patch/common/kstorage.c, y después inspecciona la ruta correspondiente lkm/supercall/kstorage.c. Sigue SUPERCALL_KSTORAGE_LIST_IDS desde arg2 hasta list_kstorage_ids() y ejecuta el reproducer proporcionado. El trabajo estará terminado cuando la salida de userspace se gestione de forma segura en ambas rutas afectadas y ya no se produzca la excepción del kernel por el puntero incorrecto.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

Summary

SUPERCALL_KSTORAGE_LIST_IDS (0x1043) forwards a userspace-supplied pointer into list_kstorage_ids() with data_is_user = false, so the kernel takes the raw memcpy() path instead of copy_to_user(). There is no access_ok() check anywhere in kstorage.c (verified: grep -c access_ok = 0). A bad or stale ids argument therefore makes the kernel write hashtable data to an arbitrary address in kernel context → data abort / KE.

Hit on a Redmi K50 Pro (MT6983, Android 14, KernelPatch 0.13.8 / 0xd08), reproducible kernel exception:

ZZ_INTERNAL: Kernel (KE),0,0,99,/data/vendor/core/,0,,KE at __memcpy+0x8c/0x180,Sat Sep 12 21:59:23 CST 2026

Root cause

kernel/patch/common/kstorage.c:

int list_kstorage_ids(int gid, long *ids, int idslen, bool data_is_user)
{
    if (gid < 0 || gid >= KSTRORAGE_MAX_GROUP_NUM) return -ENOENT;
    ...
    for (int b = 0; b < KSTORAGE_NBUCKETS; b++) {
        hlist_for_each_entry_rcu(pos, &kstorage_groups[gid][b], hnode)
        {
            if (cnt >= idslen) goto out;

            if (data_is_user) {
                int cplen = compat_copy_to_user(ids + cnt, &pos->did, sizeof(pos->did));
                if (cplen <= 0) { ...; goto out; }
            } else {
                memcpy(ids + cnt, &pos->did, sizeof(pos->did));   // <-- raw kernel write
            }
            cnt++;
        }
    }
    ...
}

kernel/patch/common/supercall.c — the userspace-reachable path passes false:

static long call_list_kstorage_ids(int gid, long *ids, int ids_len)
{
    return list_kstorage_ids(gid, ids, ids_len, false);   // ids is a __user pointer!
}
...
case SUPERCALL_KSTORAGE_LIST_IDS:
    return call_list_kstorage_ids((int)arg1, (long *)arg2, (int)arg3);

arg2 comes straight from the syscall registers, i.e. it is an untrusted userspace value. It is then dereferenced with a plain memcpy() in kernel context, with no access_ok() and no data_is_user flag.

The same pattern exists in the kp_kstorage_list_ids port used by the LKM (lkm/supercall/kstorage.c), so current main is affected too, not just the kernel/patch/common tree.

Reproduction

Minimal reproducer (aarch64, run as a uid in the su allowlist, e.g. root):

/* supercall channel: __NR_supercall == __NR3264_truncate == 45 */
#define SUPERCALL_KSTORAGE_LIST_IDS 0x1043
#define KSTORAGE_EXCLUDE_LIST_GROUP 1

long ver_and_cmd(long cmd) {
    /* MAJOR 0, MINOR 13, PATCH 8 -> 0x0d08 ; magic 0x1158 ; cmd in low 16 bits */
    return ((long)0x0d08 << 32) | (0x1158 << 16) | (cmd & 0xFFFF);
}

long *ids = malloc(sizeof(long) * 512);   /* or an intentionally bad pointer */
syscall(45, "su", ver_and_cmd(SUPERCALL_KSTORAGE_LIST_IDS),
        KSTORAGE_EXCLUDE_LIST_GROUP, ids, 512);

Accidentally passing a non-pointer in the ids slot (e.g. two integers that were meant to be (ids, len)) reproduces the crash deterministically: the kernel memcpys into an address like 0x200 = 512 and faults.

Impact

  • Availability: kernel data abort / KE → device hangs → forced long-press reboot (observed ro.boot.bootreason: reboot_longkey), MTK rebuild + fsck on the next boot.
  • Security: this is effectively a kernel arbitrary-write primitive: an authenticated supercall caller (any uid in the su allowlist / manager uid) controls both the destination address and the written value (pos->did, the stored kstorage key, i.e. attacker-chosen uid values). Writing 8 bytes at a controlled kernel address is directly usable for privilege escalation. The idslen bound only limits the number of writes, not where they land.
  • Any KPM (including third-party ones) that calls the exported list_kstorage_ids("...", ptr, len, false) with a userspace pointer inherits the same fault.

Suggested fix

In call_list_kstorage_ids() the data really is userspace, so either of these works:

  1. Pass data_is_user = true (one-line fix):
static long call_list_kstorage_ids(int gid, long *ids, int ids_len)
{
-   return list_kstorage_ids(gid, ids, ids_len, false);
+   return list_kstorage_ids(gid, ids, ids_len, true);
}
  1. Additionally validate in list_kstorage_ids() before taking the memcpy path, so future callers cannot regress:
if (!data_is_user && !access_ok(ids, (size_t)idslen * sizeof(long)))
    return -EFAULT;

and consider clamping idslen to the group size to also protect the VLA in list_ap_mod_exclude():

int list_ap_mod_exclude(uid_t *uids, int len)
{
    long ids[len];      /* VLA sized by an unvalidated caller argument */
    ...
    for (int i = 0; i < len; i++) uids[i] = (uid_t)ids[i];   /* writes len entries */
}

Environment

Device Redmi K50 Pro (22011211C, MT6983), Android 14
Kernel 5.10.209-android12-9-00019-g4ea09a298bb4-ab12292661
Root APatch, /data/adb/apd version 115032
KernelPatch 0xd08 (0.13.8), compile time 08:03:59 Aug 31 2026, config=android,release
Supercall SUPERCALL_KSTORAGE_LIST_IDS = 0x1043, KSTORAGE_EXCLUDE_LIST_GROUP = 1
Crash KE at __memcpy+0x8c/0x180, 2026-09-12 21:59:23 CST

Notes

  • Not a duplicate of #227 (that one is __sock_create on a Pixel).
  • kernel/patch/common/sucompat.c:481 (list_ap_mod_exclude) passes false too, but with a stack array, so that call site itself is fine — the bug is that the supercall path reuses the same false with an untrusted pointer.
  • I can produce the AEE dump and a disassembly of the faulting list_kstorage_ids frame if useful.
Lenguaje dominante
C
Estrellas
1.6k
Forks
393
Merge medio
3 d 23 h
PR fusionados (30 d)
7

Preparar el entorno

Este proyecto no incluye contenedor de desarrollo, Dockerfile ni guía de contribución, así que la configuración corre por tu cuenta: empieza por su README y consulta nuestra guía para la primera contribución para los pasos generales.

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de bmax121/KernelPatch

Todos los issues de bmax121/KernelPatch

Issues similares

Más issues de C

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.