2019-05-19 15:08:20 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2005-04-17 02:20:36 +04:00
/*
* linux / fs / binfmt_em86 . c
*
* Based on linux / fs / binfmt_script . c
2007-10-20 01:21:04 +04:00
* Copyright ( C ) 1996 Martin von Löwis
2005-04-17 02:20:36 +04:00
* original # ! - checking implemented by tytso .
*
* em86 changes Copyright ( C ) 1997 Jim Paradis
*/
# include <linux/module.h>
# include <linux/string.h>
# include <linux/stat.h>
# include <linux/binfmts.h>
# include <linux/elf.h>
# include <linux/init.h>
# include <linux/fs.h>
# include <linux/file.h>
# include <linux/errno.h>
# define EM86_INTERP " / usr / bin / em86"
# define EM86_I_NAME "em86"
2012-10-21 06:00:48 +04:00
static int load_em86 ( struct linux_binprm * bprm )
2005-04-17 02:20:36 +04:00
{
2016-08-03 00:04:57 +03:00
const char * i_name , * i_arg ;
char * interp ;
2005-04-17 02:20:36 +04:00
struct file * file ;
int retval ;
struct elfhdr elf_ex ;
/* Make sure this is a Linux/Intel ELF executable... */
elf_ex = * ( ( struct elfhdr * ) bprm - > buf ) ;
if ( memcmp ( elf_ex . e_ident , ELFMAG , SELFMAG ) ! = 0 )
return - ENOEXEC ;
/* First of all, some simple consistency checks */
if ( ( elf_ex . e_type ! = ET_EXEC & & elf_ex . e_type ! = ET_DYN ) | |
( ! ( ( elf_ex . e_machine = = EM_386 ) | | ( elf_ex . e_machine = = EM_486 ) ) ) | |
2013-09-23 00:27:52 +04:00
! bprm - > file - > f_op - > mmap ) {
2005-04-17 02:20:36 +04:00
return - ENOEXEC ;
}
syscalls: implement execveat() system call
This patchset adds execveat(2) for x86, and is derived from Meredydd
Luff's patch from Sept 2012 (https://lkml.org/lkml/2012/9/11/528).
The primary aim of adding an execveat syscall is to allow an
implementation of fexecve(3) that does not rely on the /proc filesystem,
at least for executables (rather than scripts). The current glibc version
of fexecve(3) is implemented via /proc, which causes problems in sandboxed
or otherwise restricted environments.
Given the desire for a /proc-free fexecve() implementation, HPA suggested
(https://lkml.org/lkml/2006/7/11/556) that an execveat(2) syscall would be
an appropriate generalization.
Also, having a new syscall means that it can take a flags argument without
back-compatibility concerns. The current implementation just defines the
AT_EMPTY_PATH and AT_SYMLINK_NOFOLLOW flags, but other flags could be
added in future -- for example, flags for new namespaces (as suggested at
https://lkml.org/lkml/2006/7/11/474).
Related history:
- https://lkml.org/lkml/2006/12/27/123 is an example of someone
realizing that fexecve() is likely to fail in a chroot environment.
- http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=514043 covered
documenting the /proc requirement of fexecve(3) in its manpage, to
"prevent other people from wasting their time".
- https://bugzilla.redhat.com/show_bug.cgi?id=241609 described a
problem where a process that did setuid() could not fexecve()
because it no longer had access to /proc/self/fd; this has since
been fixed.
This patch (of 4):
Add a new execveat(2) system call. execveat() is to execve() as openat()
is to open(): it takes a file descriptor that refers to a directory, and
resolves the filename relative to that.
In addition, if the filename is empty and AT_EMPTY_PATH is specified,
execveat() executes the file to which the file descriptor refers. This
replicates the functionality of fexecve(), which is a system call in other
UNIXen, but in Linux glibc it depends on opening "/proc/self/fd/<fd>" (and
so relies on /proc being mounted).
The filename fed to the executed program as argv[0] (or the name of the
script fed to a script interpreter) will be of the form "/dev/fd/<fd>"
(for an empty filename) or "/dev/fd/<fd>/<filename>", effectively
reflecting how the executable was found. This does however mean that
execution of a script in a /proc-less environment won't work; also, script
execution via an O_CLOEXEC file descriptor fails (as the file will not be
accessible after exec).
Based on patches by Meredydd Luff.
Signed-off-by: David Drysdale <drysdale@google.com>
Cc: Meredydd Luff <meredydd@senatehouse.org>
Cc: Shuah Khan <shuah.kh@samsung.com>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Rich Felker <dalias@aerifal.cx>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Michael Kerrisk <mtk.manpages@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2014-12-13 03:57:29 +03:00
/* Need to be able to load the file after exec */
if ( bprm - > interp_flags & BINPRM_FLAGS_PATH_INACCESSIBLE )
return - ENOENT ;
2005-04-17 02:20:36 +04:00
/* Unlike in the script case, we don't have to do any hairy
* parsing to find our interpreter . . . it ' s hardcoded !
*/
interp = EM86_INTERP ;
i_name = EM86_I_NAME ;
i_arg = NULL ; /* We reserve the right to add an arg later */
/*
* Splice in ( 1 ) the interpreter ' s name for argv [ 0 ]
* ( 2 ) ( optional ) argument to interpreter
* ( 3 ) filename of emulated file ( replace argv [ 0 ] )
*
* This is done in reverse order , because of how the
* user environment and arguments are stored .
*/
remove_arg_zero ( bprm ) ;
2020-06-05 02:51:14 +03:00
retval = copy_string_kernel ( bprm - > filename , bprm ) ;
2005-04-17 02:20:36 +04:00
if ( retval < 0 ) return retval ;
bprm - > argc + + ;
if ( i_arg ) {
2020-06-05 02:51:14 +03:00
retval = copy_string_kernel ( i_arg , bprm ) ;
2005-04-17 02:20:36 +04:00
if ( retval < 0 ) return retval ;
bprm - > argc + + ;
}
2020-06-05 02:51:14 +03:00
retval = copy_string_kernel ( i_name , bprm ) ;
2005-04-17 02:20:36 +04:00
if ( retval < 0 ) return retval ;
bprm - > argc + + ;
/*
* OK , now restart the process with the interpreter ' s inode .
* Note that we use open_exec ( ) as the name is now in kernel
* space , and we don ' t need to copy it .
*/
file = open_exec ( interp ) ;
if ( IS_ERR ( file ) )
return PTR_ERR ( file ) ;
2020-05-19 02:43:20 +03:00
bprm - > interpreter = file ;
return 0 ;
2005-04-17 02:20:36 +04:00
}
static struct linux_binfmt em86_format = {
. module = THIS_MODULE ,
. load_binary = load_em86 ,
} ;
static int __init init_em86_binfmt ( void )
{
2012-03-17 11:05:16 +04:00
register_binfmt ( & em86_format ) ;
return 0 ;
2005-04-17 02:20:36 +04:00
}
static void __exit exit_em86_binfmt ( void )
{
unregister_binfmt ( & em86_format ) ;
}
core_initcall ( init_em86_binfmt ) ;
module_exit ( exit_em86_binfmt ) ;
MODULE_LICENSE ( " GPL " ) ;