about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog8
-rw-r--r--locale/loadarchive.c34
2 files changed, 33 insertions, 9 deletions
diff --git a/ChangeLog b/ChangeLog
index ac29548eac..38cf4938b3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
 2002-08-22  Roland McGrath  <roland@redhat.com>
 
+	* locale/loadarchive.c (_nl_load_locale_from_archive): Check max file
+	position indicated by locrectab against file bounds before rounding to
+	page size.  In mapping loop, always set TO before breaking out of
+	contiguous range coalescing loop.
+
+	* locale/loadarchive.c (_nl_load_locale_from_archive): Use MAP_PRIVATE
+	(or MAP_COPY if available) instead of MAP_SHARED.
+
 	* scripts/firstversions.awk: When encountering a version newer than
 	the specified earliest version, be sure to emit the specified earliest
 	version first if any renaming of an older version to that has been.
diff --git a/locale/loadarchive.c b/locale/loadarchive.c
index e32e8c7648..d25334a7fd 100644
--- a/locale/loadarchive.c
+++ b/locale/loadarchive.c
@@ -45,6 +45,19 @@ static const char archfname[] = LOCALEDIR "/locale-archive";
    cover the header plus the initial locale.  */
 #define ARCHIVE_MAPPING_WINDOW	(2 * 1024 * 1024)
 
+#ifndef MAP_COPY
+/* This is not quite as good as MAP_COPY since unexamined pages
+   can change out from under us and give us inconsistent data.
+   But we rely on the user not to diddle the system's live archive.
+   Even though we only ever use PROT_READ, using MAP_SHARED would
+   not give the system sufficient freedom to e.g. let the on disk
+   file go away because it doesn't know we won't call mprotect later.  */
+# define MAP_COPY MAP_PRIVATE
+#endif
+#ifndef MAP_FILE
+ /* Some systems do not have this flag; it is superfluous.  */
+# define MAP_FILE 0
+#endif
 
 /* Record of contiguous pages already mapped from the locale archive.  */
 struct archmapped
@@ -208,7 +221,7 @@ _nl_load_locale_from_archive (int category, const char **namep)
       mapsize = (sizeof (void *) > 4 ? archive_stat.st_size
 		 : MIN (archive_stat.st_size, ARCHIVE_MAPPING_WINDOW));
 
-      result = __mmap64 (NULL, mapsize, PROT_READ, MAP_SHARED, fd, 0);
+      result = __mmap64 (NULL, mapsize, PROT_READ, MAP_FILE|MAP_COPY, fd, 0);
       if (result == MAP_FAILED)
 	goto close_and_out;
 
@@ -226,7 +239,8 @@ _nl_load_locale_from_archive (int category, const char **namep)
 	  /* Freakishly long header.  */
 	  /* XXX could use mremap when available */
 	  mapsize = (headsize + ps - 1) & ~(ps - 1);
-	  result = __mmap64 (NULL, mapsize, PROT_READ, MAP_SHARED, fd, 0);
+	  result = __mmap64 (NULL, mapsize, PROT_READ, MAP_FILE|MAP_COPY,
+			     fd, 0);
 	  if (result == MAP_FAILED)
 	    goto close_and_out;
 	}
@@ -357,20 +371,21 @@ _nl_load_locale_from_archive (int category, const char **namep)
 	  upper = cnt;
 	  do
 	    {
+	      to = ranges[upper].from + ranges[upper].len;
+	      if (to > archive_stat.st_size)
+		/* The archive locrectab contains bogus offsets.  */
+		return NULL;
+	      to = (to + ps - 1) & ~(ps - 1);
+
 	      /* If a range is already mmaped in, stop.	 */
 	      if (mapped != NULL && ranges[upper].from >= mapped->from)
 		break;
-	      to = ((ranges[upper].from + ranges[upper].len + ps - 1)
-		    & ~(ps - 1));
+
 	      ++upper;
 	    }
 	  /* Loop while still in contiguous pages. */
 	  while (upper < nranges && ranges[upper].from < to + ps);
 
-	  if (to > archive_stat.st_size)
-	    /* The archive locrectab contains bogus offsets.  */
-	    return NULL;
-
 	  /* Open the file if it hasn't happened yet.  */
 	  if (fd == -1)
 	    {
@@ -391,7 +406,8 @@ _nl_load_locale_from_archive (int category, const char **namep)
 	    }
 
 	  /* Map the range from the archive.  */
-	  addr = __mmap64 (NULL, to - from, PROT_READ, MAP_SHARED, fd, from);
+	  addr = __mmap64 (NULL, to - from, PROT_READ, MAP_FILE|MAP_COPY,
+			   fd, from);
 	  if (addr == MAP_FAILED)
 	    return NULL;