1
0
mirror of https://github.com/wfjm/w11.git synced 2026-02-06 16:55:09 +00:00

stktst: document the 11/70 findings [skip ci]

This commit is contained in:
wfjm
2022-08-06 08:00:53 +02:00
parent 0f6557beea
commit 6cb56af26c

View File

@@ -2,8 +2,8 @@
### Background
The `MMR1` response after an MMU abort in an FPP instruction depends on the CPU.
On an 11/70, the registers reflect the state at abort and `MMR1` shows the
change. On a J11, the registers are unchanged, and `MMR1` shows zero.
On an 11/70, the registers reflect the state at abort and `MMR1` returns the
change. On a J11, the registers are unchanged, and `MMR1` returns zero.
SimH V3.11-0 used the J11 FPP MMU abort handling for _all_ CPU models.
So even when an 11/70 is modeled, the behavior is like a J11.
@@ -28,7 +28,7 @@ That leads to two vulnerabilities:
- in a SimH 11/70, which probes as an 11/70 but behaves like a J11, any
push from an FPP instruction might fail.
The first is a 2.11BSD issue, the second is a SimH issue.
The first is a _2.11BSD issue_, the second is a _SimH issue_.
The tests were run under `tcsh`, it gives "Segmentation fault" in case of
a problem. Under `sh` one gets "Memory fault".
@@ -88,3 +88,116 @@ That's after 25 clicks. The initial stack size is 20 clicks
(see [SSIZE](https://www.retro11.de/ouxr/211bsd/usr/src/sys/pdp/machparam.h.html#m:SSIZE)) and the stack segment is a bit larger to accommodate argument and
environment structures.
So the `double` pushes fail when the initial allocation is exhausted.
### SimH in 11/70 mode, FPP enabled
SimH pdp11 started with
```
set cpu 11/70
```
and 2.11BSD starts with
```
70Boot from xp(0,0,0) at 0176700
```
The CPU probes now as 11/70, indicated by the `70Boot` startup message,
but behaves like a J11 for `MMR1`. The 2.11BSD J11 hack isn't done and
_all_ FPP pushes are vulnerable. That's what tests show:
```
# word push from FPP
./stktst i '4096' -c ' 2' -o ' -2'
# stktst-I: before sp 177304 (0, 4,60); 177176 (0, 6, 2);
# Segmentation fault (core dumped)
./stktst i ' 607' -c ' 2' -o ' -2'
# stktst-I: before sp 177304 (0, 4,60); 177176 (0, 6, 2);
# stktst-I: after sp 177304 (0, 4,60); 177176 (0, 6, 2); 174700 (0, 24,64);
./stktst i ' 608' -c ' 2' -o ' -2'
# stktst-I: before sp 177304 (0, 4,60); 177176 (0, 6, 2);
#
# long push from FPP
./stktst l '2048' -c ' 2' -o ' -2'
# stktst-I: before sp 177304 (0, 4,60); 177176 (0, 6, 2);
# Segmentation fault (core dumped)
./stktst l ' 303' -c ' 2' -o ' -2'
# stktst-I: before sp 177304 (0, 4,60); 177176 (0, 6, 2);
# stktst-I: after sp 177304 (0, 4,60); 177176 (0, 6, 2); 174702 (0, 24,62);
./stktst l ' 304' -c ' 2' -o ' -2'
# stktst-I: before sp 177304 (0, 4,60); 177176 (0, 6, 2);
# Segmentation fault (core dumped)
#
# float push from FPP
./stktst f '2048' -c ' 2' -o ' -2'
# stktst-I: before sp 177304 (0, 4,60); 177176 (0, 6, 2);
# Segmentation fault (core dumped)
./stktst f ' 303' -c ' 2' -o ' -2'
# stktst-I: before sp 177304 (0, 4,60); 177176 (0, 6, 2);
# stktst-I: after sp 177304 (0, 4,60); 177176 (0, 6, 2); 174702 (0, 24,62);
./stktst f ' 304' -c ' 2' -o ' -2'
# stktst-I: before sp 177304 (0, 4,60); 177176 (0, 6, 2);
# Segmentation fault (core dumped)
#
# double push from FPP
./stktst d '1024' -c ' 2' -o ' -2'
# stktst-I: before sp 177304 (0, 4,60); 177176 (0, 6, 2);
# Segmentation fault (core dumped)
./stktst d ' 151' -c ' 2' -o ' -2'
# stktst-I: before sp 177304 (0, 4,60); 177176 (0, 6, 2);
# stktst-I: after sp 177304 (0, 4,60); 177176 (0, 6, 2); 174706 (0, 24,58);
./stktst d ' 152' -c ' 2' -o ' -2'
# stktst-I: before sp 177304 (0, 4,60); 177176 (0, 6, 2);
# Segmentation fault (core dumped)
```
All FPP pushes fail when the first stack extend is reached.
This is, as stated before, not a 2.11BSD issue but a SimH issue.
### SimH in 11/70 mode, FPP disabled
SimH pdp11 started with
```
set cpu 11/70
set cpu nofpp
```
and 2.11BSD starts with
```
70Boot from xp(0,0,0) at 0176700
```
All FPP instructions trap and are emulated by a kernel mode handler with
plain integer arithmetic. Stack extends work as expected:
```
./stktst d '1024' -c ' 2' -o ' -2'
# stktst-I: before sp 177304 (0, 4,60); 177176 (0, 6, 2);
# stktst-I: after sp 177304 (0, 4,60); 177176 (0, 6, 2); 157176 (1, 6, 2);
# fill 2 pages
./stktst d '1999' -c ' 2' -o ' -2'
# stktst-I: before sp 177304 (0, 4,60); 177176 (0, 6, 2);
# stktst-I: after sp 177304 (0, 4,60); 177176 (0, 6, 2); 140006 (1,127,58);
# fill 3 pages
./stktst d '3023' -c ' 2' -o ' -2'
# stktst-I: before sp 177304 (0, 4,60); 177176 (0, 6, 2);
# stktst-I: after sp 177304 (0, 4,60); 177176 (0, 6, 2); 120006 (2,127,58);
# fill 5 pages
./stktst d '5071' -c ' 2' -o ' -2'
# stktst-I: before sp 177304 (0, 4,60); 177176 (0, 6, 2);
# stktst-I: after sp 177304 (0, 4,60); 177176 (0, 6, 2); 060006 (4,127,58);
# fill 6 pages
./stktst d '6095' -c ' 2' -o ' -2'
# stktst-I: before sp 177304 (0, 4,60); 177176 (0, 6, 2);
# stktst-I: after sp 177304 (0, 4,60); 177176 (0, 6, 2); 040006 (5,127,58);
# fill 7 pages
./stktst d '7119' -c ' 2' -o ' -2'
# stktst-I: before sp 177304 (0, 4,60); 177176 (0, 6, 2);
# stktst-I: after sp 177304 (0, 4,60); 177176 (0, 6, 2); 020006 (6,127,58);
```
`stktst` doesn't use separate I/D space, so page 0 is used by code and data.
The stack segment can't grow larger than 7 pages, and an extension beyond must
fail. And it does fail, a bit more spectacular than it should:
```
# and try one more
./stktst d '7120' -c ' 2' -o ' -2'
# ka6 36722 aps 147472
# pc 161324 ps 30004
# ov 4
# cpuerr 20
# trap type 0
# panic: trap
# syncing disks... done
```
The _kernel panic_ must come from a bug in the 2.11BSD FPP emulation code
[mch_fpsim.s](https://www.retro11.de/ouxr/211bsd/usr/src/sys/pdp/mch_fpsim.s.html). It should forward a SIGSEGV to the user process, like is does for other captured faults (like in code around [ferr1](https://www.retro11.de/ouxr/211bsd/usr/src/sys/pdp/mch_fpsim.s.html#s:ferr1)).