From: Denys Vlasenko <dvlasenk@redhat.com>
To: Brian Gerst <brgerst@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>,
Denys Vlasenko <vda.linux@googlemail.com>,
Andy Lutomirski <luto@amacapital.net>,
Linus Torvalds <torvalds@linux-foundation.org>,
Steven Rostedt <rostedt@goodmis.org>,
Borislav Petkov <bp@alien8.de>, "H. Peter Anvin" <hpa@zytor.com>,
Oleg Nesterov <oleg@redhat.com>,
Frederic Weisbecker <fweisbec@gmail.com>,
Alexei Starovoitov <ast@plumgrid.com>,
Will Drewry <wad@chromium.org>, Kees Cook <keescook@chromium.org>,
X86 ML <x86@kernel.org>,
"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH] x86: vdso32/syscall.S: do not load __USER32_DS to %ss
Date: Tue, 24 Mar 2015 21:17:05 +0100 [thread overview]
Message-ID: <5511C641.7000700@redhat.com> (raw)
In-Reply-To: <CAMzpN2huVk1nNGLYsYXCOyCvpYBTwKYCyn29JQWZ+r8ZZmyskA@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 1117 bytes --]
On 03/24/2015 05:55 PM, Brian Gerst wrote:
>>> Might be nice to place a more generic description there, which
>>> registers are expected to be saved by user-space calling in here, etc.
>>
>> __kernel_vsyscall entry point has the same ABI in any 32-bit vDSO,
>> the good old int 0x80 calling convention:
>>
>> syscall# in eax,
>> params in ebx/ecx/edx/esi/edi/ebp,
>> all registers are preserved by the syscall.
>>
>> (I think we don't guarantee that all flags are preserved:
>> I have a testcase where DF gets cleared).
>
> DF should always be clear on any function call per the C ABI. But,
> eflags should be preserved, at least the non-privileged bits. I'd
> like to see that testcase.
The testcase is a simplistic example of how to find and use
32-bit vDSO to perform system calls.
It also sets flags.DF before syscall, and checks whether registers
are preserved, including flags.DF.
On 32-bit kernel (on Intel CPU, where vDSO uses SYSENTER), I see this:
$ ./test32_syscall_vdso
Result:1
whereas on 64-bit it is
./test32_syscall_vdso
Result:0
"Result:1" means that DF was cleared.
See attached source.
[-- Attachment #2: test32_syscall_vdso.c --]
[-- Type: text/x-csrc, Size: 2919 bytes --]
// (Assuming that int 80 works,) test that syscall32/sysenter32 works
//
// i686-gcc -Os -Wall -static
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <elf.h>
long syscall_addr;
long get_syscall(char **envp)
{
Elf32_auxv_t *auxv;
while (*envp++ != NULL)
continue;
for (auxv = (void *)envp; auxv->a_type != AT_NULL; auxv++)
if( auxv->a_type == AT_SYSINFO)
return auxv->a_un.a_val;
fprintf(stderr, "AT_SYSINFO not supplied, can't test\n");
exit(0); /* this is not a failure */
}
int nfds;
fd_set rfds;
fd_set wfds;
fd_set efds;
struct timespec timeout;
sigset_t sigmask;
struct {
sigset_t *sp;
int sz;
} sigmask_desc;
char RES[] = "Result:0\n";
void prep_args()
{
nfds = 42;
FD_ZERO(&rfds);
FD_ZERO(&wfds);
FD_ZERO(&efds);
FD_SET(0, &rfds);
FD_SET(1, &wfds);
FD_SET(2, &efds);
timeout.tv_sec = 0;
timeout.tv_nsec = 123;
sigemptyset(&sigmask);
sigaddset(&sigmask, SIGINT);
sigaddset(&sigmask, SIGUSR2);
sigaddset(&sigmask, SIGRTMAX);
sigmask_desc.sp = &sigmask;
sigmask_desc.sz = 8; /* bytes */
}
#define PSELECT 308
// pselect(nfds,rfds,wfds,efds,timeout,sigmask)
int main(int argc, char **argv, char **envp)
{
// This only works for non-static builds:
//syscall_addr = dlsym(dlopen("linux-gate.so.1", RTLD_NOW), "__kernel_vsyscall");
syscall_addr = get_syscall(envp);
prep_args();
asm("\n"
// Try 6-arg syscall: pselect. It should return quickly
" mov $308,%eax\n" // PSELECT
" mov nfds,%ebx\n" // ebx arg1
" mov $rfds,%ecx\n" // ecx arg2
" mov $wfds,%edx\n" // edx arg3
" mov $efds,%esi\n" // esi arg4
" mov $timeout,%edi\n" // edi arg5
" mov $sigmask_desc,%ebp\n" // %ebp arg6
" std\n"
" call *syscall_addr\n"
// Check that registers are not clobbered
" pushf\n"
" pop %eax\n"
" cmp nfds,%ebx\n" // ebx arg1
" movb $0x32,RES+7\n"
" jne end\n"
" cmp $rfds,%ecx\n" // ecx arg2
" movb $0x33,RES+7\n"
" jne end\n"
" cmp $wfds,%edx\n" // edx arg3
" movb $0x34,RES+7\n"
" jne end\n"
" cmp $efds,%esi\n" // esi arg4
" movb $0x35,RES+7\n"
" jne end\n"
" cmp $timeout,%edi\n" // edi arg5
" movb $0x36,RES+7\n"
" jne end\n"
" cmpl $sigmask_desc,%ebp\n" // %ebp arg6
" movb $0x37,RES+7\n"
" jne end\n"
// This fails (DF is not preserved)
// on 32-bit kernels. 64-bit ones worked:
" bt $10,%eax\n" //flags.DF still set?
" movb $0x31,RES+7\n"
" jnc end\n"
" movb $0x30,RES+7\n"
"end:\n"
" mov $4,%eax\n" // WRITE
" mov $1,%ebx\n" // ebx arg1
" mov $RES,%ecx\n" // ecx arg2
" mov $9,%edx\n" // edx arg3
" int $0x80\n"
// Error if result is not 0 or 1
// (result:1 means DF was clobbered)
" mov $1,%eax\n" // EXIT
" xor %ebx,%ebx\n" // ebx arg1
" cmpb $0x31,RES+7\n"
" ja 1f\n"
" int $0x80\n"
"1: inc %ebx\n"
" int $0x80\n"
);
return 42; /* not reached */
}
next prev parent reply other threads:[~2015-03-24 20:17 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-03-23 16:47 [PATCH] x86: vdso32/syscall.S: do not load __USER32_DS to %ss Denys Vlasenko
2015-03-23 19:37 ` Andy Lutomirski
2015-03-23 20:38 ` Andy Lutomirski
2015-03-23 21:55 ` Denys Vlasenko
2015-03-24 6:34 ` Ingo Molnar
2015-03-24 14:08 ` Denys Vlasenko
2015-03-24 15:50 ` Ingo Molnar
2015-03-24 16:55 ` Brian Gerst
2015-03-24 20:17 ` Denys Vlasenko [this message]
2015-03-24 21:40 ` Andy Lutomirski
2015-03-25 9:28 ` Ingo Molnar
2015-03-25 15:03 ` Denys Vlasenko
2015-03-25 15:17 ` Andy Lutomirski
2015-03-25 14:55 ` Denys Vlasenko
2015-03-25 15:12 ` Andy Lutomirski
2015-03-25 0:59 ` Brian Gerst
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=5511C641.7000700@redhat.com \
--to=dvlasenk@redhat.com \
--cc=ast@plumgrid.com \
--cc=bp@alien8.de \
--cc=brgerst@gmail.com \
--cc=fweisbec@gmail.com \
--cc=hpa@zytor.com \
--cc=keescook@chromium.org \
--cc=linux-kernel@vger.kernel.org \
--cc=luto@amacapital.net \
--cc=mingo@kernel.org \
--cc=oleg@redhat.com \
--cc=rostedt@goodmis.org \
--cc=torvalds@linux-foundation.org \
--cc=vda.linux@googlemail.com \
--cc=wad@chromium.org \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox