Skip to content

stc_identity_restore() stores into module storage in key 8 -- S0C4 on P HTTPD with an APF-authorized LINKLIB #197

Description

@mgrossmann

HTTPD is link-edited AC(1) and authorizes itself at startup (__autask(),
src/httpd.c:1028). On that route the module is fetched into key-8 storage and
JSCBAUTH is set afterwards, so writable module data goes unnoticed. Add an APF
entry for the LINKLIB and the picture inverts: the job step is authorized
before program fetch runs, MVS obtains the job pack area in subpool 252
key 0 — authorized code must not be patchable by problem-key code — and any
store into the module's own storage from problem state key 8 takes a protection
exception.

This is the same defect ufsd#64
turned out to be (fixed in ufsd#66), found here by running ufsd's
tools/check-module-data.py across the ecosystem. HTTPD has exactly one
exposed store, and it is on the shutdown path.

The site

stc_prev_acee (src/httpd.c:57) is written twice, and the two are not alike:

  • stc_identity(), src/httpd.c:103stc_prev_acee = old_acee; sits
    inside the __super(PSWKEY0, &savekey) window opened on line 74 and
    closed on line 110. Key 0, so it stores fine either way. No action needed.
  • stc_identity_restore(), src/httpd.c:135stc_prev_acee = NULL; is not
    in a window, and the block comment says why: "racf_set_acee() does its own
    supervisor/key switching, so no __super() here."
    True for the call, not
    for the assignment after it. That store runs problem state key 8, so with an
    APF-authorized LINKLIB P HTTPD ends in S0C4 instead of a clean shutdown —
    and it does so after racf_set_acee() has already put the STC account back,
    which is the part that matters for the SVC 244 release.

The read on line 132 is fine; only the store is a problem.

__stklen (src/httpd.c:22) is module data too, but it is only ever read by
the CRT startup, so it is not at risk.

Direction

The narrow fix is to give stc_identity_restore() the same __super /
__prob window stc_identity() already has — one store, called once, at
shutdown. The alternative is to move stc_prev_acee out of module storage
into the HTTPD control block, which is where per-STC state otherwise lives.

Worth noting regardless of APF

ld370 marks a load module RENT and REUS unless the module opts out with
norent / noreus, and HTTPD does not. So a writable static already breaks the
reentrancy attribute the module carries, and would fail the same way if HTTPD
were ever placed in the LPA.

Checking it

ufsd's guard is portable to any mbt v2 project — it only needs project.toml
and Python 3.11+, no toolchain:

python3 ../ufsd/tools/check-module-data.py project.toml

It reads the [[module]] blocks, checks the ac = 1 ones, and rejects mutable
file-scope data and function-local statics. ufsd runs it as its own CI job.
Note it cannot tell a key-0 window from a key-8 one — it flags the data, the
key question is still a matter of reading the code, as with the two stores
above.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions