--- /dev/null
+# Security Fix Plan - 2026-05-26
+
+## Contexto
+
+Este plano é baseado na reanálise completa do AdrOS (ZIP CDFA4C08) realizada em 2026-05-25, cruzada com as correções já implementadas em sessões anteriores (documentadas nas memórias do sistema).
+
+## Status dos Itens do Relatório
+
+### Itens JÁ Corrigidos (sessões anteriores)
+
+| ID | Descrição | Status |
+|---|---|---|
+| A16 | pmm_decref underflow check | ✅ Corrigido |
+| A03 | pread/pwrite mode validation | ✅ Corrigido |
+| A04 | O_RDONLY\|O_TRUNC rejeição | ✅ Corrigido |
+| A14 | truncate/ftruncate VFS integration | ✅ Corrigido |
+| A17 | varargs open/openat/fcntl | ✅ Corrigido |
+| U04 | execl/execlp varargs | ✅ Corrigido |
+| U02 | scanf %s limit (255 bytes) | ✅ Corrigido |
+| A18 | shell command substitution | ✅ Corrigido |
+| A13 | posix_spawn PID fix | ✅ Corrigido |
+| A19 | access() mode implementation | ✅ Corrigido |
+| K21 | O_NOFOLLOW implementation | ✅ Corrigido |
+| K35 | socket bounce buffers (SMAP) | ✅ Corrigido |
+| K14 | SHM permissions | ✅ Corrigido |
+| K22 | dlopen per-process isolation | ✅ Corrigido |
+| K17 | futex keying (mm, uaddr) | ⚠️ Parcial (addr_space adicionado, mas não robusto) |
+| K24 | NX flag in SHM | ⚠️ TODO (desabilitado temporariamente) |
+
+### Itens Tentados mas Causaram Regressões
+
+| ID | Descrição | Status |
+|---|---|---|
+| K12/K13/K23 | /proc access control (UID checks) | ❌ Requer infraestrutura UID completa |
+| K15 | raw socket privilege (UID check) | ❌ Requer infraestrutura UID completa |
+
+### Itens Remanescentes (não abordados)
+
+Abaixo estão os itens que ainda precisam ser corrigidos, organizados por prioridade.
+
+---
+
+## Fase 1: Críticos de Memória e Parser (7 itens)
+
+### C1: ELF Loader p_filesz > p_memsz Validation
+**Severidade:** CRÍTICA
+**Arquivos:** `src/arch/x86/elf.c`
+**Problema:** O loader valida `p_offset + p_filesz <= file_len` mas não valida `p_filesz <= p_memsz`. Isso permite escrever além da área mapeada.
+**Solução:**
+- Adicionar validação `if (ph[i].p_filesz > ph[i].p_memsz) return -EINVAL;` em `elf32_load_segments`
+- Aplicar mesma validação em `elf32_load_shared_lib_at` (dlopen path)
+- Validar também `p_align`, `e_phentsize`, `e_phnum`, tipo ELF, endianess e ABI
+
+### C2: NX por Default em Todos os Mapeamentos User
+**Severidade:** CRÍTICA
+**Arquivos:** `src/kernel/syscall.c`, `src/arch/x86/elf.c`, `src/kernel/shm.c`, `src/drivers/vbe.c`
+**Problema:** NX não é aplicado por default em mmap anônimo, brk, stack inicial, SHM e fb0_mmap.
+**Solução:**
+- `mmap`: Adicionar `VMM_FLAG_NX` por default, remover apenas se `PROT_EXEC` presente
+- `brk`: Adicionar `VMM_FLAG_NX` ao criar heap
+- `elf32_load_user_from_initrd`: Stack inicial deve ter NX
+- `shm_at`: Mapear com NX por default (já documentado como TODO K24)
+- `fb0_mmap`: Aplicar NX e respeitar argumento `prot`
+
+### C3: Initrd TAR Parser com Limites de Tamanho
+**Severidade:** CRÍTICA
+**Arquivo:** `src/drivers/initrd.c`
+**Problema:** Loop TAR sem limite pelo tamanho do initrd, `tar_is_zero_block` sem validar 512 bytes disponíveis, acesso a header/payload sem bounds checking.
+**Solução:**
+- Manter `end = base + size` e validar cada acesso
+- Validar `p + TAR_BLOCK <= end` antes de `tar_is_zero_block`
+- Validar `p + sizeof(tar_header_t) + payload <= end` antes de ler
+- Validar checksum TAR e overflow em `adv`
+- Validar `LZ4B_HDR_SIZE + comp_sz <= size`
+
+### C4: pmm_boot.c Multiboot2 Parsing com Cursor/Limit
+**Severidade:** CRÍTICA
+**Arquivo:** `src/arch/x86/pmm_boot.c`
+**Problema:** Loops sem validação de `total_size`, `tag->size >= 8`, limite do buffer, nem `mmap->entry_size`.
+**Solução:**
+- Portar lógica de cursor/limite de `arch_early_setup.c` para `pmm_boot.c`
+- Validar `tag->size >= 8` antes de acessar campos
+- Validar `cursor + tag->size <= end` antes de `MB2_TAG_NEXT`
+- Validar `mmap->entry_size` e bounds do array de entradas
+
+### C5: VMA Table per Process para mprotect Robusto
+**Severidade:** CRÍTICA
+**Arquivos:** `src/kernel/syscall.c`, `include/process.h`
+**Problema:** `mprotect` tem fallback permissivo para endereços não modelados como VMA.
+**Solução:**
+- Criar tabela VMA unificada por processo (struct vma_region com start, end, prot)
+- Registrar cada mmap, brk, stack, ELF segment na tabela VMA
+- `mprotect` deve aceitar apenas ranges completamente cobertos por VMAs
+- Remover fallback permissivo
+
+### C6: Ext2 Superblock/GDT Validation
+**Severidade:** CRÍTICA
+**Arquivo:** `src/kernel/ext2.c`
+**Problema:** `s_blocks_per_group`, `s_inodes_per_group` podem ser zero; `num_groups` e `gdt_bytes` podem overflowar; validação incompleta.
+**Solução:**
+- Validar `s_blocks_per_group > 0` e `s_inodes_per_group > 0`
+- Validar overflow em `num_groups = (s_blocks_count - s_first_data_block + s_blocks_per_group - 1) / s_blocks_per_group`
+- Validar `gdt_bytes = num_groups * sizeof(ext2_group_desc_t)` não overflow
+- Validar `block_size` é potência de 2 e >= 1024
+- Validar inode size, GDT blocks e bitmap blocks contra limites do dispositivo
+
+### C7: FAT BPB Validation
+**Severidade:** CRÍTICA
+**Arquivo:** `src/kernel/fat.c`
+**Problema:** `total_sectors - (data_lba - partition_lba)` pode underflowar; `sectors_per_cluster` não validado como potência de 2; cadeias de cluster sem limite.
+**Solução:**
+- Validar `data_lba >= partition_lba` antes de subtração
+- Validar `sectors_per_cluster` é potência de 2 entre 1 e 128
+- Validar `fat_size`, `reserved_sectors`, `root_cluster` contra limites do dispositivo
+- Limitar caminhada de cluster por `total_clusters` em `fat_extend_chain`/`fat_free_chain`
+- Detectar ciclos em cadeias de cluster
+
+---
+
+## Fase 2: Isolamento e Políticas de Segurança (8 itens)
+
+### H1: AIO fd Mode e Read-Only Mount Validation
+**Severidade:** ALTA
+**Arquivo:** `src/kernel/syscall.c`
+**Problema:** `syscall_aio_rw_impl` não reutiliza política de read/write/pread/pwrite.
+**Solução:**
+- Centralizar validação de modo e mount em helper usado por todas as rotas de I/O
+- `aio_write` deve rejeitar fd `O_RDONLY` e mount `MS_RDONLY`
+- `aio_read` deve rejeitar fd `O_WRONLY`
+
+### H2: /proc Access Control
+**Severidade:** ALTA
+**Arquivo:** `src/kernel/procfs.c`
+**Problema:** Entradas `/proc/dmesg`, `/proc/cmdline`, `/proc/<pid>/status`, `/proc/<pid>/maps`, `/proc/<pid>/cmdline` sem controle de acesso.
+**Solução:**
+- Implementar função `proc_may_access(pid, uid)` similar a `ptrace_may_access`
+- Redigir endereços em `/proc/<pid>/maps` para não-root
+- Implementar hidepid (2 = hide all pids from non-root)
+- Usar pin/refcount ou snapshot sob lock para evitar UAF
+- **NOTA:** Requer infraestrutura UID completa (ver Fase 4)
+
+### H3: SHM Permissões Completas
+**Severidade:** ALTA
+**Arquivo:** `src/kernel/shm.c`
+**Problema:** Falta mode por segmento, grupos, attach read-only, NX default.
+**Solução:**
+- Adicionar campo `mode`, `gid` em `struct shm_segment`
+- Implementar attach read-only (sem flag SHM_RDONLY no momento)
+- Aplicar NX por default (já documentado como TODO K24)
+- Modelar uid/gid/mode como SysV/POSIX SHM
+
+### H4: SOCK_RAW Privilege Check
+**Severidade:** ALTA
+**Arquivo:** `src/kernel/socket.c`
+**Problema:** `ksocket_create` aceita `SOCK_RAW` sem checar `current_process->euid`.
+**Solução:**
+- Adicionar verificação `if (type == SOCK_RAW && current_process->euid != 0) return -EPERM`
+- **NOTA:** Requer infraestrutura UID completa (ver Fase 4)
+
+### H5: Futex Robusto com Spinlock e Shared Memory Keying
+**Severidade:** ALTA
+**Arquivo:** `src/kernel/syscall.c`
+**Problema:** Tabela global sem lock; futex em memória compartilhada não usa objeto físico/inode+offset.
+**Solução:**
+- Adicionar spinlock para proteger tabela global de futex
+- Chavear futex privado por `(mm, uaddr)` (já parcialmente feito)
+- Chavear futex compartilhado por página física ou inode+offset
+- Coordenar wait/wake com scheduler de forma mais robusta
+
+### H6: Remover Fixed VAs (KVA_PHYS_MAP)
+**Severidade:** ALTA
+**Arquivos:** `src/hal/x86/mm.c`, `src/drivers/virtio_blk.c`, `include/arch/x86/kernel_va_map.h`
+**Problema:** `hal_mm_map_physical_range` usa sempre `KVA_PHYS_MAP` sem alocador; colisão virtio-blk/E1000 em VAs fixas.
+**Solução:**
+- Criar alocador de VA kernel para MMIO/DMA/mapeamentos temporários
+- Remover VAs fixas locais (KVA_PHYS_MAP)
+- Resolver colisão virtio-blk (0xC0340000) com E1000 (0xC0330000..0xC034FFFF)
+
+### H7: Tmpfs Locking, Quotas e Overflow Validation
+**Severidade:** ALTA
+**Arquivo:** `src/kernel/tmpfs.c`
+**Problema:** Sem locks, sem quotas, `new_cap *= 2` pode virar zero, metadados não inicializados.
+**Solução:**
+- Adicionar lock por árvore/inode
+- Adicionar quota global
+- Validar overflow em `new_cap *= 2`
+- Inicializar `uid/gid/mode` corretamente
+
+### H8: rumpuser_free Alignment Handling
+**Severidade:** ALTA
+**Arquivo:** `src/rump/rumpuser_adros.c`
+**Problema:** Quando `alignment > 16`, `rumpuser_free` chama `kfree(mem)` diretamente em vez do ponteiro bruto.
+**Solução:**
+- Armazenar header uniforme para todas as alocações rumpuser
+- Recuperar ponteiro bruto antes de chamar `kfree`
+
+---
+
+## Fase 3: Polimento de VFS e Userspace (12 itens)
+
+### M1: VFS Permissions - mode != 0 e execve Bit Check
+**Severidade:** MÉDIA
+**Arquivos:** `src/kernel/fs.c`, `src/kernel/syscall.c`
+**Problema:** `vfs_check_permission` retorna sucesso quando `node->mode == 0`; `execve` não verifica bit executável.
+**Solução:**
+- Remover caso permissivo quando `mode == 0`
+- `execve` deve verificar bit executável do inode (S_IXUSR|S_IXGRP|S_IXOTH)
+
+### M2: POSIX access() Completo
+**Severidade:** MÉDIA
+**Arquivo:** `src/kernel/syscall.c`
+**Problema:** `access()` simplificado - `R_OK` assume legível se existir, `X_OK` testa apenas arquivo regular.
+**Solução:**
+- Implementar `F_OK/R_OK/W_OK/X_OK` sobre mesma função de permissão
+- Usar uid/gid reais em vez de efetivos
+
+### M3: O_NOFOLLOW -ELOOP Return
+**Severidade:** MÉDIA
+**Arquivos:** `src/kernel/syscall.c`, `src/kernel/fs.c`
+**Problema:** `vfs_lookup_nofollow` evita seguir symlink mas não retorna erro POSIX claro quando componente final é symlink.
+**Solução:**
+- Se `O_NOFOLLOW` presente e componente final for `FS_SYMLINK`, retornar `-ELOOP`
+
+### M4: Truncate Fallback Remoção
+**Severidade:** MÉDIA
+**Arquivo:** `src/kernel/fs.c`
+**Problema:** `vfs_truncate` altera apenas `node->length` se backend não implementa truncate.
+**Solução:**
+- Sem `i_ops->truncate`, retornar `-ENOSYS`
+- Limitar fallback a filesystems explicitamente marcados como seguros (se necessário)
+
+### M5: Socket copy_to_user Ignored Failures
+**Severidade:** MÉDIA
+**Arquivo:** `src/kernel/syscall.c`
+**Problema:** `accept`, `recvfrom`, `recvmsg`, `getsockname`, `getpeername` usam `(void)copy_to_user(...)`.
+**Solução:**
+- Retornar `-EFAULT` quando copyout obrigatório falhar
+- Para campos opcionais, validar ponteiro e tamanho antes
+
+### M6: Overlayfs Wrapper Lifetime/Refcount
+**Severidade:** MÉDIA
+**Arquivo:** `src/kernel/overlayfs.c`
+**Problema:** `overlay_wrap_child` aloca wrappers sem caminho claro de liberação.
+**Solução:**
+- Introduzir cache/refcount/release para wrappers
+- Ou simplificar overlayfs até haver ownership claro
+
+### M7: fb0_mmap Respeitar prot e NX
+**Severidade:** MÉDIA
+**Arquivo:** `src/drivers/vbe.c`
+**Problema:** `fb0_mmap` ignora argumento `prot` e sempre mapeia RW sem NX.
+**Solução:**
+- Respeitar `PROT_READ/PROT_WRITE`
+- Negar execução e aplicar NX
+
+### M8: CSPRNG Implementation
+**Severidade:** MÉDIA
+**Arquivos:** `src/kernel/devfs.c`, `include/net/lwipopts.h`, `user/ulibc/src/rand.c`, `src/rump/rumpuser_adros.c`
+**Problema:** `/dev/random`, `/dev/urandom`, lwIP, libc usam RNGs previsíveis.
+**Solução:**
+- Implementar CSPRNG de kernel com seed de entropia real (RDRND se disponível, ou TSC + timer)
+- Fazer lwIP/devfs/userspace consumirem essa fonte
+
+### M9: mkstemp Retry Multiple Names
+**Severidade:** MÉDIA
+**Arquivo:** `user/ulibc/src/stdlib.c`
+**Problema:** `mkstemp` tenta apenas um nome; se colidir, falha.
+**Solução:**
+- Após corrigir CSPRNG, fazer `mkstemp` tentar múltiplos nomes (loop com limite)
+- Documentar/desencorajar `tmpnam`
+
+### M10: fcntl Varargs em ulibc
+**Severidade:** MÉDIA
+**Arquivo:** `user/ulibc/src/unistd.c`
+**Problema:** `fcntl` lê vararg para `F_GETFD` e `F_GETFL` que não exigem argumento.
+**Solução:**
+- Ler vararg somente nos comandos que precisam: `F_SETFD`, `F_SETFL`, `F_DUPFD`, `F_DUPFD_CLOEXEC`
+
+### M11: newlib libgloss Varargs
+**Severidade:** MÉDIA
+**Arquivo:** `newlib/libgloss/adros/posix_stubs.c`
+**Problema:** `fcntl` e `openat` leem vararg incondicionalmente.
+**Solução:**
+- Aplicar mesma correção que ulibc: leitura condicional de vararg
+
+### M12: scanf Field Width e Buffer Size
+**Severidade:** MÉDIA
+**Arquivo:** `user/ulibc/src/stdio.c`
+**Problema:** Limite 255 bytes não resolve API - `%s` não sabe tamanho real do buffer.
+**Solução:**
+- Respeitar largura de campo (ex: `%255s`)
+- Suportar formatos de largura corretamente
+- Auditar comandos que usam `%s`
+
+---
+
+## Fase 4: Infraestrutura UID (Pré-requisito para H2, H4)
+
+### UID Infrastructure
+**Severidade:** ALTA (pré-requisito)
+**Descrição:** AdrOS é um OS single-user sem infraestrutura de autenticação multi-usuário completa.
+**Solução:**
+- Implementar `/etc/passwd` parsing
+- Implementar login com autenticação
+- UID/EUID inheritance em fork/clone
+- Per-process mount namespaces (opcional, mas desejável)
+- **Estimativa:** 3-4 dias de trabalho
+
+---
+
+## Fase 5: Low Priority (2 itens)
+
+### L1: Path Truncation - ENAMETOOLONG
+**Severidade:** BAIXA
+**Arquivos:** `src/kernel/syscall.c`, `src/kernel/fs.c`
+**Problema:** `path_resolve_user` e `vfs_lookup_parent` truncam strings silenciosamente.
+**Solução:**
+- Tratar truncamento como erro em todos os caminhos de path
+- Retornar `-ENAMETOOLONG` quando input excede limite
+
+### L2: getlogin/who Session/TTY/utmp
+**Severidade:** BAIXA
+**Arquivos:** `user/ulibc/src/unistd.c`, `user/cmds/who/who.c`
+**Problema:** `getlogin()` usa fallback `"root"`, `who` imprime linha fixa.
+**Solução:**
+- Conectar login a sessões/TTY/utmp
+- Retornar erro quando não houver informação confiável
+
+---
+
+## Itens NÃO Incluídos (Falsos Positivos ou Fora de Escopo)
+
+### sysenter.S (A02)
+**Status:** NÃO incluído neste plano
+**Motivo:** Relatório menciona problema mas validação atual (`ECX < 0xC0000000` e `ECX >= 8`) é razoável para ABI sysenter. Melhoria seria mudança de ABI, não correção de bug.
+
+### posix_spawn Kernel Implementation (A13)
+**Status:** NÃO incluído neste plano
+**Motivo:** Wrapper userspace foi corrigido. Implementação kernel como fork+execve é padrão POSIX e funciona corretamente.
+
+---
+
+## Ordem de Execução Sugerida
+
+1. **Fase 1 (Críticos):** 7 itens - estimativa 10-14 dias
+2. **Fase 4 (UID Infrastructure):** Pré-requisito para H2, H4 - estimativa 3-4 dias
+3. **Fase 2 (Isolamento):** 8 itens (H1, H3, H5, H6, H7, H8 primeiro; H2, H4 após UID) - estimativa 8-10 dias
+4. **Fase 3 (Polimento):** 12 itens - estimativa 6-8 dias
+5. **Fase 5 (Low):** 2 itens - estimativa 1-2 dias
+
+**Total estimado:** 28-38 dias de trabalho focado
+
+---
+
+## Notas Importantes
+
+- Este plano assume que os itens já corrigidos (sessões anteriores) permanecem estáveis.
+- Itens marcados como "REQUIRES UID INFRASTRUCTURE" devem ser implementados após Fase 4.
+- Testes de regressão devem ser executados após cada fase completa.
+- Alguns itens (como VMA table per process) são arquiteturais e podem ter impactos amplos.