sparc64/72998: [patch] set_mcontext() change syscalls parameters on
sparc64
Andrew Belashov
bel at orel.ru
Fri Oct 22 04:50:13 PDT 2004
>Number: 72998
>Category: sparc64
>Synopsis: [patch] set_mcontext() change syscalls parameters on sparc64
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: freebsd-sparc64
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Fri Oct 22 11:50:12 GMT 2004
>Closed-Date:
>Last-Modified:
>Originator: Andrew Belashov
>Release: FreeBSD 5.3-BETA7 sparc64
>Organization:
JSC CenterTelecom
>Environment:
System: FreeBSD bel.localdomain 5.3-BETA7 FreeBSD 5.3-BETA7 #11: Thu Oct 14 13:02:53 MSD 2004 bel at bel.localdomain:/usr/obj/usr/src/sys/SUNC3D sparc64
>Description:
Some syscalls using set_mcontext can sneakily change
parameters and later when those syscalls references parameters,
they will wrongly use register values in mcontext_t.
This problem is critical for thread related syscalls!
>How-To-Repeat:
Use following changes in kernel:
--- debug.patch begins here ---
--- sys/kern/kern_kse.c.orig Fri Oct 22 14:47:07 2004
+++ sys/kern/kern_kse.c Fri Oct 22 14:46:13 2004
@@ -140,8 +140,12 @@ kse_switchin(struct thread *td, struct k
if (!error && (uap->flags & KSE_SWITCHIN_SETTMBX))
error = (suword(&ku->ku_mailbox->km_curthread,
(long)uap->tmbx) != 0 ? EINVAL : 0);
+ TR2("thread_schedule_upcall: before set_mcontext: tmbx %p flags %d",
+ uap->tmbx, uap->flags);
if (!error)
error = set_mcontext(td, &tmbx.tm_context.uc_mcontext);
+ TR2("thread_schedule_upcall: after set_mcontext: tmbx %p flags %d",
+ uap->tmbx, uap->flags);
if (!error) {
suword32(&uap->tmbx->tm_lwp, td->td_tid);
if (uap->flags & KSE_SWITCHIN_SETTMBX) {
--- sys/sparc64/conf/GENERIC.orig Wed Sep 22 23:23:39 2004
+++ sys/sparc64/conf/GENERIC Fri Oct 22 15:00:49 2004
@@ -201,3 +201,7 @@
device firewire # FireWire bus code
device sbp # SCSI over FireWire (Requires scbus and da)
device fwe # Ethernet over FireWire (non-standard!)
+
+options KDB #Enable kernel debugger support
+options DDB #Enable the kernel debugger
+options GDB #Support remote GDB
+options KTR
+options KTR_COMPILE=(KTR_GEN|KTR_SMP|KTR_TRAP|KTR_INTR|KTR_SIG|KTR_PROC|KTR_SYSC)
+options KTR_ENTRIES=8192
--- debug.patch ends here ---
Run any simple threated program compiled with libkse. For example:
--- hello_d.c begins here ---
/****************************************************************************
*
* Simple diff mode test.
*
* $FreeBSD: src/lib/libpthread/test/hello_d.c,v 1.1 2000/04/24 21:07:37 jasone Exp $
*
****************************************************************************/
#include <stdio.h>
#include <string.h>
#include <pthread.h>
extern int _libkse_debug;
void *
entry(void * a_arg)
{
char *str = NULL;
fprintf(stderr, "Hello world\n");
#if 0
*str = 'a';
#endif
return NULL;
}
int
main()
{
pthread_t thread;
int error;
pthread_attr_t attr;
int scope;
/*
_libkse_debug = 1;
*/
error = pthread_attr_init(&attr);
if (error)
fprintf(stderr, "Error in pthread_attr_init(): %s\n",
strerror(error));
error = pthread_attr_getscope(&attr, &scope);
if (error)
fprintf(stderr, "Error in pthread_attr_getscope(): %s\n",
strerror(error));
printf("Default scope: %d\n", scope);
#if 1
scope |= PTHREAD_SCOPE_SYSTEM;
#endif
printf("Set scope: %d\n", scope);
error = pthread_attr_setscope(&attr, scope);
if (error)
fprintf(stderr, "Error in pthread_attr_setscope(): %s\n",
strerror(error));
error = pthread_create(&thread, &attr, entry, NULL);
if (error)
fprintf(stderr, "Error in pthread_create(): %s\n",
strerror(error));
error = pthread_join(thread, NULL);
if (error)
fprintf(stderr, "Error in pthread_join(): %s\n",
strerror(error));
error = pthread_attr_destroy(&attr);
if (error)
fprintf(stderr, "Error in pthread_attr_destroy(): %s\n",
strerror(error));
return 0;
}
--- hello_d.c ends here ---
Go to kernel debugger by pressing Control-Alt-Esc and "show ktr".
Compare arguments before and after set_mcontext.
>Fix:
Simple patch. See also amd64/amd64/trap.c revision 1.278.
<http://www.freebsd.org/cgi/cvsweb.cgi/src/sys/amd64/amd64/trap.c.diff?r1=1.277&r2=1.278>
--- sparc64_trap.patch begins here ---
--- sys/sparc64/sparc64/trap.c.orig Thu Aug 5 09:42:43 2004
+++ sys/sparc64/sparc64/trap.c Fri Sep 24 10:09:06 2004
@@ -559,7 +559,8 @@ syscall(struct trapframe *tf)
narg = callp->sy_narg & SYF_ARGMASK;
if (narg <= regcnt) {
- argp = &tf->tf_out[reg];
+ argp = args;
+ bcopy(&tf->tf_out[reg], args, sizeof(args[0]) * regcnt);
error = 0;
} else {
KASSERT(narg <= sizeof(args) / sizeof(args[0]),
--- sparc64_trap.patch ends here ---
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-sparc64
mailing list