mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-19 02:04:19 +08:00
d7627467b7
Make do_execve() take a const filename pointer so that kernel_execve() compiles correctly on ARM: arch/arm/kernel/sys_arm.c:88: warning: passing argument 1 of 'do_execve' discards qualifiers from pointer target type This also requires the argv and envp arguments to be consted twice, once for the pointer array and once for the strings the array points to. This is because do_execve() passes a pointer to the filename (now const) to copy_strings_kernel(). A simpler alternative would be to cast the filename pointer in do_execve() when it's passed to copy_strings_kernel(). do_execve() may not change any of the strings it is passed as part of the argv or envp lists as they are some of them in .rodata, so marking these strings as const should be fine. Further kernel_execve() and sys_execve() need to be changed to match. This has been test built on x86_64, frv, arm and mips. Signed-off-by: David Howells <dhowells@redhat.com> Tested-by: Ralf Baechle <ralf@linux-mips.org> Acked-by: Russell King <rmk+kernel@arm.linux.org.uk> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
134 lines
3.4 KiB
C
134 lines
3.4 KiB
C
/*
|
|
* linux/arch/arm/kernel/sys_arm.c
|
|
*
|
|
* Copyright (C) People who wrote linux/arch/i386/kernel/sys_i386.c
|
|
* Copyright (C) 1995, 1996 Russell King.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This file contains various random system calls that
|
|
* have a non-standard calling sequence on the Linux/arm
|
|
* platform.
|
|
*/
|
|
#include <linux/module.h>
|
|
#include <linux/errno.h>
|
|
#include <linux/sched.h>
|
|
#include <linux/mm.h>
|
|
#include <linux/sem.h>
|
|
#include <linux/msg.h>
|
|
#include <linux/shm.h>
|
|
#include <linux/stat.h>
|
|
#include <linux/syscalls.h>
|
|
#include <linux/mman.h>
|
|
#include <linux/fs.h>
|
|
#include <linux/file.h>
|
|
#include <linux/ipc.h>
|
|
#include <linux/uaccess.h>
|
|
#include <linux/slab.h>
|
|
|
|
/* Fork a new task - this creates a new program thread.
|
|
* This is called indirectly via a small wrapper
|
|
*/
|
|
asmlinkage int sys_fork(struct pt_regs *regs)
|
|
{
|
|
#ifdef CONFIG_MMU
|
|
return do_fork(SIGCHLD, regs->ARM_sp, regs, 0, NULL, NULL);
|
|
#else
|
|
/* can not support in nommu mode */
|
|
return(-EINVAL);
|
|
#endif
|
|
}
|
|
|
|
/* Clone a task - this clones the calling program thread.
|
|
* This is called indirectly via a small wrapper
|
|
*/
|
|
asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
|
|
int __user *parent_tidptr, int tls_val,
|
|
int __user *child_tidptr, struct pt_regs *regs)
|
|
{
|
|
if (!newsp)
|
|
newsp = regs->ARM_sp;
|
|
|
|
return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr);
|
|
}
|
|
|
|
asmlinkage int sys_vfork(struct pt_regs *regs)
|
|
{
|
|
return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->ARM_sp, regs, 0, NULL, NULL);
|
|
}
|
|
|
|
/* sys_execve() executes a new program.
|
|
* This is called indirectly via a small wrapper
|
|
*/
|
|
asmlinkage int sys_execve(const char __user *filenamei,
|
|
const char __user *const __user *argv,
|
|
const char __user *const __user *envp, struct pt_regs *regs)
|
|
{
|
|
int error;
|
|
char * filename;
|
|
|
|
filename = getname(filenamei);
|
|
error = PTR_ERR(filename);
|
|
if (IS_ERR(filename))
|
|
goto out;
|
|
error = do_execve(filename, argv, envp, regs);
|
|
putname(filename);
|
|
out:
|
|
return error;
|
|
}
|
|
|
|
int kernel_execve(const char *filename,
|
|
const char *const argv[],
|
|
const char *const envp[])
|
|
{
|
|
struct pt_regs regs;
|
|
int ret;
|
|
|
|
memset(®s, 0, sizeof(struct pt_regs));
|
|
ret = do_execve(filename,
|
|
(const char __user *const __user *)argv,
|
|
(const char __user *const __user *)envp, ®s);
|
|
if (ret < 0)
|
|
goto out;
|
|
|
|
/*
|
|
* Save argc to the register structure for userspace.
|
|
*/
|
|
regs.ARM_r0 = ret;
|
|
|
|
/*
|
|
* We were successful. We won't be returning to our caller, but
|
|
* instead to user space by manipulating the kernel stack.
|
|
*/
|
|
asm( "add r0, %0, %1\n\t"
|
|
"mov r1, %2\n\t"
|
|
"mov r2, %3\n\t"
|
|
"bl memmove\n\t" /* copy regs to top of stack */
|
|
"mov r8, #0\n\t" /* not a syscall */
|
|
"mov r9, %0\n\t" /* thread structure */
|
|
"mov sp, r0\n\t" /* reposition stack pointer */
|
|
"b ret_to_user"
|
|
:
|
|
: "r" (current_thread_info()),
|
|
"Ir" (THREAD_START_SP - sizeof(regs)),
|
|
"r" (®s),
|
|
"Ir" (sizeof(regs))
|
|
: "r0", "r1", "r2", "r3", "ip", "lr", "memory");
|
|
|
|
out:
|
|
return ret;
|
|
}
|
|
EXPORT_SYMBOL(kernel_execve);
|
|
|
|
/*
|
|
* Since loff_t is a 64 bit type we avoid a lot of ABI hassle
|
|
* with a different argument ordering.
|
|
*/
|
|
asmlinkage long sys_arm_fadvise64_64(int fd, int advice,
|
|
loff_t offset, loff_t len)
|
|
{
|
|
return sys_fadvise64_64(fd, offset, len, advice);
|
|
}
|