diff options
Diffstat (limited to 'regress')
-rw-r--r-- | regress/sys/kern/ptrace/Makefile | 4 | ||||
-rw-r--r-- | regress/sys/kern/ptrace/xstate/Makefile | 26 | ||||
-rw-r--r-- | regress/sys/kern/ptrace/xstate/avx.S | 79 | ||||
-rw-r--r-- | regress/sys/kern/ptrace/xstate/xstate.c | 259 | ||||
-rw-r--r-- | regress/usr.bin/ssh/hostkey-agent.sh | 26 |
5 files changed, 392 insertions, 2 deletions
diff --git a/regress/sys/kern/ptrace/Makefile b/regress/sys/kern/ptrace/Makefile index 5a41ee05a49..e4f4c38e86b 100644 --- a/regress/sys/kern/ptrace/Makefile +++ b/regress/sys/kern/ptrace/Makefile @@ -1,4 +1,6 @@ -# $OpenBSD: Makefile,v 1.3 2016/09/23 18:56:49 bluhm Exp $ +# $OpenBSD: Makefile,v 1.4 2024/11/27 05:27:21 anton Exp $ + +SUBDIR+= xstate PROG= ptrace diff --git a/regress/sys/kern/ptrace/xstate/Makefile b/regress/sys/kern/ptrace/xstate/Makefile new file mode 100644 index 00000000000..d42929434d3 --- /dev/null +++ b/regress/sys/kern/ptrace/xstate/Makefile @@ -0,0 +1,26 @@ +# $OpenBSD: Makefile,v 1.1 2024/11/27 05:26:58 anton Exp $ + +.if ${MACHINE} == "amd64" + +WARNINGS= yes + +PROG= xstate +SRCS+= xstate.c +SRCS+= avx.S + +REGRESS_SETUP_ONCE=${PROG} + +.for t in xstate-ymm-get xstate-ymm-set +${t}: + ${.OBJDIR}/xstate ${t} +REGRESS_TARGETS+=${t} +.endfor + +.else + +regress: + @echo SKIPPED + +.endif + +.include <bsd.regress.mk> diff --git a/regress/sys/kern/ptrace/xstate/avx.S b/regress/sys/kern/ptrace/xstate/avx.S new file mode 100644 index 00000000000..5571a2e634e --- /dev/null +++ b/regress/sys/kern/ptrace/xstate/avx.S @@ -0,0 +1,79 @@ +/* $OpenBSD */ + +#include <machine/asm.h> + + .intel_syntax noprefix + +/* void ymm_write(void) */ +ENTRY(ymm_write) + vmovdqu ymm0, [rip + .Lymm0] + vmovdqu ymm1, [rip + .Lymm1] + vmovdqu ymm2, [rip + .Lymm2] + vmovdqu ymm3, [rip + .Lymm3] + vmovdqu ymm4, [rip + .Lymm4] + vmovdqu ymm5, [rip + .Lymm5] + vmovdqu ymm6, [rip + .Lymm6] + vmovdqu ymm7, [rip + .Lymm7] + vmovdqu ymm8, [rip + .Lymm8] + vmovdqu ymm9, [rip + .Lymm9] + vmovdqu ymm10, [rip + .Lymm10] + vmovdqu ymm11, [rip + .Lymm11] + vmovdqu ymm12, [rip + .Lymm12] + vmovdqu ymm13, [rip + .Lymm13] + vmovdqu ymm14, [rip + .Lymm14] + vmovdqu ymm15, [rip + .Lymm15] + ret + +/* void ymm_read(struct ymm[16]) */ +ENTRY(ymm_read) + vmovdqu [rdi + 0x000], ymm0 + vmovdqu [rdi + 0x020], ymm1 + vmovdqu [rdi + 0x040], ymm2 + vmovdqu [rdi + 0x060], ymm3 + vmovdqu [rdi + 0x080], ymm4 + vmovdqu [rdi + 0x0a0], ymm5 + vmovdqu [rdi + 0x0c0], ymm6 + vmovdqu [rdi + 0x0e0], ymm7 + vmovdqu [rdi + 0x100], ymm8 + vmovdqu [rdi + 0x120], ymm9 + vmovdqu [rdi + 0x140], ymm10 + vmovdqu [rdi + 0x160], ymm11 + vmovdqu [rdi + 0x180], ymm12 + vmovdqu [rdi + 0x1a0], ymm13 + vmovdqu [rdi + 0x1c0], ymm14 + vmovdqu [rdi + 0x1e0], ymm15 + ret + + .rodata +.Lymm0: + .rept 4; .quad 0x0000000000000000; .endr +.Lymm1: + .rept 4; .quad 0x1111111111111111; .endr +.Lymm2: + .rept 4; .quad 0x2222222222222222; .endr +.Lymm3: + .rept 4; .quad 0x3333333333333333; .endr +.Lymm4: + .rept 4; .quad 0x4444444444444444; .endr +.Lymm5: + .rept 4; .quad 0x5555555555555555; .endr +.Lymm6: + .rept 4; .quad 0x6666666666666666; .endr +.Lymm7: + .rept 4; .quad 0x7777777777777777; .endr +.Lymm8: + .rept 4; .quad 0x8888888888888888; .endr +.Lymm9: + .rept 4; .quad 0x9999999999999999; .endr +.Lymm10: + .rept 4; .quad 0xaaaaaaaaaaaaaaaa; .endr +.Lymm11: + .rept 4; .quad 0xbbbbbbbbbbbbbbbb; .endr +.Lymm12: + .rept 4; .quad 0xcccccccccccccccc; .endr +.Lymm13: + .rept 4; .quad 0xdddddddddddddddd; .endr +.Lymm14: + .rept 4; .quad 0xeeeeeeeeeeeeeeee; .endr +.Lymm15: + .rept 4; .quad 0xffffffffffffffff; .endr diff --git a/regress/sys/kern/ptrace/xstate/xstate.c b/regress/sys/kern/ptrace/xstate/xstate.c new file mode 100644 index 00000000000..bee551463f8 --- /dev/null +++ b/regress/sys/kern/ptrace/xstate/xstate.c @@ -0,0 +1,259 @@ +/* $OpenBSD */ + +#include <sys/types.h> +#include <sys/ptrace.h> +#include <sys/wait.h> + +#include <err.h> +#include <signal.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +struct cpuid { + uint32_t a, b, c, d; +}; + +struct xstate { + struct { + uint8_t buf[1024]; + uint32_t size; + } area; + + struct { + uint32_t supported; + uint32_t offset; + uint32_t size; + } components[3]; +#define XSTATE_COMPONENT_X87 0 +#define XSTATE_COMPONENT_SSE 1 +#define XSTATE_COMPONENT_AVX 2 +}; + +struct u128 { + uint64_t v[2]; +} __attribute__((packed)); + +struct ymm { + struct u128 xmm; + struct u128 ymm; +} __attribute__((packed)); + +extern void ymm_write(void); +extern void ymm_read(struct ymm[16]); + +static inline void +cpuid(uint32_t leaf, uint32_t subleaf, struct cpuid *out) +{ + __asm__("cpuid" + : "=a" (out->a), "=b" (out->b), "=c" (out->c), "=d" (out->d) + : "a" (leaf), "c" (subleaf)); +} + +static int +xstate_init(struct xstate *xstate, pid_t pid) +{ +#define CPUID_01_C_XSAVE_MASK (1 << 26) +#define XCR0_XMM_MASK (1 << 1) +#define XCR0_YMM_MASK (1 << 2) + + struct cpuid leaf; + struct ptrace_xstate_info info; + + cpuid(0x1, 0, &leaf); + if ((leaf.c & CPUID_01_C_XSAVE_MASK) == 0) { + printf("SKIPPED: XSAVE not enumerated"); + return 1; + } + + memset(xstate, 0, sizeof(*xstate)); + + if (ptrace(PT_GETXSTATE_INFO, pid, + (caddr_t)&info, sizeof(info)) == -1) + err(1, "ptrace: PT_GETXSTATE_INFO"); + if (info.xsave_len > sizeof(xstate->area.buf)) + errx(1, "xstate buffer too small"); + xstate->area.size = info.xsave_len; + + if ((info.xsave_mask & XCR0_XMM_MASK) == 0 || + (info.xsave_mask & XCR0_YMM_MASK) == 0) { + printf("SKIPPED: SSE/AVX disabled in XCR0\n"); + return 1; + } + + xstate->components[XSTATE_COMPONENT_SSE].supported = 1; + /* Part of legacy region in XSAVE area. */ + xstate->components[XSTATE_COMPONENT_SSE].offset = 160; + xstate->components[XSTATE_COMPONENT_SSE].size = 256; + + cpuid(0xd, XSTATE_COMPONENT_AVX, &leaf); + xstate->components[XSTATE_COMPONENT_AVX].supported = 1; + xstate->components[XSTATE_COMPONENT_AVX].offset = leaf.b; + xstate->components[XSTATE_COMPONENT_AVX].size = leaf.a; + + return 0; +} + +static void +xstate_ymm_read(struct xstate *xstate, int regno, struct ymm *rd) +{ + struct u128 *xmm = (struct u128 *)(xstate->area.buf + + xstate->components[XSTATE_COMPONENT_SSE].offset); + struct u128 *ymm = (struct u128 *)(xstate->area.buf + + xstate->components[XSTATE_COMPONENT_AVX].offset); + + rd->xmm = xmm[regno]; + rd->ymm = ymm[regno]; +} + +static void +xstate_ymm_write(struct xstate *xstate, int regno, struct ymm *wr) +{ + struct u128 *xmm = (struct u128 *)(xstate->area.buf + + xstate->components[XSTATE_COMPONENT_SSE].offset); + struct u128 *ymm = (struct u128 *)(xstate->area.buf + + xstate->components[XSTATE_COMPONENT_AVX].offset); + + xmm[regno] = wr->xmm; + ymm[regno] = wr->ymm; +} + +static void +wait_until_stopped(pid_t pid) +{ + int status; + + if (waitpid(pid, &status, 0) == -1) + err(1, "waitpid"); + if (!WIFSTOPPED(status)) + errx(1, "expected traced process to be stopped"); +} + +static int +check_ymm(const struct ymm ymm[16]) +{ + int error = 0; + int i; + + for (i = 0; i < 16; i++) { + struct ymm exp; + + memset(&exp, (i << 4) | i, 32); + if (memcmp(&exp, &ymm[i], 32) == 0) + continue; + + warnx("ymm%d: expected %016llx%016llx%016llx%016llx," + " got %016llx%016llx%016llx%016llx", i, + exp.ymm.v[1], exp.ymm.v[0], + exp.xmm.v[1], exp.xmm.v[0], + ymm[i].ymm.v[1], ymm[i].ymm.v[0], + ymm[i].xmm.v[1], ymm[i].xmm.v[0]); + error = 1; + } + + return error; +} + +static int +test_ymm_get(struct xstate *xstate) +{ + struct ymm ymm[16]; + pid_t pid; + int i; + + pid = fork(); + if (pid == 0) { + ptrace(PT_TRACE_ME, 0, 0, 0); + ymm_write(); + raise(SIGSTOP); + /* UNREACHABLE */ + } + + wait_until_stopped(pid); + + if (xstate_init(xstate, pid)) + return 0; + + if (ptrace(PT_GETXSTATE, pid, + xstate->area.buf, xstate->area.size) == -1) + err(1, "ptrace: PT_GETXSTATE"); + for (i = 0; i < 16; i++) + xstate_ymm_read(xstate, i, &ymm[i]); + return check_ymm(ymm); +} + +static int +test_ymm_set(struct xstate *xstate) +{ + pid_t pid; + int i, status; + + pid = fork(); + if (pid == 0) { + struct ymm ymm[16]; + + ptrace(PT_TRACE_ME, 0, 0, 0); + raise(SIGSTOP); + ymm_read(ymm); + _exit(check_ymm(ymm)); + } + + wait_until_stopped(pid); + + if (xstate_init(xstate, pid)) + return 0; + + if (ptrace(PT_GETXSTATE, pid, + xstate->area.buf, xstate->area.size) == -1) + err(1, "ptrace: PT_GETXSTATE"); + for (i = 0; i < 16; i++) { + struct ymm ymm; + + memset(&ymm, (i << 4) | i, 32); + xstate_ymm_write(xstate, i, &ymm); + } + + if (ptrace(PT_SETXSTATE, pid, + xstate->area.buf, xstate->area.size) == -1) + err(1, "ptrace: PT_SETXSTATE"); + + if (ptrace(PT_CONTINUE, pid, (caddr_t)1, 0) == -1) + err(1, "ptrace: PT_CONTINUE"); + if (waitpid(pid, &status, 0) == -1) + err(1, "waitpid"); + return WIFEXITED(status) && WEXITSTATUS(status) == 0 ? 0 : 1; +} + +static void __attribute__((noreturn)) +usage(void) +{ + fprintf(stderr, "usage: xstate test-case\n"); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + struct { + const char *name; + int (*test)(struct xstate *); + } tests[] = { + { "xstate-ymm-get", test_ymm_get }, + { "xstate-ymm-set", test_ymm_set }, + }; + struct xstate xstate; + unsigned int i; + + if (argc != 2) + usage(); + + for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { + if (strcmp(argv[1], tests[i].name) == 0) + return tests[i].test(&xstate); + } + + warnx("no such test case"); + return 1; +} diff --git a/regress/usr.bin/ssh/hostkey-agent.sh b/regress/usr.bin/ssh/hostkey-agent.sh index 222d424bd34..38486585701 100644 --- a/regress/usr.bin/ssh/hostkey-agent.sh +++ b/regress/usr.bin/ssh/hostkey-agent.sh @@ -1,4 +1,4 @@ -# $OpenBSD: hostkey-agent.sh,v 1.13 2021/09/30 05:20:08 dtucker Exp $ +# $OpenBSD: hostkey-agent.sh,v 1.14 2024/11/26 22:02:28 djm Exp $ # Placed in the Public Domain. tid="hostkey agent" @@ -82,6 +82,30 @@ for k in $SSH_CERTTYPES ; do fi done +verbose "multiple hostkeys" +cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy +cp $OBJ/ssh_proxy $OBJ/ssh_proxy.orig +grep -vi 'globalknownhostsfile' $OBJ/ssh_proxy.orig > $OBJ/ssh_proxy +echo "UpdateHostkeys=yes" >> $OBJ/ssh_proxy +echo "GlobalKnownHostsFile=none" >> $OBJ/ssh_proxy + +for k in $SSH_KEYTYPES ; do + verbose "Addkey type $k" + echo "Hostkey $OBJ/agent-key.${k}" >> $OBJ/sshd_proxy + + ( printf 'localhost-with-alias ' ; + cat $OBJ/agent-key.$k.pub) > $OBJ/known_hosts +done + +opts="-oStrictHostKeyChecking=yes -F $OBJ/ssh_proxy" +SSH_CONNECTION=`${SSH} $opts host 'echo $SSH_CONNECTION'` +if [ $? -ne 0 ]; then + fail "connection to server with multiple hostkeys failed" +fi +if [ "$SSH_CONNECTION" != "UNKNOWN 65535 UNKNOWN 65535" ]; then + fail "bad SSH_CONNECTION key while using multiple hostkeys" +fi + trace "kill agent" ${SSHAGENT} -k > /dev/null |