| Bellacosa Mainframe e os perigos na gestão de memoria no mainframe |
☕💥 Buffer Overflow, Memory Overwrite e Storage Corruption no z/OS
Ou como um simples MOVE pode transformar um datacenter multimilionário em uma sessão espírita conduzida por um Sysprog com café frio
Introdução
Existe uma frase antiga entre veteranos de Mainframe:
"Computadores não cometem erros. Eles apenas obedecem ordens idiotas em velocidades absurdamente altas."
E poucas coisas representam melhor isso do que três monstros ancestrais da programação:
Buffer Overflow
Memory Overwrite
Storage Corruption
O curioso é que muitos desenvolvedores COBOL juniores acreditam que isso é um problema de C, C++, Linux ou Windows.
Na verdade...
Mainframe conhece esses monstros desde que Elvis Presley ainda estava gravando discos.
A diferença é que o z/OS aprendeu a sobreviver a eles.
Hoje vamos entender como esses problemas surgem em:
COBOL
JCL
REXX
CICS
DB2
IMS
VSAM
Batch
JES2
SDSF
Language Environment
e principalmente...
como impedir que uma simples variável PIC X(10) provoque um incidente digno de abertura de War Room.
Capítulo 1
O que é Buffer Overflow?
Definição simples.
Você reservou espaço para 10.
Escreveu 100.
Fim.
Exemplo.
COBOL
01 WS-NOME.
05 WS-TEXTO PIC X(10).
MOVE "BELLACOSA-MAINFRAME" TO WS-TEXTO
Teoricamente:
0123456789
BELLACOSA
Sobrou:
MAINFRAME
Para onde foi?
Depende.
Pode ir para:
Flag
Outra variável
LE Runtime
Heap
Stack
Linguagem C
char nome[10];
strcpy(nome,"BellacosaMainframe");
Mesmo problema.
COBOL apenas costuma esconder melhor.
Capítulo 2
Memory Overwrite
Buffer Overflow produz.
Memory Overwrite.
É o efeito colateral.
Exemplo
01 WS-AREA.
05 TABELA OCCURS 100.
10 COD PIC X.
05 FLAG PIC X.
Erro.
MOVE 'S'
TO TABELA(101)
Resultado.
FLAG = S
Pior.
Pode alterar:
SQLCA
DFHEIBLK
TGT
Save Area
Storage Corruption
É o estágio terminal.
Já não sabemos mais o que foi alterado.
O programa continua rodando.
Mas agora virou um zumbi.
O pesadelo
Job roda.
Termina RC=0000.
DB2 recebe dados errados.
VSAM inconsistente.
Extrato bancário incorreto.
E ninguém percebe.
Capítulo 3
Como o z/OS protege memória
1964
System/360
Quase nenhuma proteção.
Anos 70
Storage Keys
PSW
Anos 80
MVS/XA
Address Space
Anos 90
ESA
Cross Memory
Anos 2000
zOS
64 bits
LE
Heap protegido
Hoje
z16
z17
Guard Pages
Hardware assistido
Storage protection
O conceito de Address Space
Cada Job.
Cada TSO.
Cada CICS.
Possui seu universo.
Imagine apartamentos.
Apartamento 101.
COBOL.
Apartamento 102.
DB2.
Apartamento 103.
JES2.
Overflow.
Quebrou parede.
Invadiu apartamento vizinho.
Sysprog chora.
Capítulo 4
Batch
Batch é perigoso.
Porque roda horas.
Exemplo
5 milhões registros.
Erro.
Registro 3.456.789.
Corrupção.
Abends comuns
S0C4
Protection Exception
S0C7
Dados inválidos
S0C1
Opcode ilegal
S878
Storage
S80A
Memória insuficiente
U4038
LE detectou problema
Caso histórico
Década 90.
Seguradora.
Tabela OCCURS 500.
Nova regra.
700 elementos.
Programa não recompilado.
Sobrescreveu área.
Job fechou mensal.
Milhares apólices erradas.
Descoberta.
3 semanas depois.
Capítulo 5
CICS
No online.
Muito pior.
CICS compartilha recursos.
Tasking.
Threads.
Erro.
Pode derrubar milhares usuários.
DFHEIBLK corrompido.
Retorno errado.
Pseudo-conversacional.
COMMAREA.
Overflow.
Exemplo
DFHCOMMAREA PIC X(32767)
Recebe.
40 mil.
Boom.
Abends famosos
AEI9
ASRA
AEYD
APCT
AICA
AICA
Loop infinito.
CPU consumida.
ASRA
Equivalente S0C4.
Capítulo 6
DB2
DB2 é robusto.
Mas aplicativo não.
SQLDA.
SQLCA.
Host Variables.
Exemplo
PIC X(10)
Coluna VARCHAR(100)
Truncation.
SQLCODE
-302
-311
-305
Melhor prática.
Verificar.
SQLCODE.
Sempre.
Capítulo 7
IMS
IMS é uma máquina do tempo.
Ainda vivo.
PCB errado.
SSA inválida.
Pode gerar.
U0777
Overflow.
Área I/O.
Segmento corrompido.
Capítulo 8
VSAM
KSDS.
RRDS.
ESDS.
Erro clássico.
READ NEXT.
EOF ignorado.
Subscript inválido.
Storage corruption.
IDCAMS detecta.
VERIFY
EXAMINE
Capítulo 9
REXX
Parece inocente.
Não é.
Stem.
CLIENTE.0=100
DO I=1 TO 1000
SAY CLIENTE.I
END
Dados inexistentes.
RC inesperado.
Storage não costuma corromper.
Mas lógica.
Sim.
Capítulo 10
JES2
JES2 protege spool.
Mas programa pode gerar.
100 milhões linhas.
SYSOUT gigante.
JES2 sofre.
HASP...
mensagens.
Spool cheio.
Job cancelado.
Capítulo 11
SDSF
Melhor amigo.
ST
Status
DA
Address Spaces
LOG
Mensagens
ENC
Enclave
Examine.
MEMORY.
CPU.
Abends.
Capítulo 12
LE
Language Environment.
Herói desconhecido.
SSRANGE
CHECK
HEAPCHK
RPTSTG
TRAP
TERMTHDACT
Exemplo
PARM='TRAP(ON)'
Captura.
Stack.
Dump.
Capítulo 13
Ferramentas modernas
Fault Analyzer
Abend Aid
IBM Debug
IPDF
CEEDUMP
SMF
30
110
120
RMF
OMEGAMON
Z APM
Capítulo 14
Como programar seguro
Sempre
SSRANGE
Validar índices.
IF IDX <= MAX
Nunca confiar input.
CHECK LENGTH
SQLCODE
RESP
CICS
FILE STATUS
ON SIZE ERROR
INITIALIZE
INSPECT
TESTAR.
TESTAR.
TESTAR.
Capítulo 15
Detectando antes do caos
Pipeline ideal.
DEV
SSRANGE
QA
HEAPCHK
HML
TRAP
PRD
NOSSRANGE
SMF
OMEGAMON
Alarmes.
CPU.
Storage.
Abends.
Spool.
Response Time.
Easter Egg Bellacosa
Existe uma lenda em alguns datacenters.
Conta-se que um programa COBOL compilado em 1984 executava perfeitamente.
Até que um desenvolvedor júnior resolveu "modernizar".
Adicionou:
OCCURS 2000 TIMES
Compilou.
Promoveu.
Sexta-feira.
17h45.
Produção.
Fim de mês.
Folha salarial.
Executou.
RC=0000.
Tudo aparentemente perfeito.
Na segunda-feira descobriram que 12 mil funcionários haviam recebido exatamente:
R$ 0,01
O programa não havia abendado.
Não havia S0C4.
Não havia dump.
Apenas um discreto byte sobrescrito em uma área esquecida do Working Storage.
Dizem que o Sysprog responsável ainda hoje aparece pelos corredores do CPD segurando uma caneca de café e repetindo para novos desenvolvedores:
"Tem gente que teme IA substituir programadores. Eu temo programadores que compilam NOSSRANGE em homologação."
Conclusão
Os grandes incidentes em Mainframe raramente começam com uma pane espetacular.
Eles começam com pequenas negligências:
Um índice não validado;
Um OCCURS mal dimensionado;
Um SQLCODE ignorado;
Um COMMAREA maior que o esperado;
Um READ VSAM sem FILE STATUS;
Um JCL sem limites de espaço;
Um REXX assumindo que tudo sempre existe.
O z/OS evoluiu durante mais de 60 anos justamente para impedir que esses erros se transformem em catástrofes.
Mas a última linha de defesa continua sendo a mesma desde 1959:
O desenvolvedor que entende memória, respeita limites e trata cada MOVE como se estivesse carregando plutônio digital.