From 1cdce607b52bea36f89b5620f53237db4a8216ce Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Fri, 26 Jul 2013 16:33:59 +0100 Subject: [PATCH] initial code --- .gitignore | 3 +++ Makefile | 7 +++++ map-unshare.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++ map-unshare.h | 6 +++++ simple-test.c | 20 ++++++++++++++ 5 files changed, 111 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 map-unshare.c create mode 100644 map-unshare.h create mode 100644 simple-test.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a8637a6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.o +*~ +simple-test diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..75321d8 --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ + +CFLAGS += -Wall -Werror + +simple-test: map-unshare.o simple-test.o + +clean: + rm -f *.o simple-test diff --git a/map-unshare.c b/map-unshare.c new file mode 100644 index 0000000..5af8996 --- /dev/null +++ b/map-unshare.c @@ -0,0 +1,75 @@ +#include +#include +#include +#include +#include +#include + +#include "map-unshare.h" + +#define MAXFLAGS 10 + +#define STRING(x) STRING2(x) +#define STRING2(x) #x + +void map_unshare(void) { + char lbuf[4096]; + FILE *maps = fopen("/proc/self/maps", "r"); + assert(maps); + while (fgets(lbuf,sizeof(lbuf),maps)) { + uintptr_t mstart,mend; + unsigned long inum; + char flagstr[MAXFLAGS+1]; + int pathoffset; + + int ll = strlen(lbuf); + assert(ll>=1); + assert(lbuf[ll-1]=='\n'); + lbuf[--ll]=0; + + pathoffset=-1; + sscanf(lbuf,"%"SCNxPTR"-%"SCNxPTR" %"STRING(MAXFLAGS)"s" + " %*"SCNxPTR" %*x:%*x %lu %n", + &mstart,&mend, flagstr, &inum, &pathoffset); + assert(pathoffset>=0 && pathoffset<=ll); + const char *orgpath = lbuf+pathoffset; + fprintf(stderr,"%"PRIxPTR"-%"PRIxPTR" %s %lu %s: ", + mstart,mend,flagstr,inum,orgpath); + int prot = + (!!strchr(flagstr,'x') * PROT_EXEC) | + (!!strchr(flagstr,'r') * PROT_READ) | + (!!strchr(flagstr,'w') * PROT_WRITE); + int flags = + (!!strchr(flagstr,'p') * MAP_PRIVATE) | + (!!strchr(flagstr,'s') * MAP_SHARED); + +#define SKIP(why) { fprintf(stderr,"skip, %s\n",(why)); continue; } + + if (mstart==mend) SKIP("zero length"); + if (!(prot & PROT_READ)) SKIP("unreadable"); + if ((prot & PROT_WRITE) && (flags & MAP_SHARED)) SKIP("shared write"); + if (orgpath[0] != '/') SKIP("no path"); + + FILE *copyf = tmpfile(); + assert(copyf); + + size_t length = mend-mstart; + void *startp = (void*)mstart; + + fputs("copy ",stderr); + size_t done = fwrite(startp, 1, length, copyf); + assert(done == length); + int r = fflush(copyf); + assert(!r); + + fputs("mmap ",stderr); + void *mapped; + mapped = mmap(startp, length, prot, MAP_SHARED|MAP_FIXED, fileno(copyf), 0); + assert(mapped = startp); + fclose(copyf); + + fputs("done.\n",stderr); + } + assert(!ferror(maps)); + fclose(maps); +} diff --git a/map-unshare.h b/map-unshare.h new file mode 100644 index 0000000..8bd64a3 --- /dev/null +++ b/map-unshare.h @@ -0,0 +1,6 @@ +#ifndef MAP_UNSHARE_H +#define MAP_UNSHARE_H + +void map_unshare(void); + +#endif /*MAP_UNSHARE_H*/ diff --git a/simple-test.c b/simple-test.c new file mode 100644 index 0000000..8e67bbd --- /dev/null +++ b/simple-test.c @@ -0,0 +1,20 @@ +#include "map-unshare.h" + +#include +#include +#include + +static void dumpmaps(void) { + FILE *maps = fopen("/proc/self/maps","r"); + int c; + while ((c=getc(maps)) != EOF) putchar(c); + assert(!ferror(maps) && !fclose(maps)); + assert(!fflush(stdout) && !ferror(stdout)); +} + +int main(void) { + dumpmaps(); + map_unshare(); + dumpmaps(); + exit(0); +} -- 2.30.2