xref: /openbmc/linux/arch/um/kernel/exec.c (revision ba180fd4)
11d3468a6SJeff Dike /*
2ba180fd4SJeff Dike  * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
31d3468a6SJeff Dike  * Licensed under the GPL
41d3468a6SJeff Dike  */
51d3468a6SJeff Dike 
6ba180fd4SJeff Dike #include "linux/stddef.h"
7ba180fd4SJeff Dike #include "linux/fs.h"
81d3468a6SJeff Dike #include "linux/smp_lock.h"
91d3468a6SJeff Dike #include "linux/ptrace.h"
10ba180fd4SJeff Dike #include "linux/sched.h"
11ba180fd4SJeff Dike #include "asm/current.h"
12ba180fd4SJeff Dike #include "asm/processor.h"
131d3468a6SJeff Dike #include "asm/uaccess.h"
141d3468a6SJeff Dike #include "mem_user.h"
15ba180fd4SJeff Dike #include "skas.h"
161d3468a6SJeff Dike #include "os.h"
171d3468a6SJeff Dike 
181d3468a6SJeff Dike void flush_thread(void)
191d3468a6SJeff Dike {
2077bf4400SJeff Dike 	void *data = NULL;
2177bf4400SJeff Dike 	unsigned long end = proc_mm ? task_size : CONFIG_STUB_START;
2277bf4400SJeff Dike 	int ret;
2377bf4400SJeff Dike 
241d3468a6SJeff Dike 	arch_flush_thread(&current->thread.arch);
2577bf4400SJeff Dike 
2677bf4400SJeff Dike 	ret = unmap(&current->mm->context.skas.id, 0, end, 1, &data);
2777bf4400SJeff Dike 	if (ret) {
28ba180fd4SJeff Dike 		printk(KERN_ERR "flush_thread - clearing address space failed, "
2977bf4400SJeff Dike 		       "err = %d\n", ret);
3077bf4400SJeff Dike 		force_sig(SIGKILL, current);
3177bf4400SJeff Dike 	}
3277bf4400SJeff Dike 
3377bf4400SJeff Dike 	__switch_mm(&current->mm->context.skas.id);
341d3468a6SJeff Dike }
351d3468a6SJeff Dike 
361d3468a6SJeff Dike void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp)
371d3468a6SJeff Dike {
3877bf4400SJeff Dike 	set_fs(USER_DS);
3977bf4400SJeff Dike 	PT_REGS_IP(regs) = eip;
4077bf4400SJeff Dike 	PT_REGS_SP(regs) = esp;
411d3468a6SJeff Dike }
421d3468a6SJeff Dike 
431d3468a6SJeff Dike #ifdef CONFIG_TTY_LOG
441d3468a6SJeff Dike extern void log_exec(char **argv, void *tty);
451d3468a6SJeff Dike #endif
461d3468a6SJeff Dike 
471d3468a6SJeff Dike static long execve1(char *file, char __user * __user *argv,
481d3468a6SJeff Dike 		    char __user *__user *env)
491d3468a6SJeff Dike {
501d3468a6SJeff Dike 	long error;
51f9795220SJeff Dike #ifdef CONFIG_TTY_LOG
5224ec839cSPeter Zijlstra 	struct tty_struct *tty;
531d3468a6SJeff Dike 
54b1fc0b1fSAlan Cox 	mutex_lock(&tty_mutex);
5524ec839cSPeter Zijlstra 	tty = get_current_tty();
5624ec839cSPeter Zijlstra 	if (tty)
5724ec839cSPeter Zijlstra 		log_exec(argv, tty);
58b1fc0b1fSAlan Cox 	mutex_unlock(&tty_mutex);
591d3468a6SJeff Dike #endif
601d3468a6SJeff Dike 	error = do_execve(file, argv, env, &current->thread.regs);
611d3468a6SJeff Dike 	if (error == 0) {
621d3468a6SJeff Dike 		task_lock(current);
631d3468a6SJeff Dike 		current->ptrace &= ~PT_DTRACE;
641d3468a6SJeff Dike #ifdef SUBARCH_EXECVE1
651d3468a6SJeff Dike 		SUBARCH_EXECVE1(&current->thread.regs.regs);
661d3468a6SJeff Dike #endif
671d3468a6SJeff Dike 		task_unlock(current);
681d3468a6SJeff Dike 	}
69ba180fd4SJeff Dike 	return error;
701d3468a6SJeff Dike }
711d3468a6SJeff Dike 
721d3468a6SJeff Dike long um_execve(char *file, char __user *__user *argv, char __user *__user *env)
731d3468a6SJeff Dike {
741d3468a6SJeff Dike 	long err;
751d3468a6SJeff Dike 
761d3468a6SJeff Dike 	err = execve1(file, argv, env);
771d3468a6SJeff Dike 	if (!err)
781d3468a6SJeff Dike 		do_longjmp(current->thread.exec_buf, 1);
79ba180fd4SJeff Dike 	return err;
801d3468a6SJeff Dike }
811d3468a6SJeff Dike 
821d3468a6SJeff Dike long sys_execve(char __user *file, char __user *__user *argv,
831d3468a6SJeff Dike 		char __user *__user *env)
841d3468a6SJeff Dike {
851d3468a6SJeff Dike 	long error;
861d3468a6SJeff Dike 	char *filename;
871d3468a6SJeff Dike 
881d3468a6SJeff Dike 	lock_kernel();
891d3468a6SJeff Dike 	filename = getname(file);
901d3468a6SJeff Dike 	error = PTR_ERR(filename);
911d3468a6SJeff Dike 	if (IS_ERR(filename)) goto out;
921d3468a6SJeff Dike 	error = execve1(filename, argv, env);
931d3468a6SJeff Dike 	putname(filename);
941d3468a6SJeff Dike  out:
951d3468a6SJeff Dike 	unlock_kernel();
96ba180fd4SJeff Dike 	return error;
971d3468a6SJeff Dike }
98