Bug 19408 - linux personality syscall wrapper may erroneously return an error on 32-bit architectures
Summary: linux personality syscall wrapper may erroneously return an error on 32-bit a...
Status: RESOLVED FIXED
Alias: None
Product: glibc
Classification: Unclassified
Component: libc (show other bugs)
Version: unspecified
: P2 normal
Target Milestone: 2.23
Assignee: Dmitry V. Levin
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-12-28 01:02 UTC by Dmitry V. Levin
Modified: 2019-04-10 15:23 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:
fweimer: security-


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Dmitry V. Levin 2015-12-28 01:02:08 UTC
While personality syscall is always successful on 32-bit architectures nowadays, the syscall wrapper may return an error.
For example, personality((unsigned) -EINVAL) will make any subsequent personality call, including absolutely harmless read-only personality(0xffffffff) call, return -1 with errno set to EINVAL.
Comment 1 Sourceware Commits 2015-12-31 00:27:16 UTC
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU C Library master sources".

The branch, master has been updated
       via  e0043e17dfc52fe1702746543127cb4a87232bcd (commit)
      from  cc42170ef6ca931c7527a86f14fc66059b6dfff4 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=e0043e17dfc52fe1702746543127cb4a87232bcd

commit e0043e17dfc52fe1702746543127cb4a87232bcd
Author: Dmitry V. Levin <ldv@altlinux.org>
Date:   Sun Dec 27 16:30:02 2015 +0000

    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.

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog                                          |   25 ++++++++++
 sysdeps/unix/sysv/linux/Makefile                   |    5 +-
 sysdeps/unix/sysv/linux/arm/syscalls.list          |    2 +
 sysdeps/unix/sysv/linux/hppa/syscalls.list         |    1 +
 sysdeps/unix/sysv/linux/i386/syscalls.list         |    2 +
 sysdeps/unix/sysv/linux/m68k/syscalls.list         |    1 +
 sysdeps/unix/sysv/linux/microblaze/syscalls.list   |    1 +
 .../unix/sysv/linux/mips/mips64/n32/syscalls.list  |    2 +
 sysdeps/unix/sysv/linux/personality.c              |   49 ++++++++++++++++++++
 sysdeps/unix/sysv/linux/s390/s390-32/syscalls.list |    1 +
 sysdeps/unix/sysv/linux/sh/syscalls.list           |    2 +
 .../unix/sysv/linux/sparc/sparc64/personality.c    |    3 +
 sysdeps/unix/sysv/linux/syscalls.list              |    1 -
 sysdeps/unix/sysv/linux/tst-personality.c          |   45 ++++++++++++++++++
 sysdeps/unix/sysv/linux/wordsize-64/syscalls.list  |    1 +
 sysdeps/unix/sysv/linux/x86_64/x32/syscalls.list   |    1 +
 16 files changed, 139 insertions(+), 3 deletions(-)
 create mode 100644 sysdeps/unix/sysv/linux/personality.c
 create mode 100644 sysdeps/unix/sysv/linux/sparc/sparc64/personality.c
 create mode 100644 sysdeps/unix/sysv/linux/tst-personality.c
Comment 2 Dmitry V. Levin 2015-12-31 00:33:31 UTC
Fixed in master.