Re: [PATCH] x86/asm/64: do not clear high 32 bits of syscall number when CONFIG_X86_X32=y

From: Dmitry V. Levin
Date: Thu Sep 14 2017 - 16:21:21 EST


On Wed, Sep 13, 2017 at 06:49:21PM +0200, Oleg Nesterov wrote:
> On 09/13, Dmitry V. Levin wrote:
> >
> > Before this change, CONFIG_X86_X32=y fastpath behaviour was different
> > from slowpath:
>
> and even with this change they differ if CONFIG_X86_X32=n?

No, I don't think so.

> do_syscall_64() does "nr & __SYSCALL_MASK" unconditionally,

yes

> this clears the upper bits, no?

Why? As "nr" is of type "unsigned long" and __SYSCALL_MASK is either
(~(__X32_SYSCALL_BIT)) or (~0), that is, an integer with the sign bit set,
in "nr & __SYSCALL_MASK" expression __SYSCALL_MASK is sign-extended
to unsigned long. When __SYSCALL_MASK is defined to (~0),
"nr & __SYSCALL_MASK" is optimized to "nr" at compilation time:

$ echo 'unsigned long foo(unsigned long nr) { return nr & (~0); }' |
gcc -Wall -O2 -xc -S -o - - |
sed -n '/cfi_/,/cfi_/p'
.cfi_startproc
movq %rdi, %rax
ret
.cfi_endproc

> And why __SYSCALL_MASK is not "unsigned long" ? IOW, why do we want to silently
> ignore the upper bits in $rax ?

__SYSCALL_MASK is "int" but it is being sign-extended to unsigned long in all
(two) places of arch/x86/entry/common.c where it is used.

> Or I am totally confused?

The thing looks like it was designed to confuse people.


--
ldv

Attachment: signature.asc
Description: PGP signature