From 0b79eac6423ec1e204856a6d29ce600422106cd6 Mon Sep 17 00:00:00 2001 From: Ben Gras Date: Mon, 17 Mar 2014 15:53:28 +0100 Subject: [PATCH] mmap: accept non-PROT_WRITE MAP_SHARED mappings Currently we don't accept writable file mmap()s, as there is no system in place to guarantee dirty buffers would make it back to disk. But we can actually accept MAP_SHARED for PROT_READ mappings, meaning the ranges aren't writable at all (and no private copy is made as with MAP_PRIVATE), as it turns out a fairly large class of usage. . fail writable MAP_SHARED mappings at runtime . reduces some minix-specific patches . lets binutils gold build on minix without further patching Change-Id: If2896c0a555328ac5b324afa706063fc6d86519e --- common/lib/libprop/prop_object.c | 4 ---- lib/libc/cdb/cdbr.c | 4 ---- lib/libc/nls/catopen.c | 4 ---- libexec/ftpd/ftpd.c | 6 ++++-- libexec/ld.elf_so/map_object.c | 4 ---- libexec/ld.elf_so/paths.c | 14 ++------------ servers/vm/mmap.c | 7 ++++--- sys/sys/mman.h | 2 -- test/test74.c | 10 ++++++++++ usr.bin/msgc/msg_sys.def | 4 ---- usr.bin/xinstall/xinstall.c | 8 +------- 11 files changed, 21 insertions(+), 46 deletions(-) diff --git a/common/lib/libprop/prop_object.c b/common/lib/libprop/prop_object.c index 12e040355..7a79e1934 100644 --- a/common/lib/libprop/prop_object.c +++ b/common/lib/libprop/prop_object.c @@ -942,13 +942,9 @@ _prop_object_internalize_map_file(const char *fname) if ((sb.st_size & pgmask) == 0) need_guard = true; -#ifndef __minix mf->poimf_xml = mmap(NULL, need_guard ? mf->poimf_mapsize + pgsize : mf->poimf_mapsize, PROT_READ, MAP_FILE|MAP_SHARED, fd, (off_t)0); -#else - mf->poimf_xml = MAP_FAILED; -#endif (void) close(fd); if (mf->poimf_xml == MAP_FAILED) { _PROP_FREE(mf, M_TEMP); diff --git a/lib/libc/cdb/cdbr.c b/lib/libc/cdb/cdbr.c index 0fe919625..2cc534db6 100644 --- a/lib/libc/cdb/cdbr.c +++ b/lib/libc/cdb/cdbr.c @@ -57,10 +57,6 @@ __RCSID("$NetBSD: cdbr.c,v 1.4 2012/09/27 00:37:43 joerg Exp $"); #include #include -#if defined(__minix) && !defined(MAP_SHARED) -#define MAP_SHARED MAP_PRIVATE /* LSC: We lose some memory, but it's OK as this is RO. */ -#endif /* defined(__minix) && !defined(MAP_SHARED) */ - #ifdef __weak_alias __weak_alias(cdbr_close,_cdbr_close) __weak_alias(cdbr_find,_cdbr_find) diff --git a/lib/libc/nls/catopen.c b/lib/libc/nls/catopen.c index eb81b1aec..b32c2479f 100644 --- a/lib/libc/nls/catopen.c +++ b/lib/libc/nls/catopen.c @@ -61,10 +61,6 @@ __RCSID("$NetBSD: catopen.c,v 1.32 2013/08/19 08:03:34 joerg Exp $"); #define NLS_DEFAULT_PATH "/usr/share/nls/%L/%N.cat:/usr/share/nls/%N/%L" #define NLS_DEFAULT_LANG "C" -#if defined(__minix) && !defined(MAP_SHARED) -#define MAP_SHARED MAP_PRIVATE /* LSC: We lose some memory, but it's OK as this is RO. */ -#endif /* defined(__minix) && !defined(MAP_SHARED) */ - __weak_alias(catopen, _catopen) __weak_alias(catopen_l, _catopen_l) diff --git a/libexec/ftpd/ftpd.c b/libexec/ftpd/ftpd.c index 179b7dd79..d230004bf 100644 --- a/libexec/ftpd/ftpd.c +++ b/libexec/ftpd/ftpd.c @@ -2232,7 +2232,6 @@ send_data_with_mmap(int filefd, int netfd, const struct stat *st, int isdata) (void)gettimeofday(&then, NULL); } else bufrem = winsize; -#if !defined(__minix) while (1) { mapsize = MIN(filesize - off, winsize); if (mapsize == 0) @@ -2244,10 +2243,14 @@ send_data_with_mmap(int filefd, int netfd, const struct stat *st, int isdata) goto try_read; return (SS_FILE_ERROR); } +#ifndef __minix (void) madvise(win, mapsize, MADV_SEQUENTIAL); +#endif error = write_data(netfd, win, mapsize, &bufrem, &then, isdata); +#ifndef __minix (void) madvise(win, mapsize, MADV_DONTNEED); +#endif munmap(win, mapsize); if (urgflag && handleoobcmd()) return (SS_ABORTED); @@ -2257,7 +2260,6 @@ send_data_with_mmap(int filefd, int netfd, const struct stat *st, int isdata) } return (SS_SUCCESS); -#endif /* !defined(__minix) */ try_read: return (send_data_with_read(filefd, netfd, st, isdata)); } diff --git a/libexec/ld.elf_so/map_object.c b/libexec/ld.elf_so/map_object.c index 7beafee06..ae178ea86 100644 --- a/libexec/ld.elf_so/map_object.c +++ b/libexec/ld.elf_so/map_object.c @@ -52,10 +52,6 @@ __RCSID("$NetBSD: map_object.c,v 1.52 2013/08/03 13:17:05 skrll Exp $"); #if defined(__minix) #define MINIXVERBOSE 0 -#ifndef MAP_SHARED -#define MAP_SHARED MAP_PRIVATE /* minix: MAP_SHARED should be MAP_PRIVATE */ -#endif - #if MINIXVERBOSE #include #endif diff --git a/libexec/ld.elf_so/paths.c b/libexec/ld.elf_so/paths.c index d763cfc5d..6f5c57ec9 100644 --- a/libexec/ld.elf_so/paths.c +++ b/libexec/ld.elf_so/paths.c @@ -61,15 +61,13 @@ __RCSID("$NetBSD: paths.c,v 1.41 2013/05/06 08:02:20 skrll Exp $"); static Search_Path *_rtld_find_path(Search_Path *, const char *, size_t); static Search_Path **_rtld_append_path(Search_Path **, Search_Path **, const char *, const char *, const char *); -#if !defined(__minix) static void _rtld_process_mapping(Library_Xform **, const char *, const char *); -#endif /* !defined(__minix) */ static char *exstrdup(const char *, const char *); -#if !defined(__minix) static const char *getstr(const char **, const char *, const char *); static const char *getcstr(const char **, const char *, const char *); static const char *getword(const char **, const char *, const char *); +#if !defined(__minix) static int matchstr(const char *, const char *, const char *); #endif /* !defined(__minix) */ @@ -90,7 +88,6 @@ exstrdup(const char *bp, const char *ep) return (cp); } -#if !defined(__minix) /* * Like strsep(), but takes end of string and doesn't put any NUL. To * detect empty string, compare `*p' and return value. @@ -149,6 +146,7 @@ getword(const char **p, const char *ep, const char *delim) return (getstr(p, ep, delim)); } +#if !defined(__minix) /* * Match `bp' against NUL terminated string pointed by `p'. */ @@ -234,7 +232,6 @@ _rtld_add_paths(const char *execname, Search_Path **path_p, const char *pathstr) } } -#if !defined(__minix) /* * Process library mappings of the form: * ... @@ -340,17 +337,11 @@ cleanup: xfree(hwptr->name); xfree(hwptr); } -#endif /* !defined(__minix) */ void _rtld_process_hints(const char *execname, Search_Path **path_p, Library_Xform **lib_p, const char *fname) { - -#if defined(__minix) - /* Minix doesn't support MAP_SHARED. */ - return; -#else int fd; char *buf, small[128]; const char *b, *ep, *ptr; @@ -421,7 +412,6 @@ _rtld_process_hints(const char *execname, Search_Path **path_p, if (buf != small) (void)munmap(buf, sz); -#endif /* defined(__minix) */ } #if !defined(__minix) diff --git a/servers/vm/mmap.c b/servers/vm/mmap.c index 62c0f432b..405e5fc79 100644 --- a/servers/vm/mmap.c +++ b/servers/vm/mmap.c @@ -256,9 +256,10 @@ int do_mmap(message *m) /* File mapping might be disabled */ if(!enable_filemap) return ENXIO; - /* files get private copies of pages on writes. */ - if(!(m->VMM_FLAGS & MAP_PRIVATE)) { - printf("VM: mmap file must MAP_PRIVATE\n"); + /* For files, we only can't accept writable MAP_SHARED + * mappings. + */ + if((m->VMM_FLAGS & MAP_SHARED) && (m->VMM_PROT & PROT_WRITE)) { return ENXIO; } diff --git a/sys/sys/mman.h b/sys/sys/mman.h index 19df99d08..91e3fa02f 100644 --- a/sys/sys/mman.h +++ b/sys/sys/mman.h @@ -68,9 +68,7 @@ typedef __off_t off_t; /* file offset */ * Flags contain sharing type and options. * Sharing types; choose one. */ -#if !defined(__minix) #define MAP_SHARED 0x0001 /* share changes */ -#endif /* !defined(__minix) */ #define MAP_PRIVATE 0x0002 /* changes are private */ #ifdef _KERNEL diff --git a/test/test74.c b/test/test74.c index 7d2d23fb2..252a2dfbd 100644 --- a/test/test74.c +++ b/test/test74.c @@ -403,6 +403,16 @@ void basic_regression(void) fd2 = open("../testsh2", O_RDONLY); if(fd1 < 0 || fd2 < 0) { e(2); } + /* just check that we can't mmap() a file writable */ + if(mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FILE, fd1, 0) != MAP_FAILED) { + e(1); + } + + /* check that we can mmap() a file MAP_SHARED readonly */ + if(mmap(NULL, PAGE_SIZE, PROT_READ, MAP_SHARED | MAP_FILE, fd1, 0) == MAP_FAILED) { + e(1); + } + /* clear cache of files before mmap so pages won't be present already */ if(fcntl(fd1, F_FLUSH_FS_CACHE) < 0) { e(1); } if(fcntl(fd2, F_FLUSH_FS_CACHE) < 0) { e(1); } diff --git a/usr.bin/msgc/msg_sys.def b/usr.bin/msgc/msg_sys.def index bc19d260f..1b1ba4e40 100644 --- a/usr.bin/msgc/msg_sys.def +++ b/usr.bin/msgc/msg_sys.def @@ -104,11 +104,7 @@ msg_file(const char *file) if (fd == -1) return -1; msgmapsz = lseek(fd, 0, SEEK_END); -#ifdef __minix - msgmap = mmap(0, msgmapsz, PROT_READ, MAP_PRIVATE, fd, 0); -#else /* ! __minix */ msgmap = mmap(0, msgmapsz, PROT_READ, MAP_SHARED, fd, 0); -#endif /* ! __minix */ close(fd); if (msgmap == MAP_FAILED) return -1; diff --git a/usr.bin/xinstall/xinstall.c b/usr.bin/xinstall/xinstall.c index 73f96897e..83acd42ac 100644 --- a/usr.bin/xinstall/xinstall.c +++ b/usr.bin/xinstall/xinstall.c @@ -819,9 +819,7 @@ copy(int from_fd, char *from_name, int to_fd, char *to_name, off_t size) { ssize_t nr, nw; int serrno; -#if !defined(__minix) u_char *p; -#endif /* !defined(__minix) */ u_char buf[MAXBSIZE]; MD5_CTX ctxMD5; RMD160_CTX ctxRMD160; @@ -868,15 +866,12 @@ copy(int from_fd, char *from_name, int to_fd, char *to_name, off_t size) */ if (size <= 8 * 1048576) { -#if defined(__minix) - goto mmap_failed; -#else if ((p = mmap(NULL, (size_t)size, PROT_READ, MAP_FILE|MAP_SHARED, from_fd, (off_t)0)) == MAP_FAILED) { goto mmap_failed; } -#if defined(MADV_SEQUENTIAL) && !defined(__APPLE__) +#if defined(MADV_SEQUENTIAL) && !defined(__APPLE__) && !defined(__minix) if (madvise(p, (size_t)size, MADV_SEQUENTIAL) == -1 && errno != EOPNOTSUPP) warnx("madvise: %s", strerror(errno)); @@ -911,7 +906,6 @@ copy(int from_fd, char *from_name, int to_fd, char *to_name, off_t size) break; } (void)munmap(p, size); -#endif /* defined(__minix) */ } else { mmap_failed: while ((nr = read(from_fd, buf, sizeof(buf))) > 0) { -- 2.44.0