Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 22 Oct 2004 15:43:51 +0400 (MSD)
From:      Andrew Belashov <bel@orel.ru>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   sparc64/72998: [patch] set_mcontext() change syscalls parameters on sparc64
Message-ID:  <200410221143.i9MBhpna088318@white.orel.ru>
Resent-Message-ID: <200410221150.i9MBoDOO028436@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>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@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:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200410221143.i9MBhpna088318>