Fix linux personality syscall wrapper
The personality system call, starting with linux kernel commit v2.6.29-6609-g11d06b2a1e5658f448a308aa3beb97bacd64a940, always successfully changes the personality if requested. The syscall wrapper, however, still can return an error in the following cases: - the value returned by the system call looks like an error due to architecture limitations of 32-bit kernels; - a personality greater than 0xffffffff is passed to the system call, and the 64-bit kernel does not have commit v2.6.35-rc1-372-g485d527686850d68a0e9006dd9904f19f122485e that would truncate this value to unsigned int; - on sparc64, the value returned by the system call looks like an error due to sparc64 kernel sign extension bug. The solution is three-fold: - move generic syscalls.list personality entry to generic 64-bit syscalls.list file; - for each 32-bit architecture that use negated errno semantics, add a NOERRNO personality entry to their syscalls.list file; - for sparc64 and 32-bit architectures that use dedicated registers to flag syscall errors, add a wrapper around personality syscall; if the system call return value is flagged as an error, this wrapper returns the negated "would be errno" value, otherwise it returns the system call return value; on sparc64, it also truncates the personality argument to unsigned int before passing it to the kernel. [BZ #19408] * sysdeps/unix/sysv/linux/personality.c: New file. * sysdeps/unix/sysv/linux/sparc/sparc64/personality.c: Likewise. * sysdeps/unix/sysv/linux/tst-personality.c: Likewise. * sysdeps/unix/sysv/linux/Makefile [$(subdir) == misc] (sysdep_routines): Add personality. (tests): Add tst-personality. * sysdeps/unix/sysv/linux/syscalls.list (personality): Move ... * sysdeps/unix/sysv/linux/wordsize-64/syscalls.list: ... here. * sysdeps/unix/sysv/linux/arm/syscalls.list (personality): New entry. * sysdeps/unix/sysv/linux/hppa/syscalls.list (personality): Likewise. * sysdeps/unix/sysv/linux/i386/syscalls.list (personality): Likewise. * sysdeps/unix/sysv/linux/m68k/syscalls.list (personality): Likewise. * sysdeps/unix/sysv/linux/microblaze/syscalls.list (personality): Likewise. * sysdeps/unix/sysv/linux/mips/mips64/n32/syscalls.list (personality): Likewise. * sysdeps/unix/sysv/linux/s390/s390-32/syscalls.list (personality): Likewise. * sysdeps/unix/sysv/linux/sh/syscalls.list (personality): Likewise. * sysdeps/unix/sysv/linux/x86_64/x32/syscalls.list (personality): Likewise.
This commit is contained in:
parent
cc42170ef6
commit
e0043e17df
25
ChangeLog
25
ChangeLog
|
@ -1,3 +1,28 @@
|
|||
2015-12-30 Dmitry V. Levin <ldv@altlinux.org>
|
||||
|
||||
[BZ #19408]
|
||||
* sysdeps/unix/sysv/linux/personality.c: New file.
|
||||
* sysdeps/unix/sysv/linux/sparc/sparc64/personality.c: Likewise.
|
||||
* sysdeps/unix/sysv/linux/tst-personality.c: Likewise.
|
||||
* sysdeps/unix/sysv/linux/Makefile [$(subdir) == misc]
|
||||
(sysdep_routines): Add personality.
|
||||
(tests): Add tst-personality.
|
||||
* sysdeps/unix/sysv/linux/syscalls.list (personality): Move ...
|
||||
* sysdeps/unix/sysv/linux/wordsize-64/syscalls.list: ... here.
|
||||
* sysdeps/unix/sysv/linux/arm/syscalls.list (personality): New entry.
|
||||
* sysdeps/unix/sysv/linux/hppa/syscalls.list (personality): Likewise.
|
||||
* sysdeps/unix/sysv/linux/i386/syscalls.list (personality): Likewise.
|
||||
* sysdeps/unix/sysv/linux/m68k/syscalls.list (personality): Likewise.
|
||||
* sysdeps/unix/sysv/linux/microblaze/syscalls.list (personality):
|
||||
Likewise.
|
||||
* sysdeps/unix/sysv/linux/mips/mips64/n32/syscalls.list (personality):
|
||||
Likewise.
|
||||
* sysdeps/unix/sysv/linux/s390/s390-32/syscalls.list (personality):
|
||||
Likewise.
|
||||
* sysdeps/unix/sysv/linux/sh/syscalls.list (personality): Likewise.
|
||||
* sysdeps/unix/sysv/linux/x86_64/x32/syscalls.list (personality):
|
||||
Likewise.
|
||||
|
||||
2015-12-30 Aurelien Jarno <aurelien@aurel32.net>
|
||||
|
||||
* sysdeps/unix/sysv/linux/arm/ioperm.c: Do not include <string.h>.
|
||||
|
|
|
@ -16,7 +16,8 @@ include $(firstword $(wildcard $(sysdirs:=/sysctl.mk)))
|
|||
|
||||
sysdep_routines += clone llseek umount umount2 readahead \
|
||||
setfsuid setfsgid makedev epoll_pwait signalfd \
|
||||
eventfd eventfd_read eventfd_write prlimit
|
||||
eventfd eventfd_read eventfd_write prlimit \
|
||||
personality
|
||||
|
||||
CFLAGS-gethostid.c = -fexceptions
|
||||
CFLAGS-tst-writev.c += "-DARTIFICIAL_LIMIT=0x80000000-__getpagesize()"
|
||||
|
@ -41,7 +42,7 @@ sysdep_headers += sys/mount.h sys/acct.h sys/sysctl.h \
|
|||
bits/socket_type.h bits/syscall.h bits/sysctl.h \
|
||||
bits/mman-linux.h
|
||||
|
||||
tests += tst-clone tst-fanotify
|
||||
tests += tst-clone tst-fanotify tst-personality
|
||||
|
||||
# Generate the list of SYS_* macros for the system calls (__NR_* macros).
|
||||
|
||||
|
|
|
@ -19,6 +19,8 @@ prlimit64 EXTRA prlimit64 i:iipp prlimit64
|
|||
|
||||
fanotify_mark EXTRA fanotify_mark i:iiiiis fanotify_mark
|
||||
|
||||
personality EXTRA personality Ei:i __personality personality
|
||||
|
||||
# Semaphore and shm system calls. msgctl, shmctl, and semctl have C
|
||||
# wrappers (to set __IPC_64).
|
||||
msgget - msgget i:ii __msgget msgget
|
||||
|
|
|
@ -37,3 +37,4 @@ setrlimit - setrlimit i:ip __setrlimit setrlimit
|
|||
getrlimit - getrlimit i:ip __getrlimit getrlimit
|
||||
prlimit64 EXTRA prlimit64 i:iipp __prlimit64 prlimit64@@GLIBC_2.17
|
||||
fanotify_mark EXTRA fanotify_mark i:iiiiis __fanotify_mark fanotify_mark@@GLIBC_2.19
|
||||
personality EXTRA personality Ei:i __personality personality
|
||||
|
|
|
@ -25,3 +25,5 @@ waitpid - waitpid Ci:ipi __waitpid waitpid
|
|||
prlimit64 EXTRA prlimit64 i:iipp prlimit64
|
||||
|
||||
fanotify_mark EXTRA fanotify_mark i:iiiiis fanotify_mark
|
||||
|
||||
personality EXTRA personality Ei:i __personality personality
|
||||
|
|
|
@ -19,3 +19,4 @@ setfsuid - setfsuid32 Ei:i setfsuid
|
|||
cacheflush EXTRA cacheflush i:iiii __cacheflush cacheflush
|
||||
prlimit64 EXTRA prlimit64 i:iipp prlimit64
|
||||
fanotify_mark EXTRA fanotify_mark i:iiiiis fanotify_mark
|
||||
personality EXTRA personality Ei:i __personality personality
|
||||
|
|
|
@ -4,6 +4,7 @@ cacheflush EXTRA cacheflush i:iiii __cacheflush cacheflush
|
|||
|
||||
prlimit64 EXTRA prlimit64 i:iipp prlimit64
|
||||
fanotify_mark EXTRA fanotify_mark i:iiiiis fanotify_mark
|
||||
personality EXTRA personality Ei:i __personality personality
|
||||
|
||||
# Semaphore and shm system calls. msgctl, shmctl, and semctl have C
|
||||
# wrappers (to set __IPC_64).
|
||||
|
|
|
@ -6,3 +6,5 @@ sync_file_range - sync_file_range Ci:iiii sync_file_range
|
|||
prlimit64 EXTRA prlimit64 i:iipp prlimit64
|
||||
|
||||
fanotify_mark EXTRA fanotify_mark i:iiiis fanotify_mark
|
||||
|
||||
personality EXTRA personality Ei:i __personality personality
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
/* Copyright (C) 2015 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <sys/personality.h>
|
||||
#include <sysdep.h>
|
||||
|
||||
extern __typeof (personality) __personality;
|
||||
|
||||
int
|
||||
__personality (unsigned long persona)
|
||||
{
|
||||
#ifdef PERSONALITY_TRUNCATE_ARGUMENT
|
||||
/* Starting with kernel commit v2.6.21-3117-g97dc32c, the type of
|
||||
task_struct->pesonality is "unsigned int".
|
||||
Starting with kernel commit v2.6.35-rc1-372-g485d527, the personality
|
||||
syscall accepts "unsigned int" instead of "long unsigned int".
|
||||
Inbetween, a personality argument that does not fit into "unsigned int"
|
||||
would result to system call returning -EINVAL.
|
||||
We explicitly truncate the personality argument to "unsigned int"
|
||||
to eliminate the uncertainty. */
|
||||
persona = (unsigned int) persona;
|
||||
#endif
|
||||
|
||||
INTERNAL_SYSCALL_DECL (err);
|
||||
long ret = INTERNAL_SYSCALL (personality, err, 1, persona);
|
||||
|
||||
/* Starting with kernel commit v2.6.29-6609-g11d06b2, the personality syscall
|
||||
never fails. However, 32-bit kernels might flag valid values as errors, so
|
||||
we need to reverse the error setting. We can't use the raw result as some
|
||||
arches split the return/error values. */
|
||||
if (__glibc_unlikely (INTERNAL_SYSCALL_ERROR_P (ret, err)))
|
||||
ret = -INTERNAL_SYSCALL_ERRNO (ret, err);
|
||||
return ret;
|
||||
}
|
||||
weak_alias (__personality, personality)
|
|
@ -20,3 +20,4 @@ setrlimit - setrlimit i:ip __setrlimit setrlimit@GLIBC_2.0 setrlimit@@GLIBC_2.2
|
|||
|
||||
prlimit64 EXTRA prlimit64 i:iipp prlimit64
|
||||
fanotify_mark EXTRA fanotify_mark i:iiiiis fanotify_mark
|
||||
personality EXTRA personality Ei:i __personality personality
|
||||
|
|
|
@ -20,3 +20,5 @@ waitpid - waitpid Ci:ipi __waitpid waitpid
|
|||
prlimit64 EXTRA prlimit64 i:iipp prlimit64
|
||||
|
||||
fanotify_mark EXTRA fanotify_mark i:iiiiis __fanotify_mark fanotify_mark@@GLIBC_2.16
|
||||
|
||||
personality EXTRA personality Ei:i __personality personality
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
/* Work around sign extension bug in the kernel. */
|
||||
#define PERSONALITY_TRUNCATE_ARGUMENT
|
||||
#include <sysdeps/unix/sysv/linux/personality.c>
|
|
@ -46,7 +46,6 @@ munlockall - munlockall i: munlockall
|
|||
nanosleep - nanosleep Ci:pp __nanosleep nanosleep
|
||||
nfsservctl EXTRA nfsservctl i:ipp nfsservctl
|
||||
pause - pause Ci: __libc_pause pause
|
||||
personality EXTRA personality i:i __personality personality
|
||||
pipe - pipe i:f __pipe pipe
|
||||
pipe2 - pipe2 i:fi __pipe2 pipe2
|
||||
pivot_root EXTRA pivot_root i:ss pivot_root
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
/* BZ #19408 linux personality syscall wrapper test.
|
||||
|
||||
Copyright (C) 2015 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
The GNU C Library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/personality.h>
|
||||
|
||||
static int
|
||||
do_test (void)
|
||||
{
|
||||
int rc = 0;
|
||||
unsigned int test_persona = -EINVAL;
|
||||
unsigned int saved_persona;
|
||||
|
||||
errno = 0xdefaced;
|
||||
saved_persona = personality (0xffffffff);
|
||||
|
||||
if (personality (test_persona) != saved_persona ||
|
||||
personality (0xffffffff) == -1 ||
|
||||
personality (PER_LINUX) == -1 ||
|
||||
personality (0xffffffff) != PER_LINUX ||
|
||||
0xdefaced != errno)
|
||||
rc = 1;
|
||||
|
||||
(void) personality (saved_persona);
|
||||
return rc;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION do_test ()
|
||||
#include "../test-skeleton.c"
|
|
@ -20,3 +20,4 @@ open - open Ci:siv __libc_open __open open __open64 open64
|
|||
prlimit EXTRA prlimit64 i:iipp prlimit prlimit64
|
||||
|
||||
fanotify_mark EXTRA fanotify_mark i:iiiis fanotify_mark
|
||||
personality EXTRA personality i:i __personality personality
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
fallocate - fallocate Ci:iiii fallocate fallocate64
|
||||
gettimeofday - gettimeofday:__vdso_gettimeofday@LINUX_2.6 i:pP __gettimeofday gettimeofday
|
||||
personality EXTRA personality Ei:i __personality personality
|
||||
posix_fadvise - fadvise64 Vi:iiii posix_fadvise posix_fadvise64
|
||||
preadv - preadv Ci:ipii preadv preadv64
|
||||
pwritev - pwritev Ci:ipii pwritev pwritev64
|
||||
|
|
Loading…
Reference in New Issue