Hacktoberfest 2026 : les issues que les mainteneurs ont marquées pour octobre, ouvertes et accessibles aux débutants. Parcourir les issues Hacktoberfest

[Bug] lwp: sys_sigaction missing signal-number range check allows out-of-bounds read/write in kernel heap (RT-Smart)

Ouverte
#11,882 1 commentaire 0 réactions 0 personnes assignées Voir sur GitHub

Les mainteneurs répondent en général sous 1 jour

Personne n'a encore pris cette issue.

Évaluation

Difficulté
3/5
Temps estimé
1-2 jours
Accessibilité débutants
78/100
Type d'issue
Bug
Clarté
Clairement spécifiée
Activité
Active
Stack technique
c

Piste de recherche

Start with components/lwp/lwp_syscall.c at sys_sigaction() and components/lwp/lwp_signal.c at lwp_signal_action(), then trace the existing valid_signo_check() helper and its current caller. Reproduce the behavior with the supplied sigaction ELF on QEMU, including in-range, zero, and out-of-range signal numbers. Done means signal numbers outside [1, _LWP_NSIG] return -EINVAL before any signal-array access, while valid signals retain their existing behavior.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Description

RT-Thread Version

master @ 5d1fb66d (v5.4.0-dev, verified byte-identical to origin/master as of 2026-10-17). Affected since v5.0.0; introduced by commit ecf2d821 (#6641, "sync branch rt-smart", 2022-12-03).

Affected area

RT-Smart

Hardware/BSP vendor

Not applicable / Other

Architecture

ARM AArch64 (qemu-virt64-aarch64; the bug is architecture-independent C code in components/lwp)

Board and hardware details

QEMU virt machine (Cortex-A/-cpu max, GICv2), RT-Thread Smart build (RT_USING_SMART=y), root filesystem on virtio-blk (elm/FatFS). Any RT-Smart board is expected to be affected.

Develop Toolchain

aarch64-linux-musleabi gcc 7.3.0 (the official RT-Thread CI toolchain, toolchains-ci v1.7)

Describe the bug

sys_sigaction() never validates the sig argument and forwards it to lwp_signal_action(), which also performs no range check before indexing the fixed-size arrays embedded in the heap-allocated struct rt_lwp (_LWP_NSIG = 64):

// components/lwp/lwp_syscall.c:6747
sysret_t sys_sigaction(int sig, const struct k_sigaction *act,
                       struct k_sigaction *oact, size_t sigsetsize)
{ ... ret = lwp_signal_action(lwp, sig, pkact, pkoact); }   // sig unchecked

// components/lwp/lwp_signal.c:1108
rt_err_t lwp_signal_action(struct rt_lwp *lwp, int signo, ...)
{
    ...
    oact->sa_mask                   = lwp->signal.sig_action_mask[signo - 1];  // :1124 OOB read
    oact->__sa_handler._sa_handler  = lwp->signal.sig_action[signo - 1];       // :1125 OOB read
    ...
    lwp->signal.sig_action_mask[signo - 1] = act->sa_mask;                     // :1141 OOB write
    ...
    lwp->signal.sig_action[signo - 1] = act->__sa_handler._sa_handler;         // :1158 OOB write
    _signal_action_flag_u2k(signo, &lwp->signal, act);                         // :1161 more OOB RMW
}

Consequences, all reachable from any unprivileged user-mode program with a single svc (syscall 103):

  1. Arbitrary-offset 8-byte write with fully attacker-controlled value — sig_action[signo-1] = act->handler writes the user-supplied handler pointer at &lwp->signal.sig_action + (sig-1)*8 (offsetof(rt_lwp, signal.sig_action) = 800), for any positive or negative offset (sig = 0 → index −1). sig_action_mask[], and the SA_NODEFER/SA_ONSTACK/SA_RESTART/SA_SIGINFO sigsets give further OOB read-modify-write primitives.
  2. Kernel heap disclosure — the oact path copies sig_action[signo-1]/sig_action_mask[signo-1] from beyond the arrays back to user memory.
  3. Deterministic kernel crash — a far offset hits unmapped kernel VA and kills the whole kernel.

Note the range-check helper valid_signo_check() already exists since #9981 (2025-02) but is only wired into lwp_pgrp_signal_kill(); the sigaction path was missed.

Reproduction (RT-Smart on QEMU virt, full chain: user ELF → svc #0 → kernel):

msh /> sys_log 1
msh /> /sigaction_poc.elf
[poc] control sigaction(10) ret=0x0000000000000000          # in-range call: OK, system alive
[poc] sig=0x48 ... mask0=0x006a626f5f70776c                  # OOB READ: kernel heap string ("lwp_obj") leaked to user
[poc] OOB WRITE sigaction(200) handler=0x4142434445464748
[poc] write ret=0 / readback handler=0x4142434445464748      # OOB WRITE: attacker value written & read back

GDB hardware-watchpoint capture (kernel address, before/after):

Breakpoint: lwp_signal_action (lwp=0xffff000000273e90, signo=200, ...)
  #1 sys_sigaction (sig=200, ...) at lwp_syscall.c:6794
  #2 _SVC_Handler at lwp_gcc.S:177        <- user `svc #0`
&lwp->signal.sig_action[199] = 0xffff0000002747e8    (offsetof = 800)
Old value = 0
New value = 4702394921427289928 (0x4142434445464748)

Far-offset variant (sig = 0x1000000) — instant kernel death, fault address matches the computed target exactly:

Data abort, fault addr = 0xffff0000082741a8
   = lwp(0xffff000000273e90) + 0x320 + (0x1000000-1)*8
  _get_sighandler_locked lwp_signal.c:371  <- sys_sigaction:6794  <- SVC_Handler

Expected behavior

sigaction() with a signal number outside [1, 64] must fail with EINVAL before touching any array, as Linux does.

Suggested fix

sysret_t sys_sigaction(int sig, ...)
{
    if (sig <= 0 || (unsigned long)sig > _LWP_NSIG)
        return -EINVAL;
    ...
}

(or call the existing valid_signo_check() inside lwp_signal_action(), which also protects future callers).

Other additional context

  • Severity: CVSS 3.1 AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H = 7.8 (High); CWE-129 → CWE-787/CWE-125.
  • Attack prerequisite (explicit): attacker can run an unprivileged RT-Smart user program on the device (e.g. a third-party app). No other privilege or race is needed; the primitive is deterministic.
  • Related but distinct: CVE-2025-5866/CVE-2025-5868 are about the unchecked how index in sys_sigprocmask/sys_thread_sigprocmask; this report is the unchecked signal number in sys_sigaction (different parameter, different function) and is not covered by any existing CVE/issue — I found no prior report for it.
  • All evidence above is from a real RT-Thread Smart kernel running under QEMU (no host-side sanitizers involved). Repro sources/logs: kernel components/lwp/{lwp_syscall.c,lwp_signal.c}; happy to attach the freestanding user-space PoC ELF source if wanted.
Langage dominant
C
Étoiles
12.3k
Forks
5.5k
Merge moyen
7 j 22 h
PR mergées (30 j)
30

Préparer son environnement

Ouvrir dans Codespaces

Lance le conteneur de développement du projet dans votre navigateur, avec votre propre compte GitHub.

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Autres issues de RT-Thread/rt-thread

Toutes les issues de RT-Thread/rt-thread

Issues similaires

Plus d'issues C

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.