From 3f3c90a958c5abf8ec0ed5d1fad2e40bd9905a50 Mon Sep 17 00:00:00 2001 From: Andy Fiddaman Date: Thu, 24 Nov 2022 13:59:08 +0000 Subject: 15206 setcontext(2) should not restore %fsbase Reviewed by: Robert Mustacchi Reviewed by: Toomas Soome Approved by: Patrick Mooney --- usr/src/lib/libc/port/threads/sigaction.c | 12 +- usr/src/man/man2/getcontext.2 | 218 ++++++++++++++++----------- usr/src/pkg/manifests/system-test-ostest.p5m | 4 +- usr/src/test/os-tests/runfiles/default.run | 5 +- usr/src/test/os-tests/tests/Makefile | 4 + usr/src/test/os-tests/tests/ucontext.c | 103 +++++++++++++ 6 files changed, 253 insertions(+), 93 deletions(-) create mode 100644 usr/src/test/os-tests/tests/ucontext.c diff --git a/usr/src/lib/libc/port/threads/sigaction.c b/usr/src/lib/libc/port/threads/sigaction.c index 571e211f97..1417c1e18a 100644 --- a/usr/src/lib/libc/port/threads/sigaction.c +++ b/usr/src/lib/libc/port/threads/sigaction.c @@ -24,6 +24,10 @@ * Use is subject to license terms. */ +/* + * Copyright 2022 OmniOS Community Edition (OmniOSce) Association. + */ + #include "lint.h" #include /* @@ -563,7 +567,13 @@ setcontext(const ucontext_t *ucp) #if defined(__sparc) uc.uc_mcontext.gregs[REG_G7] = (greg_t)self; #elif defined(__amd64) - uc.uc_mcontext.gregs[REG_FS] = (greg_t)0; /* null for fsbase */ + /* + * 64-bit processes must have a selector value of zero for %fs + * in order to use the 64-bit fs_base (the full 64-bit address + * range cannot be expressed in a long mode descriptor). + */ + uc.uc_mcontext.gregs[REG_FS] = (greg_t)0; + uc.uc_mcontext.gregs[REG_FSBASE] = (greg_t)self; #elif defined(__i386) uc.uc_mcontext.gregs[GS] = (greg_t)LWPGS_SEL; #else diff --git a/usr/src/man/man2/getcontext.2 b/usr/src/man/man2/getcontext.2 index 5e12548f7c..80cf9b8c1f 100644 --- a/usr/src/man/man2/getcontext.2 +++ b/usr/src/man/man2/getcontext.2 @@ -43,98 +43,136 @@ .\" Copyright 1989 AT&T .\" Portions Copyright (c) 1992, X/Open Company Limited. All Rights Reserved. .\" Copyright (c) 2001, Sun Microsystems, Inc. All Rights Reserved. +.\" Copyright 2022 OmniOS Community Edition (OmniOSce) Association. .\" -.TH GETCONTEXT 2 "May 13, 2017" -.SH NAME -getcontext, setcontext \- get and set current user context -.SH SYNOPSIS -.LP -.nf -#include - -\fBint\fR \fBgetcontext\fR(\fBucontext_t *\fR\fIucp\fR); -.fi - -.LP -.nf -\fBint\fR \fBsetcontext\fR(\fBconst ucontext_t *\fR\fIucp\fR); -.fi - -.SH DESCRIPTION -.LP -The \fBgetcontext()\fR function initializes the structure pointed to by -\fIucp\fR to the current user context of the calling process. The -\fBucontext_t\fR type that \fIucp\fR points to defines the user context and -includes the contents of the calling process' machine registers, the signal -mask, and the current execution stack. -.sp -.LP -The \fBsetcontext()\fR function restores the user context pointed to by -\fIucp\fR. A successful call to \fBsetcontext()\fR does not return; program -execution resumes at the point specified by the \fIucp\fR argument passed to -\fBsetcontext()\fR. The \fIucp\fR argument should be created either by a prior -call to \fBgetcontext()\fR, or by being passed as an argument to a signal -handler. If the \fIucp\fR argument was created with \fBgetcontext()\fR, program -execution continues as if the corresponding call of \fBgetcontext()\fR had just -returned. If the \fIucp\fR argument was created with \fBmakecontext\fR(3C), -program execution continues with the function passed to \fBmakecontext\fR(3C). +.Dd November 24, 2022 +.Dt GETCONTEXT 2 +.Os +.Sh NAME +.Nm getcontext , +.Nm setcontext +.Nd get and set current user context +.Sh SYNOPSIS +.In ucontext.h +.Ft int +.Fo getcontext +.Fa "ucontext_t *ucp" +.Fc +.Ft int +.Fo setcontext +.Fa "const ucontext_t *ucp" +.Fc +.Sh DESCRIPTION +The +.Fn getcontext +function initializes the structure pointed to by +.Fa ucp +to the current user context of the calling process. +The +.Vt ucontext_t +type that +.Fa ucp +points to defines the user context and includes the contents of the calling +process' machine registers, the signal mask, and the current execution stack. +.Pp +The +.Fn setcontext +function restores the user context pointed to by +.Fa ucp . +A successful call to +.Fn setcontext +does not return; program execution resumes at the point specified by the +.Fa ucp +argument passed to +.Fn setcontext . +The +.Fa ucp +argument should be created either by a prior call to +.Fn getcontext , +or by being passed as an argument to a signal handler. +If the +.Fa ucp +argument was created with +.Fn getcontext , +program execution continues as if the corresponding call of +.Fn getcontext +had just returned. +If the +.Fa ucp +argument was created with +.Xr makecontext 3C , +program execution continues with the function passed to +.Xr makecontext 3C . When that function returns, the process continues as if after a call to -\fBsetcontext()\fR with the \fIucp\fR argument that was input to -\fBmakecontext\fR(3C). If the \fIucp\fR argument was passed to a signal -handler, program execution continues with the program instruction following the -instruction interrupted by the signal. If the \fBuc_link\fR member of the -\fBucontext_t\fR structure pointed to by the \fIucp\fR argument is equal to 0, -then this context is the main context, and the process will exit when this -context returns. The effects of passing a \fIucp\fR argument obtained from any -other source are unspecified. -.SH RETURN VALUES -.LP -On successful completion, \fBsetcontext()\fR does not return and -\fBgetcontext()\fR returns \fB0\fR. Otherwise, \fB\(mi1\fR is returned. -.SH ERRORS -.LP +.Fn setcontext +with the +.Fa ucp +argument that was input to +.Xr makecontext 3C . +If the +.Fa ucp +argument was passed to a signal handler, program execution continues with the +program instruction following the instruction interrupted by the signal. +If the +.Fa uc_link +member of the +.Vt ucontext_t +structure pointed to by the +.Fa ucp +argument is +.Dv NULL , +then this context is the main context, and the process +will exit when this context returns. +The effects of passing a +.Fa ucp +argument obtained from any other source are unspecified. +.Sh RETURN VALUES +On successful completion, +.Fn setcontext +does not return and +.Fn getcontext +returns 0. +Otherwise, -1 is returned. +.Sh ERRORS No errors are defined. -.SH USAGE -.LP +.Sh USAGE When a signal handler is executed, the current user context is saved and a new -context is created. If the thread leaves the signal handler via -\fBlongjmp\fR(3C), then it is unspecified whether the context at the time of -the corresponding \fBsetjmp\fR(3C) call is restored and thus whether future -calls to \fBgetcontext()\fR will provide an accurate representation of the -current context, since the context restored by \fBlongjmp\fR(3C) may not -contain all the information that \fBsetcontext()\fR requires. Signal handlers -should use \fBsiglongjmp\fR(3C) instead. -.sp -.LP -Portable applications should not modify or access the \fBuc_mcontext\fR member -of \fBucontext_t\fR. A portable application cannot assume that context -includes any process-wide static data, possibly including \fBerrno\fR. Users -manipulating contexts should take care to handle these explicitly when +context is created. +If the thread leaves the signal handler via +.Xr longjmp 3C , +then it is unspecified whether the context at the time of the corresponding +.Xr setjmp 3C +call is restored and thus whether future calls to +.Fn getcontext +will provide an accurate representation of the current context, since the +context restored by +.Xr longjmp 3C +may not contain all the information that +.Fn setcontext +requires. +Signal handlers should use +.Xr siglongjmp 3C +instead. +.Pp +Portable applications should not modify or access the +.Fa uc_mcontext +member of +.Vt ucontext_t . +A portable application cannot assume that context includes any process-wide +static data, possibly including +.Va errno . +Users manipulating contexts should take care to handle these explicitly when required. -.SH ATTRIBUTES -.LP -See \fBattributes\fR(7) for descriptions of the following attributes: -.sp - -.sp -.TS -box; -c | c -l | l . -ATTRIBUTE TYPE ATTRIBUTE VALUE -_ -Interface Stability Standard -.TE - -.SH SEE ALSO -.LP -.BR sigaction (2), -.BR sigaltstack (2), -.BR sigprocmask (2), -.BR bsd_signal (3C), -.BR makecontext (3C), -.BR setjmp (3C), -.BR sigsetjmp (3C), -.BR ucontext.h (3HEAD), -.BR attributes (7), -.BR standards (7) +.Sh INTERFACE STABILITY +.Sy Committed +.Sh SEE ALSO +.Xr sigaction 2 , +.Xr sigaltstack 2 , +.Xr sigprocmask 2 , +.Xr bsd_signal 3C , +.Xr makecontext 3C , +.Xr setjmp 3C , +.Xr sigsetjmp 3C , +.Xr ucontext.h 3HEAD , +.Xr attributes 7 , +.Xr standards 7 diff --git a/usr/src/pkg/manifests/system-test-ostest.p5m b/usr/src/pkg/manifests/system-test-ostest.p5m index e1530adf7c..9ee06d5fbc 100644 --- a/usr/src/pkg/manifests/system-test-ostest.p5m +++ b/usr/src/pkg/manifests/system-test-ostest.p5m @@ -13,7 +13,7 @@ # Copyright (c) 2012, 2016 by Delphix. All rights reserved. # Copyright 2014, OmniTI Computer Consulting, Inc. All rights reserved. # Copyright 2020 Joyent, Inc. -# Copyright 2021 OmniOS Community Edition (OmniOSce) Association. +# Copyright 2022 OmniOS Community Edition (OmniOSce) Association. # Copyright 2021 Tintri by DDN, Inc. All rights reserved. # Copyright 2022 Oxide Computer Company # Copyright 2022 MNX Cloud, Inc. @@ -164,6 +164,8 @@ file path=opt/os-tests/tests/uccid/txn-pollerr mode=0555 file path=opt/os-tests/tests/uccid/yk mode=0555 file path=opt/os-tests/tests/uccid/yk-poll mode=0555 file path=opt/os-tests/tests/uccid/yk-readonly mode=0555 +file path=opt/os-tests/tests/ucontext.32 mode=0555 +file path=opt/os-tests/tests/ucontext.64 mode=0555 file path=opt/os-tests/tests/writev.32 mode=0555 file path=opt/os-tests/tests/writev.64 mode=0555 file path=opt/os-tests/tests/zen_umc_test mode=0555 diff --git a/usr/src/test/os-tests/runfiles/default.run b/usr/src/test/os-tests/runfiles/default.run index 7a4189cf48..de2b29f2f1 100644 --- a/usr/src/test/os-tests/runfiles/default.run +++ b/usr/src/test/os-tests/runfiles/default.run @@ -12,7 +12,7 @@ # # Copyright (c) 2012 by Delphix. All rights reserved. # Copyright 2020 Joyent, Inc. -# Copyright 2021 OmniOS Community Edition (OmniOSce) Association. +# Copyright 2022 OmniOS Community Edition (OmniOSce) Association. # Copyright 2021 Tintri by DDN, Inc. All rights reserved. # Copyright 2022 Oxide Computer Company # Copyright 2022 MNX Cloud, Inc. @@ -39,6 +39,9 @@ tests = ['poll_test', 'epoll_test'] [/opt/os-tests/tests/clock_gettime.32] [/opt/os-tests/tests/clock_gettime.64] +[/opt/os-tests/tests/ucontext.32] +[/opt/os-tests/tests/ucontext.64] + [/opt/os-tests/tests/secflags] user = root tests = ['secflags_aslr', diff --git a/usr/src/test/os-tests/tests/Makefile b/usr/src/test/os-tests/tests/Makefile index afa9df81ed..a30832e8ee 100644 --- a/usr/src/test/os-tests/tests/Makefile +++ b/usr/src/test/os-tests/tests/Makefile @@ -46,6 +46,7 @@ PROGS = \ clock_gettime \ eventfd \ odirectory \ + ucontext \ writev CPPFLAGS += -D_REENTRANT @@ -65,6 +66,9 @@ clock_gettime.32 := CSTD = $(CSTD_GNU99) clock_gettime.64 := LDLIBS64 += -lproc clock_gettime.64 := CSTD = $(CSTD_GNU99) +ucontext.32 := SMOFF += unreachable +ucontext.64 := SMOFF += unreachable + writev.32 := CPPFLAGS += -D_FILE_OFFSET_BITS=64 writev.32 := CSTD = $(CSTD_GNU99) writev.64 := CSTD = $(CSTD_GNU99) diff --git a/usr/src/test/os-tests/tests/ucontext.c b/usr/src/test/os-tests/tests/ucontext.c new file mode 100644 index 0000000000..a6e43941c1 --- /dev/null +++ b/usr/src/test/os-tests/tests/ucontext.c @@ -0,0 +1,103 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2022 OmniOS Community Edition (OmniOSce) Association. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static __thread uint64_t tlsvar; +static ucontext_t ctx; +static uint32_t failures; +static pthread_t tid; + +#define THREAD1_VALUE 0x1010 +#define THREAD2_VALUE 0x0202 + +void +report(char *tag) +{ + pthread_t ltid = pthread_self(); + + printf(" %-14s: thread=%x, TLS variable=%x\n", + tag, (uint_t)ltid, tlsvar); +} + +void +run(void) +{ + pthread_t ltid = pthread_self(); + + printf("Coroutine started from second thread\n"); + report("coroutine"); + + if (ltid != tid) { + fprintf(stderr, + "FAIL: coroutine thread ID is %x, expected %x\n", + ltid, tid); + atomic_inc_32(&failures); + } + + if (tlsvar != THREAD2_VALUE) { + fprintf(stderr, + "FAIL: coroutine TLS variable is %x, expected %x\n", + tlsvar, THREAD2_VALUE); + atomic_inc_32(&failures); + } +} + +void * +thread(void *arg __unused) +{ + tlsvar = THREAD2_VALUE; + + report("second thread"); + /* + * setcontext() does not return if successful, checking the return + * value upsets smatch. + */ + (void) setcontext(&ctx); + errx(EXIT_FAILURE, "setcontext() returned and should not have."); + + return (NULL); +} + +int +main(void) +{ + char stk[SIGSTKSZ]; + void *status; + + tlsvar = THREAD1_VALUE; + + report("main thread"); + + VERIFY0(getcontext(&ctx)); + ctx.uc_link = NULL; + ctx.uc_stack.ss_sp = stk; + ctx.uc_stack.ss_size = sizeof (stk); + makecontext(&ctx, run, 0); + + VERIFY0(pthread_create(&tid, NULL, thread, NULL)); + VERIFY0(pthread_join(tid, &status)); + + return (failures == 0 ? EXIT_SUCCESS : EXIT_FAILURE); +} -- cgit v1.2.3