diff options
Diffstat (limited to 'arch/um/os-Linux')
| -rw-r--r-- | arch/um/os-Linux/Makefile | 8 | ||||
| -rw-r--r-- | arch/um/os-Linux/mem.c | 161 | ||||
| -rw-r--r-- | arch/um/os-Linux/start_up.c | 109 | ||||
| -rw-r--r-- | arch/um/os-Linux/tt.c | 14 | 
4 files changed, 286 insertions, 6 deletions
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile index 7a1662419c0..d15ec2af6a2 100644 --- a/arch/um/os-Linux/Makefile +++ b/arch/um/os-Linux/Makefile @@ -3,11 +3,11 @@  # Licensed under the GPL  # -obj-y = aio.o elf_aux.o file.o process.o signal.o start_up.o time.o tt.o \ -	tty.o user_syms.o drivers/ sys-$(SUBARCH)/ +obj-y = aio.o elf_aux.o file.o mem.o process.o signal.o start_up.o time.o \ +	tt.o tty.o user_syms.o drivers/ sys-$(SUBARCH)/ -USER_OBJS := aio.o elf_aux.o file.o process.o signal.o start_up.o time.o tt.o \ -	tty.o +USER_OBJS := aio.o elf_aux.o file.o mem.o process.o signal.o start_up.o \ +	time.o tt.o tty.o  elf_aux.o: $(ARCH_DIR)/kernel-offsets.h  CFLAGS_elf_aux.o += -I$(objtree)/arch/um diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c new file mode 100644 index 00000000000..8e71edaaf80 --- /dev/null +++ b/arch/um/os-Linux/mem.c @@ -0,0 +1,161 @@ +#include <stdio.h> +#include <stdlib.h> +#include <stddef.h> +#include <stdarg.h> +#include <unistd.h> +#include <errno.h> +#include <string.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/mman.h> +#include "kern_util.h" +#include "user.h" +#include "user_util.h" +#include "mem_user.h" +#include "init.h" +#include "os.h" +#include "tempfile.h" +#include "kern_constants.h" + +#include <sys/param.h> + +static char *tempdir = NULL; + +static void __init find_tempdir(void) +{ +	char *dirs[] = { "TMP", "TEMP", "TMPDIR", NULL }; +	int i; +	char *dir = NULL; + +	if(tempdir != NULL) return;	/* We've already been called */ +	for(i = 0; dirs[i]; i++){ +		dir = getenv(dirs[i]); +		if((dir != NULL) && (*dir != '\0')) +			break; +	} +	if((dir == NULL) || (*dir == '\0')) +		dir = "/tmp"; + +	tempdir = malloc(strlen(dir) + 2); +	if(tempdir == NULL){ +		fprintf(stderr, "Failed to malloc tempdir, " +			"errno = %d\n", errno); +		return; +	} +	strcpy(tempdir, dir); +	strcat(tempdir, "/"); +} + +/* + * This proc still used in tt-mode + * (file: kernel/tt/ptproxy/proxy.c, proc: start_debugger). + * So it isn't 'static' yet. + */ +int make_tempfile(const char *template, char **out_tempname, int do_unlink) +{ +	char tempname[MAXPATHLEN]; +	int fd; + +	find_tempdir(); +	if (*template != '/') +		strcpy(tempname, tempdir); +	else +		*tempname = 0; +	strcat(tempname, template); +	fd = mkstemp(tempname); +	if(fd < 0){ +		fprintf(stderr, "open - cannot create %s: %s\n", tempname, +			strerror(errno)); +		return -1; +	} +	if(do_unlink && (unlink(tempname) < 0)){ +		perror("unlink"); +		return -1; +	} +	if(out_tempname){ +		*out_tempname = strdup(tempname); +		if(*out_tempname == NULL){ +			perror("strdup"); +			return -1; +		} +	} +	return(fd); +} + +#define TEMPNAME_TEMPLATE "vm_file-XXXXXX" + +/* + * This proc is used in start_up.c + * So it isn't 'static'. + */ +int create_tmp_file(unsigned long len) +{ +	int fd, err; +	char zero; + +	fd = make_tempfile(TEMPNAME_TEMPLATE, NULL, 1); +	if(fd < 0) { +		exit(1); +	} + +	err = fchmod(fd, 0777); +	if(err < 0){ +		perror("os_mode_fd"); +		exit(1); +	} + +        if (lseek64(fd, len, SEEK_SET) < 0) { + 		perror("os_seek_file"); +		exit(1); +	} + +	zero = 0; + +	err = os_write_file(fd, &zero, 1); +	if(err != 1){ +		errno = -err; +		perror("os_write_file"); +		exit(1); +	} + +	return(fd); +} + +static int create_anon_file(unsigned long len) +{ +	void *addr; +	int fd; + +	fd = open("/dev/anon", O_RDWR); +	if(fd < 0) { +		perror("opening /dev/anon"); +		exit(1); +	} + +	addr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); +	if(addr == MAP_FAILED){ +		perror("mapping physmem file"); +		exit(1); +	} +	munmap(addr, len); + +	return(fd); +} + +extern int have_devanon; + +int create_mem_file(unsigned long len) +{ +	int err, fd; + +	if(have_devanon) +		fd = create_anon_file(len); +	else fd = create_tmp_file(len); + +	err = os_set_exec_close(fd, 1); +	if(err < 0){ +		errno = -err; +		perror("exec_close"); +	} +	return(fd); +} diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c index 040cc1472bc..6af83171ca4 100644 --- a/arch/um/os-Linux/start_up.c +++ b/arch/um/os-Linux/start_up.c @@ -4,18 +4,22 @@   */  #include <stdio.h> +#include <stddef.h> +#include <stdarg.h> +#include <stdlib.h> +#include <string.h>  #include <unistd.h>  #include <signal.h>  #include <sched.h> +#include <fcntl.h>  #include <errno.h> -#include <stdarg.h> -#include <stdlib.h>  #include <setjmp.h>  #include <sys/time.h>  #include <sys/wait.h>  #include <sys/mman.h>  #include <asm/unistd.h>  #include <asm/page.h> +#include <sys/types.h>  #include "user_util.h"  #include "kern_util.h"  #include "user.h" @@ -25,6 +29,7 @@  #include "sysdep/sigcontext.h"  #include "irq_user.h"  #include "ptrace_user.h" +#include "mem_user.h"  #include "time_user.h"  #include "init.h"  #include "os.h" @@ -32,6 +37,8 @@  #include "choose-mode.h"  #include "mode.h"  #include "tempfile.h" +#include "kern_constants.h" +  #ifdef UML_CONFIG_MODE_SKAS  #include "skas.h"  #include "skas_ptrace.h" @@ -276,9 +283,38 @@ static void __init check_ptrace(void)  	check_sysemu();  } +extern int create_tmp_file(unsigned 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); +} +  void os_early_checks(void)  {  	check_ptrace(); + +	/* Need to check this early because mmapping happens before the +	 * kernel is running. +	 */ +	check_tmpexec();  }  static int __init noprocmm_cmd_param(char *str, int* add) @@ -357,3 +393,72 @@ int can_do_skas(void)  	return(0);  }  #endif + +int have_devanon = 0; + +void check_devanon(void) +{ +	int fd; + +	printk("Checking for /dev/anon on the host..."); +	fd = open("/dev/anon", O_RDWR); +	if(fd < 0){ +		printk("Not available (open failed with errno %d)\n", errno); +		return; +	} + +	printk("OK\n"); +	have_devanon = 1; +} + +int __init parse_iomem(char *str, int *add) +{ +	struct iomem_region *new; +	struct uml_stat buf; +	char *file, *driver; +	int fd, err, size; + +	driver = str; +	file = strchr(str,','); +	if(file == NULL){ +		printf("parse_iomem : failed to parse iomem\n"); +		goto out; +	} +	*file = '\0'; +	file++; +	fd = os_open_file(file, of_rdwr(OPENFLAGS()), 0); +	if(fd < 0){ +		os_print_error(fd, "parse_iomem - Couldn't open io file"); +		goto out; +	} + +	err = os_stat_fd(fd, &buf); +	if(err < 0){ +		os_print_error(err, "parse_iomem - cannot stat_fd file"); +		goto out_close; +	} + +	new = malloc(sizeof(*new)); +	if(new == NULL){ +		perror("Couldn't allocate iomem_region struct"); +		goto out_close; +	} + +	size = (buf.ust_size + UM_KERN_PAGE_SIZE) & ~(UM_KERN_PAGE_SIZE - 1); + +	*new = ((struct iomem_region) { .next		= iomem_regions, +					.driver		= driver, +					.fd		= fd, +					.size		= size, +					.phys		= 0, +					.virt		= 0 }); +	iomem_regions = new; +	iomem_size += new->size + UM_KERN_PAGE_SIZE; + +	return(0); + out_close: +	os_close_file(fd); + out: +	return(1); +} + diff --git a/arch/um/os-Linux/tt.c b/arch/um/os-Linux/tt.c index 5b047ab8416..a6db8877931 100644 --- a/arch/um/os-Linux/tt.c +++ b/arch/um/os-Linux/tt.c @@ -36,6 +36,20 @@  #include "mode.h"  #include "tempfile.h" +int protect_memory(unsigned long addr, unsigned long len, int r, int w, int x, +		   int must_succeed) +{ +	int err; + +	err = os_protect_memory((void *) addr, len, r, w, x); +	if(err < 0){ +                if(must_succeed) +			panic("protect failed, err = %d", -err); +		else return(err); +	} +	return(0); +} +  /*   *-------------------------   * only for tt mode (will be deleted in future...)  |