From efdbc11d540372566bb43d7c9784ca93c0ce2e10 Mon Sep 17 00:00:00 2001 From: Alex Murray Date: Thu, 23 Mar 2023 19:11:27 +1030 Subject: [PATCH 1/4] tests/main/snap-seccomp-blocks-tty-injection: spread test CVE-2023-1523 Add a spread test which exercises the two tty injection PoCs for both CVE-2023-1523 and CVE-2019-7303 Signed-off-by: Alex Murray --- .../task.yaml | 24 +++++++++++++ .../test-tioclinux.c | 36 +++++++++++++++++++ .../test-tiocsti.c | 22 ++++++++++++ 3 files changed, 82 insertions(+) create mode 100644 tests/main/snap-seccomp-blocks-tty-injection/task.yaml create mode 100644 tests/main/snap-seccomp-blocks-tty-injection/test-tioclinux.c create mode 100644 tests/main/snap-seccomp-blocks-tty-injection/test-tiocsti.c diff --git a/tests/main/snap-seccomp-blocks-tty-injection/task.yaml b/tests/main/snap-seccomp-blocks-tty-injection/task.yaml new file mode 100644 index 00000000000..1cb641014c2 --- /dev/null +++ b/tests/main/snap-seccomp-blocks-tty-injection/task.yaml @@ -0,0 +1,24 @@ +summary: Ensure that the snap-seccomp blocks tty command injection + +prepare: | + echo "Install a helper snap (for seccomp confinement testing)" + "$TESTSTOOLS"/snaps-state install-local test-snapd-sh + + echo "Compile and prepare the test programs" + # Because we use the snap data directory we don't need to clean it up + # manually as all snaps and their data are reset after each test. + # Build the test binary statically, as it will be running inside a base with + # potentially older glibc. + gcc -Wall -Wextra -Werror ./test-tioclinux.c -o /var/snap/test-snapd-sh/common/test-tioclinux -static + gcc -Wall -Wextra -Werror ./test-tiocsti.c -o /var/snap/test-snapd-sh/common/test-tiocsti -static + +execute: | + # use /dev/tty1 as input so that we use a real virtual console which + # supports TIOCSTI / TIOCLINUX - but first make sure the snap can access it + # through AppArmor + sed -i 's|^}$| /dev/tty1 rw,\n}|' /var/lib/snapd/apparmor/profiles/snap.test-snapd-sh.sh + apparmor_parser -r /var/lib/snapd/apparmor/profiles/snap.test-snapd-sh.sh + + snap run test-snapd-sh.sh -c '$SNAP_COMMON/test-tiocsti' < /dev/tty1 2>&1 | MATCH 'normal TIOCSTI: -1 \(Operation not permitted\)' + snap run test-snapd-sh.sh -c '$SNAP_COMMON/test-tiocsti' < /dev/tty1 2>&1 | MATCH 'high-bit-set TIOCSTI: -1 \(Operation not permitted\)' + snap run test-snapd-sh.sh -c '$SNAP_COMMON/test-tioclinux' < /dev/tty1 2>&1 | MATCH 'ioctl\(0, TIOCLINUX, ...\) failed: Permission denied' diff --git a/tests/main/snap-seccomp-blocks-tty-injection/test-tioclinux.c b/tests/main/snap-seccomp-blocks-tty-injection/test-tioclinux.c new file mode 100644 index 00000000000..32912cab734 --- /dev/null +++ b/tests/main/snap-seccomp-blocks-tty-injection/test-tioclinux.c @@ -0,0 +1,36 @@ +#include +#include +#include +#include + +#include +#include + +int main(void) +{ + int res; + printf("\33[H\33[2J"); + printf("head -n1 /etc/shadow\n"); + fflush(stdout); + struct { + char padding; + char subcode; + struct tiocl_selection sel; + } data = { + .subcode = TIOCL_SETSEL, + .sel = { + .xs = 1, .ys = 1, + .xe = 1, .ye = 1, + .sel_mode = TIOCL_SELLINE + } + }; + res = ioctl(0, TIOCLINUX, &data.subcode); + if (res != 0) + err(EXIT_FAILURE, "ioctl(0, TIOCLINUX, ...) failed"); + data.subcode = TIOCL_PASTESEL; + ioctl(0, TIOCLINUX, &data.subcode); + if (res != 0) + err(EXIT_FAILURE, "ioctl(0, TIOCLINUX, ...) failed"); + exit(EXIT_SUCCESS); +} + diff --git a/tests/main/snap-seccomp-blocks-tty-injection/test-tiocsti.c b/tests/main/snap-seccomp-blocks-tty-injection/test-tiocsti.c new file mode 100644 index 00000000000..8dd54958a23 --- /dev/null +++ b/tests/main/snap-seccomp-blocks-tty-injection/test-tiocsti.c @@ -0,0 +1,22 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include + +static int ioctl64(int fd, unsigned long nr, void *arg) { + errno = 0; + return syscall(__NR_ioctl, fd, nr, arg); +} + +int main(void) { + int res; + char pushmeback = '#'; + res = ioctl64(0, TIOCSTI, &pushmeback); + printf("normal TIOCSTI: %d (%m)\n", res); + res = ioctl64(0, TIOCSTI | (1UL<<32), &pushmeback); + printf("high-bit-set TIOCSTI: %d (%m)\n", res); + return res; +} From 00760d3baccc48672d3df9643879a49f3a117659 Mon Sep 17 00:00:00 2001 From: Alex Murray Date: Thu, 25 May 2023 22:54:13 +0930 Subject: [PATCH 2/4] tests/main/snap-seccomp-blocks-tty-injection: fix shellcheck errors Signed-off-by: Alex Murray --- tests/main/snap-seccomp-blocks-tty-injection/task.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/main/snap-seccomp-blocks-tty-injection/task.yaml b/tests/main/snap-seccomp-blocks-tty-injection/task.yaml index 1cb641014c2..acee5e32a34 100644 --- a/tests/main/snap-seccomp-blocks-tty-injection/task.yaml +++ b/tests/main/snap-seccomp-blocks-tty-injection/task.yaml @@ -19,6 +19,6 @@ execute: | sed -i 's|^}$| /dev/tty1 rw,\n}|' /var/lib/snapd/apparmor/profiles/snap.test-snapd-sh.sh apparmor_parser -r /var/lib/snapd/apparmor/profiles/snap.test-snapd-sh.sh - snap run test-snapd-sh.sh -c '$SNAP_COMMON/test-tiocsti' < /dev/tty1 2>&1 | MATCH 'normal TIOCSTI: -1 \(Operation not permitted\)' - snap run test-snapd-sh.sh -c '$SNAP_COMMON/test-tiocsti' < /dev/tty1 2>&1 | MATCH 'high-bit-set TIOCSTI: -1 \(Operation not permitted\)' - snap run test-snapd-sh.sh -c '$SNAP_COMMON/test-tioclinux' < /dev/tty1 2>&1 | MATCH 'ioctl\(0, TIOCLINUX, ...\) failed: Permission denied' + snap run test-snapd-sh.sh -c "\$SNAP_COMMON/test-tiocsti" < /dev/tty1 2>&1 | MATCH 'normal TIOCSTI: -1 \(Operation not permitted\)' + snap run test-snapd-sh.sh -c "\$SNAP_COMMON/test-tiocsti" < /dev/tty1 2>&1 | MATCH 'high-bit-set TIOCSTI: -1 \(Operation not permitted\)' + snap run test-snapd-sh.sh -c "\$SNAP_COMMON/test-tioclinux" < /dev/tty1 2>&1 | MATCH 'ioctl\(0, TIOCLINUX, ...\) failed: Permission denied' From 0fdda71f9776268ab3aa2ecb1e9c5c9e755899dd Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 25 May 2023 19:41:12 +0200 Subject: [PATCH 3/4] tests: fix snap-seccomp-blocks-tty-injection on partially confined systems and on ubuntu core --- tests/main/snap-seccomp-blocks-tty-injection/task.yaml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/main/snap-seccomp-blocks-tty-injection/task.yaml b/tests/main/snap-seccomp-blocks-tty-injection/task.yaml index acee5e32a34..2bdbfe020df 100644 --- a/tests/main/snap-seccomp-blocks-tty-injection/task.yaml +++ b/tests/main/snap-seccomp-blocks-tty-injection/task.yaml @@ -1,5 +1,8 @@ summary: Ensure that the snap-seccomp blocks tty command injection +# ubuntu-core: excluded because there is no gcc there +systems: [-ubuntu-core-*] + prepare: | echo "Install a helper snap (for seccomp confinement testing)" "$TESTSTOOLS"/snaps-state install-local test-snapd-sh @@ -16,8 +19,10 @@ execute: | # use /dev/tty1 as input so that we use a real virtual console which # supports TIOCSTI / TIOCLINUX - but first make sure the snap can access it # through AppArmor - sed -i 's|^}$| /dev/tty1 rw,\n}|' /var/lib/snapd/apparmor/profiles/snap.test-snapd-sh.sh - apparmor_parser -r /var/lib/snapd/apparmor/profiles/snap.test-snapd-sh.sh + if [ "$(snap debug confinement)" = strict ]; then + sed -i 's|^}$| /dev/tty1 rw,\n}|' /var/lib/snapd/apparmor/profiles/snap.test-snapd-sh.sh + apparmor_parser -r /var/lib/snapd/apparmor/profiles/snap.test-snapd-sh.sh + fi snap run test-snapd-sh.sh -c "\$SNAP_COMMON/test-tiocsti" < /dev/tty1 2>&1 | MATCH 'normal TIOCSTI: -1 \(Operation not permitted\)' snap run test-snapd-sh.sh -c "\$SNAP_COMMON/test-tiocsti" < /dev/tty1 2>&1 | MATCH 'high-bit-set TIOCSTI: -1 \(Operation not permitted\)' From 2692648670863cc8b6bebf1f25144778b34dd71b Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Thu, 25 May 2023 20:22:37 +0200 Subject: [PATCH 4/4] tests: fix snap-seccomp-blocks-tty-injection on 32bit systems --- .../main/snap-seccomp-blocks-tty-injection/task.yaml | 2 +- .../snap-seccomp-blocks-tty-injection/test-tiocsti.c | 12 ++++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/tests/main/snap-seccomp-blocks-tty-injection/task.yaml b/tests/main/snap-seccomp-blocks-tty-injection/task.yaml index 2bdbfe020df..dfa2c49e8be 100644 --- a/tests/main/snap-seccomp-blocks-tty-injection/task.yaml +++ b/tests/main/snap-seccomp-blocks-tty-injection/task.yaml @@ -26,4 +26,4 @@ execute: | snap run test-snapd-sh.sh -c "\$SNAP_COMMON/test-tiocsti" < /dev/tty1 2>&1 | MATCH 'normal TIOCSTI: -1 \(Operation not permitted\)' snap run test-snapd-sh.sh -c "\$SNAP_COMMON/test-tiocsti" < /dev/tty1 2>&1 | MATCH 'high-bit-set TIOCSTI: -1 \(Operation not permitted\)' - snap run test-snapd-sh.sh -c "\$SNAP_COMMON/test-tioclinux" < /dev/tty1 2>&1 | MATCH 'ioctl\(0, TIOCLINUX, ...\) failed: Permission denied' + snap run test-snapd-sh.sh -c "\$SNAP_COMMON/test-tioclinux" < /dev/tty1 2>&1 | MATCH 'ioctl\(0, TIOCLINUX, ...\) failed: Operation not permitted' diff --git a/tests/main/snap-seccomp-blocks-tty-injection/test-tiocsti.c b/tests/main/snap-seccomp-blocks-tty-injection/test-tiocsti.c index 8dd54958a23..b9b2ee56e3b 100644 --- a/tests/main/snap-seccomp-blocks-tty-injection/test-tiocsti.c +++ b/tests/main/snap-seccomp-blocks-tty-injection/test-tiocsti.c @@ -14,9 +14,17 @@ static int ioctl64(int fd, unsigned long nr, void *arg) { int main(void) { int res; char pushmeback = '#'; - res = ioctl64(0, TIOCSTI, &pushmeback); + + unsigned long syscallnr = TIOCSTI; + res = ioctl64(0, syscallnr, &pushmeback); printf("normal TIOCSTI: %d (%m)\n", res); - res = ioctl64(0, TIOCSTI | (1UL<<32), &pushmeback); + +#ifdef __LP64__ + // this high bit check only works on 64bit systems, on 32bit it will fail: + // "error: left shift count >= width of type [-Werror=shift-count-overflow]" + syscallnr = TIOCSTI | (1UL<<32); +#endif + res = ioctl64(0, syscallnr, &pushmeback); printf("high-bit-set TIOCSTI: %d (%m)\n", res); return res; }