* 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/slab.h>
flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
/*
- * If we are doing a fixed mapping, and address < PAGE_SIZE,
+ * If we are doing a fixed mapping, and address < FIRST_USER_ADDRESS,
* then deny it.
*/
- if (flags & MAP_FIXED && addr < PAGE_SIZE && vectors_base() == 0)
+ if (flags & MAP_FIXED && addr < FIRST_USER_ADDRESS)
goto out;
error = -EBADF;
unsigned long ret = -EINVAL;
/*
- * If we are doing a fixed mapping, and address < PAGE_SIZE,
+ * If we are doing a fixed mapping, and address < FIRST_USER_ADDRESS,
* then deny it.
*/
- if (flags & MREMAP_FIXED && new_addr < PAGE_SIZE &&
- vectors_base() == 0)
+ if (flags & MREMAP_FIXED && new_addr < FIRST_USER_ADDRESS)
goto out;
down_write(¤t->mm->mmap_sem);
if (!newsp)
newsp = regs->ARM_sp;
- return do_fork(clone_flags & ~CLONE_IDLETASK, newsp, regs, 0, NULL, NULL);
+ return do_fork(clone_flags, newsp, regs, 0, NULL, NULL);
}
asmlinkage int sys_vfork(struct pt_regs *regs)
out:
return error;
}
+
+/* FIXME - see if this is correct for arm26 */
+int kernel_execve(const char *filename, char *const argv[], char *const envp[])
+{
+ struct pt_regs regs;
+ int ret;
+ memset(®s, 0, sizeof(struct pt_regs));
+ ret = do_execve((char *)filename, (char __user * __user *)argv, (char __user * __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_SIZE - 8 - sizeof(regs)),
+ "r" (®s),
+ "Ir" (sizeof(regs))
+ : "r0", "r1", "r2", "r3", "ip", "memory");
+
+ out:
+ return ret;
+}
+
+EXPORT_SYMBOL(kernel_execve);