Skip to content

Commit

Permalink
[PATCH] uml: physical memory map file fixes
Browse files Browse the repository at this point in the history
UML really wants shared memory semantics form its physical memory map file,
and the place for that is /dev/shm.  So move the default, and fix the error
messages to recognize that this value can be overridden.

Signed-off-by: Rob Landley <rob@landley.net>
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
  • Loading branch information
Rob Landley authored and Linus Torvalds committed Apr 19, 2006
1 parent f983c45 commit 966a082
Show file tree
Hide file tree
Showing 2 changed files with 118 additions and 24 deletions.
118 changes: 117 additions & 1 deletion arch/um/os-Linux/mem.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -19,6 +20,7 @@

#include <sys/param.h>

static char *default_tmpdir = "/tmp";
static char *tempdir = NULL;

static void __init find_tempdir(void)
Expand All @@ -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){
Expand All @@ -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).
Expand All @@ -56,6 +148,7 @@ int make_tempfile(const char *template, char **out_tempname, int do_unlink)
char *tempname;
int fd;

which_tmpdir();
tempname = malloc(MAXPATHLEN);

find_tempdir();
Expand Down Expand Up @@ -137,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);
}
24 changes: 1 addition & 23 deletions arch/um/os-Linux/start_up.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down

0 comments on commit 966a082

Please sign in to comment.