NetBSD Problem Report #53316

From martin@duskware.de  Sat May 26 11:59:31 2018
Return-Path: <martin@duskware.de>
Received: from mail.netbsd.org (mail.netbsd.org [199.233.217.200])
	(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
	(Client CN "mail.NetBSD.org", Issuer "mail.NetBSD.org CA" (not verified))
	by mollari.NetBSD.org (Postfix) with ESMTPS id EABAB7A21F
	for <gnats-bugs@gnats.NetBSD.org>; Sat, 26 May 2018 11:59:31 +0000 (UTC)
From: martin@NetBSD.org
Reply-To: martin@NetBSD.org
To: gnats-bugs@NetBSD.org
Subject: syscalls with more than 6 args may not work
X-Send-Pr-Version: 3.95

>Number:         53316
>Category:       port-amd64
>Synopsis:       syscalls with more than 6 args may not work
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    port-amd64-maintainer
>State:          closed
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sat May 26 12:00:00 +0000 2018
>Closed-Date:    Mon May 28 08:00:02 +0000 2018
>Last-Modified:  Mon May 28 08:20:01 +0000 2018
>Originator:     Martin Husemann
>Release:        NetBSD 8.99.18
>Organization:
The NetBSD Foundation, Inc.
>Environment:
System: NetBSD night-owl.duskware.de 8.99.18 NetBSD 8.99.18 (NIGHT-OWL) #600: Sat May 26 09:22:08 CEST 2018 martin@night-owl.duskware.de:/usr/src/sys/arch/amd64/compile/NIGHT-OWL amd64
Architecture: x86_64
Machine: amd64
>Description:

The new test /usr/tests/lib/libc/sys/t_syscall fails on amd64. It tries
to call mmap(2) via __syscall(2) with this code:

        p = (const char *)__SYSCALL_TO_UINTPTR_T(__syscall(SYS_mmap,
                0, sizeof(secrect_data), PROT_READ, MAP_PRIVATE, fd, 0, 0, 0));

This ends up in the kernel in src/sys/arch/x86/x86/syscall.c here:

    119 #ifdef __x86_64__
    120         /*
    121          * The first 6 syscall args are passed in rdi, rsi, rdx, r10, r8 and r9
    122          * (rcx gets copied to r10 in the libc stub because the syscall
    123          * instruction overwrites %cx) and are together in the trap frame
    124          * with space following for 4 more entries.
    125          */
    126         if (__predict_false(callp->sy_argsize > 6 * 8)) {
    127                 error = copyin((register_t *)frame->tf_rsp + 1,
    128                     &frame->tf_arg6, callp->sy_argsize - 6 * 8);
    129                 if (error != 0)
    130                         goto bad;
    131         }

In this case, callp->sy_argsize is 72 (bytes), so 9 arguments, 6 of which
come in registers and already are in the trapframe (and thos work fine).
The 3 additional args are copied in from one longword below the current
stack, and verifying with gdb in userland shows the copyin() getting the
right values from the stack.

The syscall stub in libc is plain RSYSCALL. I don't know the amd64 off
hand good enough, maybe this is a variadic function only issue.

The data copied in and the 6 working args match what ktrace prints
about the call.

The test program works fine on various other architectures, including some
64bit ones.

>How-To-Repeat:

cd /tmp
ktrace /usr/tests/lib/libc/sys/t_syscall mmap___syscall
kdump

and watch for this mmap right after a 1k write to the test file:

        \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
        \0\0\0"
  2071      1 t_syscall RET   write 1024/0x400
  2071      1 t_syscall CALL  mmap(0,0x400,PROT_READ,0x2<PRIVATE,,,>,3,0,0x7f7f00000000)
  2071      1 t_syscall RET   mmap 140187597225984/0x7f7ff7ef4000

Note that the last arg is wrong, so the eroneous offset requested in the mmap
leads to a sigbus as we are accessing the resulting map beyound EOF.

>Fix:
n/a

>Release-Note:

>Audit-Trail:
From: Valery Ushakov <uwe@stderr.spb.ru>
To: gnats-bugs@NetBSD.org
Cc: martin@NetBSD.org
Subject: Re: port-amd64/53316: syscalls with more than 6 args may not work
Date: Mon, 28 May 2018 04:34:16 +0300

 On Sat, May 26, 2018 at 12:00:00 +0000, martin@NetBSD.org wrote:

 > The new test /usr/tests/lib/libc/sys/t_syscall fails on amd64. It tries
 > to call mmap(2) via __syscall(2) with this code:
 > 
 >   p = (const char *)__SYSCALL_TO_UINTPTR_T(__syscall(SYS_mmap,
 >           0, sizeof(secrect_data), PROT_READ, MAP_PRIVATE, fd, 0, 0, 0));

 The last but one zero you pass is an int, but the arguments passed on
 the stack are passed in 8-byte chunks, so compiler emits movl that
 stores zero to the LSW, but the MSW contains garbage.  Syscall code in
 the kernel will pick that half-garbage value as the 8-byte off_t
 argument.

 I guess you are passing two zeroes to manually create 64-bit off_t,
 but as you can see that doesn't work as expected.

 The test should do

    ... fd, /* pad */ 0, (off_t)0)

 I think, which should also DTRT in the 32-bit case.

 The code works on sparc64 b/c its ABI defines that stack args are
 sign-extended to 8-bytes.

 -uwe 

State-Changed-From-To: open->closed
State-Changed-By: martin@NetBSD.org
State-Changed-When: Mon, 28 May 2018 08:00:02 +0000
State-Changed-Why:
Fixed (in the test case)


From: Martin Husemann <martin@duskware.de>
To: Valery Ushakov <uwe@stderr.spb.ru>
Cc: gnats-bugs@NetBSD.org, martin@NetBSD.org
Subject: Re: port-amd64/53316: syscalls with more than 6 args may not work
Date: Mon, 28 May 2018 09:56:42 +0200

 Duh, of course. Thanks!

 Martin

From: "Martin Husemann" <martin@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/53316 CVS commit: src/tests/lib/libc/sys
Date: Mon, 28 May 2018 07:55:56 +0000

 Module Name:	src
 Committed By:	martin
 Date:		Mon May 28 07:55:56 UTC 2018

 Modified Files:
 	src/tests/lib/libc/sys: t_syscall.c

 Log Message:
 PR port-amd64/53316: two int don't make a long (when passed to
 a C variadic function)


 To generate a diff of this commit:
 cvs rdiff -u -r1.2 -r1.3 src/tests/lib/libc/sys/t_syscall.c

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

>Unformatted:

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.43 2018/01/16 07:36:43 maya Exp $
$NetBSD: gnats_config.sh,v 1.9 2014/08/02 14:16:04 spz Exp $
Copyright © 1994-2017 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.