aboutsummaryrefslogtreecommitdiff
path: root/arch/um/os-Linux
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um/os-Linux')
-rw-r--r--arch/um/os-Linux/drivers/ethertap_user.c2
-rw-r--r--arch/um/os-Linux/helper.c10
-rw-r--r--arch/um/os-Linux/mem.c141
-rw-r--r--arch/um/os-Linux/process.c8
-rw-r--r--arch/um/os-Linux/sigio.c2
-rw-r--r--arch/um/os-Linux/skas/mem.c4
-rw-r--r--arch/um/os-Linux/skas/process.c40
-rw-r--r--arch/um/os-Linux/start_up.c24
-rw-r--r--arch/um/os-Linux/sys-i386/tls.c1
-rw-r--r--arch/um/os-Linux/trap.c4
-rw-r--r--arch/um/os-Linux/uaccess.c4
-rw-r--r--arch/um/os-Linux/umid.c15
-rw-r--r--arch/um/os-Linux/user_syms.c9
-rw-r--r--arch/um/os-Linux/util.c2
14 files changed, 187 insertions, 79 deletions
diff --git a/arch/um/os-Linux/drivers/ethertap_user.c b/arch/um/os-Linux/drivers/ethertap_user.c
index 901b85e8a1c..8f49507e64e 100644
--- a/arch/um/os-Linux/drivers/ethertap_user.c
+++ b/arch/um/os-Linux/drivers/ethertap_user.c
@@ -40,7 +40,7 @@ static void etap_change(int op, unsigned char *addr, unsigned char *netmask,
int fd)
{
struct addr_change change;
- void *output;
+ char *output;
int n;
change.what = op;
diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c
index 6490a4ff40a..6987d1d247a 100644
--- a/arch/um/os-Linux/helper.c
+++ b/arch/um/os-Linux/helper.c
@@ -43,7 +43,7 @@ static int helper_child(void *arg)
(*data->pre_exec)(data->pre_data);
execvp(argv[0], argv);
errval = errno;
- printk("execvp of '%s' failed - errno = %d\n", argv[0], errno);
+ printk("helper_child - execve of '%s' failed - errno = %d\n", argv[0], errno);
os_write_file(data->fd, &errval, sizeof(errval));
kill(os_getpid(), SIGKILL);
return(0);
@@ -92,15 +92,15 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv,
close(fds[1]);
fds[1] = -1;
- /*Read the errno value from the child.*/
+ /* Read the errno value from the child, if the exec failed, or get 0 if
+ * the exec succeeded because the pipe fd was set as close-on-exec. */
n = os_read_file(fds[0], &ret, sizeof(ret));
- if(n < 0){
+ if (n < 0) {
printk("run_helper : read on pipe failed, ret = %d\n", -n);
ret = n;
kill(pid, SIGKILL);
CATCH_EINTR(waitpid(pid, NULL, 0));
- }
- else if(n != 0){
+ } else if(n != 0){
CATCH_EINTR(n = waitpid(pid, NULL, 0));
ret = -errno;
} else {
diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c
index 6ab372da965..c6432e72924 100644
--- a/arch/um/os-Linux/mem.c
+++ b/arch/um/os-Linux/mem.c
@@ -8,6 +8,7 @@
#include <fcntl.h>
#include <sys/types.h>
#include <sys/mman.h>
+#include <sys/statfs.h>
#include "kern_util.h"
#include "user.h"
#include "user_util.h"
@@ -19,6 +20,7 @@
#include <sys/param.h>
+static char *default_tmpdir = "/tmp";
static char *tempdir = NULL;
static void __init find_tempdir(void)
@@ -34,7 +36,7 @@ static void __init find_tempdir(void)
break;
}
if((dir == NULL) || (*dir == '\0'))
- dir = "/tmp";
+ dir = default_tmpdir;
tempdir = malloc(strlen(dir) + 2);
if(tempdir == NULL){
@@ -46,6 +48,96 @@ static void __init find_tempdir(void)
strcat(tempdir, "/");
}
+/* This will return 1, with the first character in buf being the
+ * character following the next instance of c in the file. This will
+ * read the file as needed. If there's an error, -errno is returned;
+ * if the end of the file is reached, 0 is returned.
+ */
+static int next(int fd, char *buf, int size, char c)
+{
+ int n;
+ char *ptr;
+
+ while((ptr = strchr(buf, c)) == NULL){
+ n = read(fd, buf, size - 1);
+ if(n == 0)
+ return 0;
+ else if(n < 0)
+ return -errno;
+
+ buf[n] = '\0';
+ }
+
+ ptr++;
+ memmove(buf, ptr, strlen(ptr) + 1);
+ return 1;
+}
+
+static int checked_tmpdir = 0;
+
+/* Look for a tmpfs mounted at /dev/shm. I couldn't find a cleaner
+ * way to do this than to parse /proc/mounts. statfs will return the
+ * same filesystem magic number and fs id for both /dev and /dev/shm
+ * when they are both tmpfs, so you can't tell if they are different
+ * filesystems. Also, there seems to be no other way of finding the
+ * mount point of a filesystem from within it.
+ *
+ * If a /dev/shm tmpfs entry is found, then we switch to using it.
+ * Otherwise, we stay with the default /tmp.
+ */
+static void which_tmpdir(void)
+{
+ int fd, found;
+ char buf[128] = { '\0' };
+
+ if(checked_tmpdir)
+ return;
+
+ checked_tmpdir = 1;
+
+ printf("Checking for tmpfs mount on /dev/shm...");
+
+ fd = open("/proc/mounts", O_RDONLY);
+ if(fd < 0){
+ printf("failed to open /proc/mounts, errno = %d\n", errno);
+ return;
+ }
+
+ while(1){
+ found = next(fd, buf, sizeof(buf) / sizeof(buf[0]), ' ');
+ if(found != 1)
+ break;
+
+ if(!strncmp(buf, "/dev/shm", strlen("/dev/shm")))
+ goto found;
+
+ found = next(fd, buf, sizeof(buf) / sizeof(buf[0]), '\n');
+ if(found != 1)
+ break;
+ }
+
+err:
+ if(found == 0)
+ printf("nothing mounted on /dev/shm\n");
+ else if(found < 0)
+ printf("read returned errno %d\n", -found);
+
+ return;
+
+found:
+ found = next(fd, buf, sizeof(buf) / sizeof(buf[0]), ' ');
+ if(found != 1)
+ goto err;
+
+ if(strncmp(buf, "tmpfs", strlen("tmpfs"))){
+ printf("not tmpfs\n");
+ return;
+ }
+
+ printf("OK\n");
+ default_tmpdir = "/dev/shm";
+}
+
/*
* This proc still used in tt-mode
* (file: kernel/tt/ptproxy/proxy.c, proc: start_debugger).
@@ -53,33 +145,37 @@ static void __init find_tempdir(void)
*/
int make_tempfile(const char *template, char **out_tempname, int do_unlink)
{
- char tempname[MAXPATHLEN];
+ char *tempname;
int fd;
+ which_tmpdir();
+ tempname = malloc(MAXPATHLEN);
+
find_tempdir();
- if (*template != '/')
+ if (template[0] != '/')
strcpy(tempname, tempdir);
else
- *tempname = 0;
+ tempname[0] = '\0';
strcat(tempname, template);
fd = mkstemp(tempname);
if(fd < 0){
fprintf(stderr, "open - cannot create %s: %s\n", tempname,
strerror(errno));
- return -1;
+ goto out;
}
if(do_unlink && (unlink(tempname) < 0)){
perror("unlink");
- return -1;
+ goto out;
}
if(out_tempname){
- *out_tempname = strdup(tempname);
- if(*out_tempname == NULL){
- perror("strdup");
- return -1;
- }
+ *out_tempname = tempname;
+ } else {
+ free(tempname);
}
return(fd);
+out:
+ free(tempname);
+ return -1;
}
#define TEMPNAME_TEMPLATE "vm_file-XXXXXX"
@@ -134,3 +230,26 @@ int create_mem_file(unsigned long long len)
}
return(fd);
}
+
+
+void check_tmpexec(void)
+{
+ void *addr;
+ int err, fd = create_tmp_file(UM_KERN_PAGE_SIZE);
+
+ addr = mmap(NULL, UM_KERN_PAGE_SIZE,
+ PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0);
+ printf("Checking PROT_EXEC mmap in %s...",tempdir);
+ fflush(stdout);
+ if(addr == MAP_FAILED){
+ err = errno;
+ perror("failed");
+ if(err == EPERM)
+ printf("%s must be not mounted noexec\n",tempdir);
+ exit(1);
+ }
+ printf("OK\n");
+ munmap(addr, UM_KERN_PAGE_SIZE);
+
+ close(fd);
+}
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c
index 8176b0b5204..3505f44f8a2 100644
--- a/arch/um/os-Linux/process.c
+++ b/arch/um/os-Linux/process.c
@@ -190,7 +190,7 @@ int os_unmap_memory(void *addr, int len)
}
#ifndef MADV_REMOVE
-#define MADV_REMOVE 0x5 /* remove these pages & resources */
+#define MADV_REMOVE KERNEL_MADV_REMOVE
#endif
int os_drop_memory(void *addr, int length)
@@ -216,7 +216,7 @@ int can_drop_memory(void)
}
addr = mmap64(NULL, UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE,
- MAP_PRIVATE, fd, 0);
+ MAP_SHARED, fd, 0);
if(addr == MAP_FAILED){
printk("Mapping test memory file failed, err = %d\n", -errno);
return 0;
@@ -266,11 +266,11 @@ void init_new_thread_signals(int altstack)
int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr)
{
- sigjmp_buf buf;
+ jmp_buf buf;
int n, enable;
*jmp_ptr = &buf;
- n = UML_SIGSETJMP(&buf, enable);
+ n = UML_SETJMP(&buf, enable);
if(n != 0)
return(n);
(*fn)(arg);
diff --git a/arch/um/os-Linux/sigio.c b/arch/um/os-Linux/sigio.c
index 9ba94294714..00e9388e947 100644
--- a/arch/um/os-Linux/sigio.c
+++ b/arch/um/os-Linux/sigio.c
@@ -304,8 +304,8 @@ out_clear_poll:
.size = 0,
.used = 0 });
out_free:
- kfree(p);
sigio_unlock();
+ kfree(p);
out_close2:
close(l_sigio_private[0]);
close(l_sigio_private[1]);
diff --git a/arch/um/os-Linux/skas/mem.c b/arch/um/os-Linux/skas/mem.c
index fbb080c2fc2..b3c11cfa995 100644
--- a/arch/um/os-Linux/skas/mem.c
+++ b/arch/um/os-Linux/skas/mem.c
@@ -82,8 +82,8 @@ static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr)
if (offset) {
data = (unsigned long *)(mm_idp->stack +
offset - UML_CONFIG_STUB_DATA);
- printk("do_syscall_stub : ret = %d, offset = %d, "
- "data = 0x%x\n", ret, offset, data);
+ printk("do_syscall_stub : ret = %ld, offset = %ld, "
+ "data = %p\n", ret, offset, data);
syscall = (unsigned long *)((unsigned long)data + data[0]);
printk("do_syscall_stub: syscall %ld failed, return value = "
"0x%lx, expected return value = 0x%lx\n",
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index bbf34cb91ce..0776bc18ca8 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -265,7 +265,7 @@ void userspace(union uml_pt_regs *regs)
if(err)
panic("userspace - could not resume userspace process, "
"pid=%d, ptrace operation = %d, errno = %d\n",
- op, errno);
+ pid, op, errno);
CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED));
if(err < 0)
@@ -369,7 +369,7 @@ int copy_context_skas0(unsigned long new_stack, int pid)
*/
wait_stub_done(pid, -1, "copy_context_skas0");
if (child_data->err != UML_CONFIG_STUB_DATA)
- panic("copy_context_skas0 - stub-child reports error %d\n",
+ panic("copy_context_skas0 - stub-child reports error %ld\n",
child_data->err);
if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL,
@@ -434,7 +434,7 @@ void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
void (*handler)(int))
{
unsigned long flags;
- sigjmp_buf switch_buf, fork_buf;
+ jmp_buf switch_buf, fork_buf;
int enable;
*switch_buf_ptr = &switch_buf;
@@ -450,7 +450,7 @@ void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
*/
flags = get_signals();
block_signals();
- if(UML_SIGSETJMP(&fork_buf, enable) == 0)
+ if(UML_SETJMP(&fork_buf, enable) == 0)
new_thread_proc(stack, handler);
remove_sigstack();
@@ -466,35 +466,35 @@ void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
void thread_wait(void *sw, void *fb)
{
- sigjmp_buf buf, **switch_buf = sw, *fork_buf;
+ jmp_buf buf, **switch_buf = sw, *fork_buf;
int enable;
*switch_buf = &buf;
fork_buf = fb;
- if(UML_SIGSETJMP(&buf, enable) == 0)
+ if(UML_SETJMP(&buf, enable) == 0)
siglongjmp(*fork_buf, INIT_JMP_REMOVE_SIGSTACK);
}
void switch_threads(void *me, void *next)
{
- sigjmp_buf my_buf, **me_ptr = me, *next_buf = next;
+ jmp_buf my_buf, **me_ptr = me, *next_buf = next;
int enable;
*me_ptr = &my_buf;
- if(UML_SIGSETJMP(&my_buf, enable) == 0)
- UML_SIGLONGJMP(next_buf, 1);
+ if(UML_SETJMP(&my_buf, enable) == 0)
+ UML_LONGJMP(next_buf, 1);
}
-static sigjmp_buf initial_jmpbuf;
+static jmp_buf initial_jmpbuf;
/* XXX Make these percpu */
static void (*cb_proc)(void *arg);
static void *cb_arg;
-static sigjmp_buf *cb_back;
+static jmp_buf *cb_back;
int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
{
- sigjmp_buf **switch_buf = switch_buf_ptr;
+ jmp_buf **switch_buf = switch_buf_ptr;
int n, enable;
set_handler(SIGWINCH, (__sighandler_t) sig_handler,
@@ -502,7 +502,7 @@ int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
SIGVTALRM, -1);
*fork_buf_ptr = &initial_jmpbuf;
- n = UML_SIGSETJMP(&initial_jmpbuf, enable);
+ n = UML_SETJMP(&initial_jmpbuf, enable);
switch(n){
case INIT_JMP_NEW_THREAD:
new_thread_proc((void *) stack, new_thread_handler);
@@ -512,7 +512,7 @@ int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
break;
case INIT_JMP_CALLBACK:
(*cb_proc)(cb_arg);
- UML_SIGLONGJMP(cb_back, 1);
+ UML_LONGJMP(cb_back, 1);
break;
case INIT_JMP_HALT:
kmalloc_ok = 0;
@@ -523,12 +523,12 @@ int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr)
default:
panic("Bad sigsetjmp return in start_idle_thread - %d\n", n);
}
- UML_SIGLONGJMP(*switch_buf, 1);
+ UML_LONGJMP(*switch_buf, 1);
}
void initial_thread_cb_skas(void (*proc)(void *), void *arg)
{
- sigjmp_buf here;
+ jmp_buf here;
int enable;
cb_proc = proc;
@@ -536,8 +536,8 @@ void initial_thread_cb_skas(void (*proc)(void *), void *arg)
cb_back = &here;
block_signals();
- if(UML_SIGSETJMP(&here, enable) == 0)
- UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_CALLBACK);
+ if(UML_SETJMP(&here, enable) == 0)
+ UML_LONGJMP(&initial_jmpbuf, INIT_JMP_CALLBACK);
unblock_signals();
cb_proc = NULL;
@@ -548,13 +548,13 @@ void initial_thread_cb_skas(void (*proc)(void *), void *arg)
void halt_skas(void)
{
block_signals();
- UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_HALT);
+ UML_LONGJMP(&initial_jmpbuf, INIT_JMP_HALT);
}
void reboot_skas(void)
{
block_signals();
- UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_REBOOT);
+ UML_LONGJMP(&initial_jmpbuf, INIT_JMP_REBOOT);
}
void switch_mm_skas(struct mm_id *mm_idp)
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c
index 387e26af301..50314850400 100644
--- a/arch/um/os-Linux/start_up.c
+++ b/arch/um/os-Linux/start_up.c
@@ -296,29 +296,7 @@ static void __init check_ptrace(void)
check_sysemu();
}
-extern int create_tmp_file(unsigned long long len);
-
-static void check_tmpexec(void)
-{
- void *addr;
- int err, fd = create_tmp_file(UM_KERN_PAGE_SIZE);
-
- addr = mmap(NULL, UM_KERN_PAGE_SIZE,
- PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0);
- printf("Checking PROT_EXEC mmap in /tmp...");
- fflush(stdout);
- if(addr == MAP_FAILED){
- err = errno;
- perror("failed");
- if(err == EPERM)
- printf("/tmp must be not mounted noexec\n");
- exit(1);
- }
- printf("OK\n");
- munmap(addr, UM_KERN_PAGE_SIZE);
-
- close(fd);
-}
+extern void check_tmpexec(void);
void os_early_checks(void)
{
diff --git a/arch/um/os-Linux/sys-i386/tls.c b/arch/um/os-Linux/sys-i386/tls.c
index ba21f0e04a2..120abbe4e3c 100644
--- a/arch/um/os-Linux/sys-i386/tls.c
+++ b/arch/um/os-Linux/sys-i386/tls.c
@@ -1,3 +1,4 @@
+#include <errno.h>
#include <linux/unistd.h>
#include "sysdep/tls.h"
#include "user_util.h"
diff --git a/arch/um/os-Linux/trap.c b/arch/um/os-Linux/trap.c
index a9f6b26f982..90b29ae9af4 100644
--- a/arch/um/os-Linux/trap.c
+++ b/arch/um/os-Linux/trap.c
@@ -35,7 +35,7 @@ void os_fill_handlinfo(struct kern_handlers h)
void do_longjmp(void *b, int val)
{
- sigjmp_buf *buf = b;
+ jmp_buf *buf = b;
- UML_SIGLONGJMP(buf, val);
+ UML_LONGJMP(buf, val);
}
diff --git a/arch/um/os-Linux/uaccess.c b/arch/um/os-Linux/uaccess.c
index 166fb66995d..e523719330b 100644
--- a/arch/um/os-Linux/uaccess.c
+++ b/arch/um/os-Linux/uaccess.c
@@ -16,9 +16,9 @@ unsigned long __do_user_copy(void *to, const void *from, int n,
unsigned long *faddrp = (unsigned long *) fault_addr, ret;
int enable;
- sigjmp_buf jbuf;
+ jmp_buf jbuf;
*fault_catcher = &jbuf;
- if(UML_SIGSETJMP(&jbuf, enable) == 0){
+ if(UML_SETJMP(&jbuf, enable) == 0){
(*op)(to, from, n);
ret = 0;
*faulted_out = 0;
diff --git a/arch/um/os-Linux/umid.c b/arch/um/os-Linux/umid.c
index 198e5916328..34bfc1bb9e3 100644
--- a/arch/um/os-Linux/umid.c
+++ b/arch/um/os-Linux/umid.c
@@ -120,7 +120,8 @@ static int not_dead_yet(char *dir)
dead = 0;
fd = open(file, O_RDONLY);
- if(fd < 0){
+ if(fd < 0) {
+ fd = -errno;
if(fd != -ENOENT){
printk("not_dead_yet : couldn't open pid file '%s', "
"err = %d\n", file, -fd);
@@ -130,9 +131,13 @@ static int not_dead_yet(char *dir)
err = 0;
n = read(fd, pid, sizeof(pid));
- if(n <= 0){
+ if(n < 0){
+ printk("not_dead_yet : couldn't read pid file '%s', "
+ "err = %d\n", file, errno);
+ goto out_close;
+ } else if(n == 0){
printk("not_dead_yet : couldn't read pid file '%s', "
- "err = %d\n", file, -n);
+ "0-byte read\n", file);
goto out_close;
}
@@ -155,9 +160,9 @@ static int not_dead_yet(char *dir)
return err;
- out_close:
+out_close:
close(fd);
- out:
+out:
return 0;
}
diff --git a/arch/um/os-Linux/user_syms.c b/arch/um/os-Linux/user_syms.c
index 8da6ab31152..2598158e1f5 100644
--- a/arch/um/os-Linux/user_syms.c
+++ b/arch/um/os-Linux/user_syms.c
@@ -18,14 +18,19 @@ extern void *memmove(void *, const void *, size_t);
extern void *memset(void *, int, size_t);
extern int printf(const char *, ...);
+/* If they're not defined, the export is included in lib/string.c.*/
+#ifdef __HAVE_ARCH_STRLEN
EXPORT_SYMBOL(strlen);
+#endif
+#ifdef __HAVE_ARCH_STRSTR
+EXPORT_SYMBOL(strstr);
+#endif
+
EXPORT_SYMBOL(memcpy);
EXPORT_SYMBOL(memmove);
EXPORT_SYMBOL(memset);
EXPORT_SYMBOL(printf);
-EXPORT_SYMBOL(strstr);
-
/* Here, instead, I can provide a fake prototype. Yes, someone cares: genksyms.
* However, the modules will use the CRC defined *here*, no matter if it is
* good; so the versions of these symbols will always match
diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c
index e32065e2fdc..c47a2a7ce70 100644
--- a/arch/um/os-Linux/util.c
+++ b/arch/um/os-Linux/util.c
@@ -104,7 +104,7 @@ void setup_hostinfo(void)
int setjmp_wrapper(void (*proc)(void *, void *), ...)
{
va_list args;
- sigjmp_buf buf;
+ jmp_buf buf;
int n;
n = sigsetjmp(buf, 1);