Commit fe74290d51bc08e9b90ed7c145d74a22cd50b90e

Authored by Arnd Bergmann
Committed by Linus Torvalds
1 parent 3db03b4afb

[PATCH] provide kernel_execve on all architectures

This adds the new kernel_execve function on all architectures that were using
_syscall3() to implement execve.

The implementation uses code from the _syscall3 macros provided in the
unistd.h header file.  I don't have cross-compilers for any of these
architectures, so the patch is untested with the exception of i386.

Most architectures can probably implement this in a nicer way in assembly or
by combining it with the sys_execve implementation itself, but this should do
it for now.

[bunk@stusta.de: m68knommu build fix]
[markh@osdl.org: build fix]
[bero@arklinux.org: build fix]
[ralf@linux-mips.org: mips fix]
[schwidefsky@de.ibm.com: s390 fix]
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Cc: Andi Kleen <ak@muc.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
Cc: Russell King <rmk@arm.linux.org.uk>
Cc: Ian Molton <spyro@f2s.com>
Cc: Mikael Starvik <starvik@axis.com>
Cc: David Howells <dhowells@redhat.com>
Cc: Yoshinori Sato <ysato@users.sourceforge.jp>
Cc: Hirokazu Takata <takata.hirokazu@renesas.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: Kyle McMartin <kyle@mcmartin.ca>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: Paul Mundt <lethal@linux-sh.org>
Cc: Kazumoto Kojima <kkojima@rr.iij4u.or.jp>
Cc: Richard Curnow <rc@rc0.org.uk>
Cc: William Lee Irwin III <wli@holomorphy.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jeff Dike <jdike@addtoit.com>
Cc: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Cc: Miles Bader <uclinux-v850@lsi.nec.co.jp>
Cc: Chris Zankel <chris@zankel.net>
Cc: "Luck, Tony" <tony.luck@intel.com>
Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Roman Zippel <zippel@linux-m68k.org>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Signed-off-by: Bernhard Rosenkraenzer <bero@arklinux.org>
Signed-off-by: Mark Haverkamp <markh@osdl.org>
Signed-off-by: Adrian Bunk <bunk@stusta.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

Showing 16 changed files with 300 additions and 12 deletions Side-by-side Diff

arch/frv/kernel/Makefile
... ... @@ -8,7 +8,7 @@
8 8 extra-y:= head.o init_task.o vmlinux.lds
9 9  
10 10 obj-y := $(heads-y) entry.o entry-table.o break.o switch_to.o kernel_thread.o \
11   - process.o traps.o ptrace.o signal.o dma.o \
  11 + kernel_execve.o process.o traps.o ptrace.o signal.o dma.o \
12 12 sys_frv.o time.o semaphore.o setup.o frv_ksyms.o \
13 13 debug-stub.o irq.o sleep.o uaccess.o
14 14  
arch/frv/kernel/kernel_execve.S
  1 +/* in-kernel program execution
  2 + *
  3 + * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
  4 + * Written by David Howells (dhowells@redhat.com)
  5 + *
  6 + * This program is free software; you can redistribute it and/or
  7 + * modify it under the terms of the GNU General Public License
  8 + * as published by the Free Software Foundation; either version
  9 + * 2 of the License, or (at your option) any later version.
  10 + */
  11 +
  12 +#include <linux/linkage.h>
  13 +#include <asm/unistd.h>
  14 +
  15 +###############################################################################
  16 +#
  17 +# Do a system call from kernel instead of calling sys_execve so we end up with
  18 +# proper pt_regs.
  19 +#
  20 +# int kernel_execve(const char *filename, char *const argv[], char *const envp[])
  21 +#
  22 +# On entry: GR8/GR9/GR10: arguments to function
  23 +# On return: GR8: syscall return.
  24 +#
  25 +###############################################################################
  26 + .globl kernel_execve
  27 + .type kernel_execve,@function
  28 +kernel_execve:
  29 + setlos __NR_execve,gr7
  30 + tira gr0,#0
  31 + bralr
  32 +
  33 + .size kernel_execve,.-kernel_execve
arch/h8300/kernel/sys_h8300.c
... ... @@ -25,6 +25,7 @@
25 25 #include <asm/cachectl.h>
26 26 #include <asm/traps.h>
27 27 #include <asm/ipc.h>
  28 +#include <asm/unistd.h>
28 29  
29 30 /*
30 31 * sys_pipe() is the normal C calling standard for creating
... ... @@ -280,4 +281,25 @@
280 281 ((regs->pc)&0xffffff)-2,regs->orig_er0,regs->er1,regs->er2,regs->er3,regs->er0);
281 282 }
282 283 #endif
  284 +
  285 +/*
  286 + * Do a system call from kernel instead of calling sys_execve so we
  287 + * end up with proper pt_regs.
  288 + */
  289 +int kernel_execve(const char *filename, char *const argv[], char *const envp[])
  290 +{
  291 + register long res __asm__("er0");
  292 + register const char * _a __asm__("er1") = filename;
  293 + register void *_b __asm__("er2") = argv;
  294 + register void *_c __asm__("er3") = envp;
  295 + __asm__ __volatile__ ("mov.l %1,er0\n\t"
  296 + "trapa #0\n\t"
  297 + : "=r" (res)
  298 + : "g" (__NR_execve),
  299 + "g" (_a),
  300 + "g" (_b),
  301 + "g" (_c)
  302 + : "cc", "memory");
  303 + return res;
  304 +}
arch/i386/kernel/sys_i386.c
... ... @@ -21,6 +21,7 @@
21 21 #include <linux/utsname.h>
22 22  
23 23 #include <asm/uaccess.h>
  24 +#include <asm/unistd.h>
24 25 #include <asm/ipc.h>
25 26  
26 27 /*
... ... @@ -247,5 +248,19 @@
247 248 error = error ? -EFAULT : 0;
248 249  
249 250 return error;
  251 +}
  252 +
  253 +
  254 +/*
  255 + * Do a system call from kernel instead of calling sys_execve so we
  256 + * end up with proper pt_regs.
  257 + */
  258 +int kernel_execve(const char *filename, char *const argv[], char *const envp[])
  259 +{
  260 + long __res;
  261 + asm volatile ("push %%ebx ; movl %2,%%ebx ; int $0x80 ; pop %%ebx"
  262 + : "=a" (__res)
  263 + : "0" (__NR_execve),"ri" (filename),"c" (argv), "d" (envp) : "memory");
  264 + return __res;
250 265 }
arch/m32r/kernel/sys_m32r.c
... ... @@ -25,6 +25,8 @@
25 25 #include <asm/cachectl.h>
26 26 #include <asm/cacheflush.h>
27 27 #include <asm/ipc.h>
  28 +#include <asm/syscall.h>
  29 +#include <asm/unistd.h>
28 30  
29 31 /*
30 32 * sys_tas() - test-and-set
... ... @@ -221,5 +223,24 @@
221 223 {
222 224 /* Not implemented yet. */
223 225 return -ENOSYS;
  226 +}
  227 +
  228 +/*
  229 + * Do a system call from kernel instead of calling sys_execve so we
  230 + * end up with proper pt_regs.
  231 + */
  232 +int kernel_execve(const char *filename, char *const argv[], char *const envp[])
  233 +{
  234 + register long __scno __asm__ ("r7") = __NR_execve;
  235 + register long __arg3 __asm__ ("r2") = (long)(envp);
  236 + register long __arg2 __asm__ ("r1") = (long)(argv);
  237 + register long __res __asm__ ("r0") = (long)(filename);
  238 + __asm__ __volatile__ (
  239 + "trap #" SYSCALL_VECTOR "|| nop"
  240 + : "=r" (__res)
  241 + : "r" (__scno), "0" (__res), "r" (__arg2),
  242 + "r" (__arg3)
  243 + : "memory");
  244 + return __res;
224 245 }
arch/m68k/kernel/sys_m68k.c
... ... @@ -27,6 +27,7 @@
27 27 #include <asm/traps.h>
28 28 #include <asm/ipc.h>
29 29 #include <asm/page.h>
  30 +#include <asm/unistd.h>
30 31  
31 32 /*
32 33 * sys_pipe() is the normal C calling standard for creating
... ... @@ -662,5 +663,20 @@
662 663 asmlinkage int sys_getpagesize(void)
663 664 {
664 665 return PAGE_SIZE;
  666 +}
  667 +
  668 +/*
  669 + * Do a system call from kernel instead of calling sys_execve so we
  670 + * end up with proper pt_regs.
  671 + */
  672 +int kernel_execve(const char *filename, char *const argv[], char *const envp[])
  673 +{
  674 + register long __res asm ("%d0") = __NR_execve;
  675 + register long __a asm ("%d1") = (long)(filename);
  676 + register long __b asm ("%d2") = (long)(argv);
  677 + register long __c asm ("%d3") = (long)(envp);
  678 + asm volatile ("trap #0" : "+d" (__res)
  679 + : "d" (__a), "d" (__b), "d" (__c));
  680 + return __res;
665 681 }
arch/m68knommu/kernel/sys_m68k.c
... ... @@ -26,6 +26,7 @@
26 26 #include <asm/traps.h>
27 27 #include <asm/ipc.h>
28 28 #include <asm/cacheflush.h>
  29 +#include <asm/unistd.h>
29 30  
30 31 /*
31 32 * sys_pipe() is the normal C calling standard for creating
... ... @@ -204,5 +205,20 @@
204 205 asmlinkage int sys_getpagesize(void)
205 206 {
206 207 return PAGE_SIZE;
  208 +}
  209 +
  210 +/*
  211 + * Do a system call from kernel instead of calling sys_execve so we
  212 + * end up with proper pt_regs.
  213 + */
  214 +int kernel_execve(const char *filename, char *const argv[], char *const envp[])
  215 +{
  216 + register long __res asm ("%d0") = __NR_execve;
  217 + register long __a asm ("%d1") = (long)(filename);
  218 + register long __b asm ("%d2") = (long)(argv);
  219 + register long __c asm ("%d3") = (long)(envp);
  220 + asm volatile ("trap #0" : "+d" (__res)
  221 + : "d" (__a), "d" (__b), "d" (__c));
  222 + return __res;
207 223 }
arch/mips/kernel/syscall.c
... ... @@ -406,4 +406,33 @@
406 406 {
407 407 do_exit(SIGSEGV);
408 408 }
  409 +
  410 +/*
  411 + * Do a system call from kernel instead of calling sys_execve so we
  412 + * end up with proper pt_regs.
  413 + */
  414 +int kernel_execve(const char *filename, char *const argv[], char *const envp[])
  415 +{
  416 + register unsigned long __a0 asm("$4") = (unsigned long) filename;
  417 + register unsigned long __a1 asm("$5") = (unsigned long) argv;
  418 + register unsigned long __a2 asm("$6") = (unsigned long) envp;
  419 + register unsigned long __a3 asm("$7");
  420 + unsigned long __v0;
  421 +
  422 + __asm__ volatile (" \n"
  423 + " .set noreorder \n"
  424 + " li $2, %5 # __NR_execve \n"
  425 + " syscall \n"
  426 + " move %0, $2 \n"
  427 + " .set reorder \n"
  428 + : "=&r" (__v0), "=r" (__a3)
  429 + : "r" (__a0), "r" (__a1), "r" (__a2), "i" (__NR_execve)
  430 + : "$2", "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", "$24",
  431 + "memory");
  432 +
  433 + if (__a3 == 0)
  434 + return __v0;
  435 +
  436 + return -__v0;
  437 +}
arch/ppc/kernel/misc.S
... ... @@ -942,21 +942,16 @@
942 942 addi r1,r1,16
943 943 blr
944 944  
  945 +_GLOBAL(kernel_execve)
  946 + li r0,__NR_execve
  947 + sc
  948 + bnslr
  949 + neg r3,r3
  950 + blr
  951 +
945 952 /*
946 953 * This routine is just here to keep GCC happy - sigh...
947 954 */
948 955 _GLOBAL(__main)
949 956 blr
950   -
951   -#define SYSCALL(name) \
952   -_GLOBAL(name) \
953   - li r0,__NR_##name; \
954   - sc; \
955   - bnslr; \
956   - lis r4,errno@ha; \
957   - stw r3,errno@l(r4); \
958   - li r3,-1; \
959   - blr
960   -
961   -SYSCALL(execve)
arch/s390/kernel/sys_s390.c
... ... @@ -27,6 +27,7 @@
27 27 #include <linux/file.h>
28 28 #include <linux/utsname.h>
29 29 #include <linux/personality.h>
  30 +#include <linux/unistd.h>
30 31  
31 32 #include <asm/uaccess.h>
32 33 #include <asm/ipc.h>
... ... @@ -264,5 +265,25 @@
264 265 if ( copy_from_user(&a, args, sizeof(a)) )
265 266 return -EFAULT;
266 267 return sys_fadvise64_64(a.fd, a.offset, a.len, a.advice);
  268 +}
  269 +
  270 +/*
  271 + * Do a system call from kernel instead of calling sys_execve so we
  272 + * end up with proper pt_regs.
  273 + */
  274 +int kernel_execve(const char *filename, char *const argv[], char *const envp[])
  275 +{
  276 + register const char *__arg1 asm("2") = filename;
  277 + register char *const*__arg2 asm("3") = argv;
  278 + register char *const*__arg3 asm("4") = envp;
  279 + register long __svcres asm("2");
  280 + asm volatile(
  281 + "svc %b1"
  282 + : "=d" (__svcres)
  283 + : "i" (__NR_execve),
  284 + "0" (__arg1),
  285 + "d" (__arg2),
  286 + "d" (__arg3) : "memory");
  287 + return __svcres;
267 288 }
arch/sh/kernel/sys_sh.c
... ... @@ -25,6 +25,7 @@
25 25 #include <asm/cacheflush.h>
26 26 #include <asm/uaccess.h>
27 27 #include <asm/ipc.h>
  28 +#include <asm/unistd.h>
28 29  
29 30 /*
30 31 * sys_pipe() is the normal C calling standard for creating
... ... @@ -308,5 +309,21 @@
308 309 return sys_fadvise64_64(fd, (u64)offset0 << 32 | offset1,
309 310 (u64)len0 << 32 | len1, advice);
310 311 #endif
  312 +}
  313 +
  314 +/*
  315 + * Do a system call from kernel instead of calling sys_execve so we
  316 + * end up with proper pt_regs.
  317 + */
  318 +int kernel_execve(const char *filename, char *const argv[], char *const envp[])
  319 +{
  320 + register long __sc0 __asm__ ("r3") = __NR_execve;
  321 + register long __sc4 __asm__ ("r4") = (long) filename;
  322 + register long __sc5 __asm__ ("r5") = (long) argv;
  323 + register long __sc6 __asm__ ("r6") = (long) envp;
  324 + __asm__ __volatile__ ("trapa #0x13" : "=z" (__sc0)
  325 + : "0" (__sc0), "r" (__sc4), "r" (__sc5), "r" (__sc6)
  326 + : "memory");
  327 + return __sc0;
311 328 }
arch/sh64/kernel/sys_sh64.c
... ... @@ -32,6 +32,7 @@
32 32 #include <asm/uaccess.h>
33 33 #include <asm/ipc.h>
34 34 #include <asm/ptrace.h>
  35 +#include <asm/unistd.h>
35 36  
36 37 #define REG_3 3
37 38  
... ... @@ -282,5 +283,23 @@
282 283 err = copy_to_user(name, utsname(), sizeof (*name));
283 284 up_read(&uts_sem);
284 285 return err?-EFAULT:0;
  286 +}
  287 +
  288 +/*
  289 + * Do a system call from kernel instead of calling sys_execve so we
  290 + * end up with proper pt_regs.
  291 + */
  292 +int kernel_execve(const char *filename, char *const argv[], char *const envp[])
  293 +{
  294 + register unsigned long __sc0 __asm__ ("r9") = ((0x13 << 16) | __NR_execve);
  295 + register unsigned long __sc2 __asm__ ("r2") = (unsigned long) filename;
  296 + register unsigned long __sc3 __asm__ ("r3") = (unsigned long) argv;
  297 + register unsigned long __sc4 __asm__ ("r4") = (unsigned long) envp;
  298 + __asm__ __volatile__ ("trapa %1 !\t\t\t execve(%2,%3,%4)"
  299 + : "=r" (__sc0)
  300 + : "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4) );
  301 + __asm__ __volatile__ ("!dummy %0 %1 %2 %3"
  302 + : : "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4) : "memory");
  303 + return __sc0;
285 304 }
arch/sparc/kernel/sys_sparc.c
... ... @@ -24,6 +24,7 @@
24 24  
25 25 #include <asm/uaccess.h>
26 26 #include <asm/ipc.h>
  27 +#include <asm/unistd.h>
27 28  
28 29 /* #define DEBUG_UNIMP_SYSCALL */
29 30  
... ... @@ -487,5 +488,27 @@
487 488 out:
488 489 up_read(&uts_sem);
489 490 return err;
  491 +}
  492 +
  493 +/*
  494 + * Do a system call from kernel instead of calling sys_execve so we
  495 + * end up with proper pt_regs.
  496 + */
  497 +int kernel_execve(const char *filename, char *const argv[], char *const envp[])
  498 +{
  499 + long __res;
  500 + register long __g1 __asm__ ("g1") = __NR_execve;
  501 + register long __o0 __asm__ ("o0") = (long)(filename);
  502 + register long __o1 __asm__ ("o1") = (long)(argv);
  503 + register long __o2 __asm__ ("o2") = (long)(envp);
  504 + asm volatile ("t 0x10\n\t"
  505 + "bcc 1f\n\t"
  506 + "mov %%o0, %0\n\t"
  507 + "sub %%g0, %%o0, %0\n\t"
  508 + "1:\n\t"
  509 + : "=r" (__res), "=&r" (__o0)
  510 + : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__g1)
  511 + : "cc");
  512 + return __res;
490 513 }
arch/sparc64/kernel/sys_sparc.c
... ... @@ -31,6 +31,7 @@
31 31 #include <asm/utrap.h>
32 32 #include <asm/perfctr.h>
33 33 #include <asm/a.out.h>
  34 +#include <asm/unistd.h>
34 35  
35 36 /* #define DEBUG_UNIMP_SYSCALL */
36 37  
... ... @@ -962,5 +963,25 @@
962 963 break;
963 964 };
964 965 return err;
  966 +}
  967 +
  968 +/*
  969 + * Do a system call from kernel instead of calling sys_execve so we
  970 + * end up with proper pt_regs.
  971 + */
  972 +int kernel_execve(const char *filename, char *const argv[], char *const envp[])
  973 +{
  974 + long __res;
  975 + register long __g1 __asm__ ("g1") = __NR_execve;
  976 + register long __o0 __asm__ ("o0") = (long)(filename);
  977 + register long __o1 __asm__ ("o1") = (long)(argv);
  978 + register long __o2 __asm__ ("o2") = (long)(envp);
  979 + asm volatile ("t 0x6d\n\t"
  980 + "sub %%g0, %%o0, %0\n\t"
  981 + "movcc %%xcc, %%o0, %0\n\t"
  982 + : "=r" (__res), "=&r" (__o0)
  983 + : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__g1)
  984 + : "cc");
  985 + return __res;
965 986 }
arch/v850/kernel/syscalls.c
... ... @@ -33,6 +33,7 @@
33 33 #include <asm/uaccess.h>
34 34 #include <asm/ipc.h>
35 35 #include <asm/semaphore.h>
  36 +#include <asm/unistd.h>
36 37  
37 38 /*
38 39 * sys_ipc() is the de-multiplexer for the SysV IPC calls..
... ... @@ -193,5 +194,24 @@
193 194 err = do_mmap2 (addr, len, prot, flags, fd, offset >> PAGE_SHIFT);
194 195 out:
195 196 return err;
  197 +}
  198 +
  199 +/*
  200 + * Do a system call from kernel instead of calling sys_execve so we
  201 + * end up with proper pt_regs.
  202 + */
  203 +int kernel_execve(const char *filename, char *const argv[], char *const envp[])
  204 +{
  205 + register char *__a __asm__ ("r6") = filename;
  206 + register void *__b __asm__ ("r7") = argv;
  207 + register void *__c __asm__ ("r8") = envp;
  208 + register unsigned long __syscall __asm__ ("r12") = __NR_execve;
  209 + register unsigned long __ret __asm__ ("r10");
  210 + __asm__ __volatile__ ("trap 0"
  211 + : "=r" (__ret), "=r" (__syscall)
  212 + : "1" (__syscall), "r" (__a), "r" (__b), "r" (__c)
  213 + : "r1", "r5", "r11", "r13", "r14",
  214 + "r15", "r16", "r17", "r18", "r19");
  215 + return __ret;
196 216 }
arch/xtensa/kernel/syscalls.c
... ... @@ -266,4 +266,24 @@
266 266 regs->areg[2] = res;
267 267 do_syscall_trace();
268 268 }
  269 +
  270 +/*
  271 + * Do a system call from kernel instead of calling sys_execve so we
  272 + * end up with proper pt_regs.
  273 + */
  274 +int kernel_execve(const char *filename, char *const argv[], char *const envp[])
  275 +{
  276 + long __res;
  277 + asm volatile (
  278 + " mov a5, %2 \n"
  279 + " mov a4, %4 \n"
  280 + " mov a3, %3 \n"
  281 + " movi a2, %1 \n"
  282 + " syscall \n"
  283 + " mov %0, a2 \n"
  284 + : "=a" (__res)
  285 + : "i" (__NR_execve), "a" (filename), "a" (argv), "a" (envp)
  286 + : "a2", "a3", "a4", "a5");
  287 + return __res;
  288 +}