diff options
-rw-r--r-- | ChangeLog | 22 | ||||
-rw-r--r-- | NEWS | 26 | ||||
-rw-r--r-- | locale/locarchive.h | 7 | ||||
-rw-r--r-- | locale/programs/locarchive.c | 61 | ||||
-rw-r--r-- | sysdeps/generic/libc-mmap.h | 26 |
5 files changed, 113 insertions, 29 deletions
diff --git a/ChangeLog b/ChangeLog index 18e41e8083..445d131a10 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,27 @@ 2013-06-24 Mike Frysinger <vapier@gentoo.org> + [BZ #10283] + * NEWS: Note fixing of BZ #10283. + * locale/locarchive.h (struct locarhandle): Add mmap_base and mmap_len. + * locale/programs/locarchive.c: Include libc-mmap.h. + (prepare_address_space): Take two new outputs (the mmap base and len). + Align p to MAP_FIXED_ALIGNMENT. Set mmap base and len to the right + values. + (create_archive): Declare new mmap base and len values for + prepare_address_space, and store the result in ah. + (file_data_available_p): Replace pagesz with MAP_FIXED_ALIGNMENT. + (enlarge_archive): If ah->mmap_base is not NULL, use that and + ah->mmap_len to unmap rather than ah->addr and ah->reserved. + Declare new mmap base and len values for + prepare_address_space, and store the result in new_ah. + (open_archive): Declare new mmap base and len values for + prepare_address_space, and store the result in ah. + (close_archive): If ah->mmap_base is not NULL, use that and + ah->mmap_len to unmap rather than ah->addr and ah->reserved. + * sysdeps/generic/libc-mmap.h: New file. + +2013-06-24 Mike Frysinger <vapier@gentoo.org> + * include/libc-internal.h (ALIGN_DOWN): New helper macro. (ALIGN_UP): Likewise. (PTR_ALIGN_DOWN): Likewise. diff --git a/NEWS b/NEWS index b238255e16..f0ff9759bb 100644 --- a/NEWS +++ b/NEWS @@ -9,19 +9,19 @@ Version 2.18 * The following bugs are resolved with this release: - 2546, 2560, 5159, 6809, 7006, 10060, 10062, 10357, 10686, 11120, 11561, - 12310, 12387, 12515, 12723, 13550, 13889, 13951, 13988, 14142, 14176, - 14200, 14256, 14280, 14293, 14317, 14327, 14478, 14496, 14582, 14686, - 14812, 14888, 14894, 14907, 14908, 14909, 14920, 14952, 14964, 14981, - 14982, 14985, 14991, 14994, 14996, 15000, 15003, 15006, 15007, 15014, - 15020, 15023, 15036, 15054, 15055, 15062, 15078, 15084, 15085, 15086, - 15100, 15160, 15214, 15221, 15232, 15234, 15283, 15285, 15287, 15304, - 15305, 15307, 15309, 15327, 15330, 15335, 15336, 15337, 15339, 15342, - 15346, 15359, 15361, 15366, 15380, 15381, 15394, 15395, 15405, 15406, - 15409, 15416, 15418, 15419, 15423, 15424, 15426, 15429, 15431, 15432, - 15441, 15442, 15448, 15465, 15480, 15485, 15488, 15490, 15492, 15493, - 15497, 15506, 15529, 15536, 15553, 15577, 15583, 15618, 15627, 15631, - 15654, 15655, 15667. + 2546, 2560, 5159, 6809, 7006, 10060, 10062, 10283, 10357, 10686, 11120, + 11561, 12310, 12387, 12515, 12723, 13550, 13889, 13951, 13988, 14142, + 14176, 14200, 14256, 14280, 14293, 14317, 14327, 14478, 14496, 14582, + 14686, 14812, 14888, 14894, 14907, 14908, 14909, 14920, 14952, 14964, + 14981, 14982, 14985, 14991, 14994, 14996, 15000, 15003, 15006, 15007, + 15014, 15020, 15023, 15036, 15054, 15055, 15062, 15078, 15084, 15085, + 15086, 15100, 15160, 15214, 15221, 15232, 15234, 15283, 15285, 15287, + 15304, 15305, 15307, 15309, 15327, 15330, 15335, 15336, 15337, 15339, + 15342, 15346, 15359, 15361, 15366, 15380, 15381, 15394, 15395, 15405, + 15406, 15409, 15416, 15418, 15419, 15423, 15424, 15426, 15429, 15431, + 15432, 15441, 15442, 15448, 15465, 15480, 15485, 15488, 15490, 15492, + 15493, 15497, 15506, 15529, 15536, 15553, 15577, 15583, 15618, 15627, + 15631, 15654, 15655, 15667. * CVE-2013-0242 Buffer overrun in regexp matcher has been fixed (Bugzilla #15078). diff --git a/locale/locarchive.h b/locale/locarchive.h index db05603dfb..f2d84771ab 100644 --- a/locale/locarchive.h +++ b/locale/locarchive.h @@ -84,6 +84,13 @@ struct locarhandle void *addr; size_t mmaped; size_t reserved; + /* If this mmap required adjustment (such as re-aligning), then this is the + real address that was returned from mmap and thus should be passed to the + munmap call. The addr field above is the first usable address. */ + void *mmap_base; + /* Same as above for mmap_base vs addr, but this is the real length of the + map rather than the usable (which is what reserved represents). */ + size_t mmap_len; }; diff --git a/locale/programs/locarchive.c b/locale/programs/locarchive.c index 2f544893b6..3255c6c0f8 100644 --- a/locale/programs/locarchive.c +++ b/locale/programs/locarchive.c @@ -37,8 +37,10 @@ #include <stdint.h> #include <sys/mman.h> #include <sys/param.h> +#include <sys/shm.h> #include <sys/stat.h> +#include <libc-mmap.h> #include "../../crypt/md5.h" #include "../localeinfo.h" #include "../locarchive.h" @@ -79,21 +81,29 @@ static const char *locnames[] = mapping affects the address selection. So do this mapping from the actual file, even though it's only a dummy to reserve address space. */ static void * -prepare_address_space (int fd, size_t total, size_t *reserved, int *xflags) +prepare_address_space (int fd, size_t total, size_t *reserved, int *xflags, + void **mmap_base, size_t *mmap_len) { if (total < RESERVE_MMAP_SIZE) { void *p = mmap64 (NULL, RESERVE_MMAP_SIZE, PROT_NONE, MAP_SHARED, fd, 0); if (p != MAP_FAILED) - { - *reserved = RESERVE_MMAP_SIZE; - *xflags = MAP_FIXED; - return p; - } + { + void *aligned_p = PTR_ALIGN_UP (p, MAP_FIXED_ALIGNMENT); + size_t align_adjust = aligned_p - p; + *mmap_base = p; + *mmap_len = RESERVE_MMAP_SIZE; + assert (align_adjust < RESERVE_MMAP_SIZE); + *reserved = RESERVE_MMAP_SIZE - align_adjust; + *xflags = MAP_FIXED; + return aligned_p; + } } *reserved = total; *xflags = 0; + *mmap_base = NULL; + *mmap_len = 0; return NULL; } @@ -151,9 +161,11 @@ create_archive (const char *archivefname, struct locarhandle *ah) error (EXIT_FAILURE, errval, _("cannot resize archive file")); } - size_t reserved; + size_t reserved, mmap_len; int xflags; - void *p = prepare_address_space (fd, total, &reserved, &xflags); + void *mmap_base; + void *p = prepare_address_space (fd, total, &reserved, &xflags, &mmap_base, + &mmap_len); /* Map the header and all the administration data structures. */ p = mmap64 (p, total, PROT_READ | PROT_WRITE, MAP_SHARED | xflags, fd, 0); @@ -199,6 +211,8 @@ create_archive (const char *archivefname, struct locarhandle *ah) } ah->fd = fd; + ah->mmap_base = mmap_base; + ah->mmap_len = mmap_len; ah->addr = p; ah->mmaped = total; ah->reserved = reserved; @@ -271,8 +285,7 @@ file_data_available_p (struct locarhandle *ah, uint32_t offset, uint32_t size) if (st.st_size > ah->reserved) return false; - const size_t pagesz = getpagesize (); - size_t start = ah->mmaped & ~(pagesz - 1); + size_t start = ALIGN_DOWN (ah->mmaped, MAP_FIXED_ALIGNMENT); void *p = mmap64 (ah->addr + start, st.st_size - start, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, ah->fd, start); @@ -332,10 +345,15 @@ enlarge_archive (struct locarhandle *ah, const struct locarhead *head) MAP_SHARED | MAP_FIXED, ah->fd, 0); else { - munmap (ah->addr, ah->reserved); + if (ah->mmap_base) + munmap (ah->mmap_base, ah->mmap_len); + else + munmap (ah->addr, ah->reserved); ah->addr = mmap64 (NULL, st.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, ah->fd, 0); ah->reserved = st.st_size; + ah->mmap_base = NULL; + ah->mmap_len = 0; head = ah->addr; } if (ah->addr == MAP_FAILED) @@ -401,9 +419,11 @@ enlarge_archive (struct locarhandle *ah, const struct locarhead *head) error (EXIT_FAILURE, errval, _("cannot resize archive file")); } - size_t reserved; + size_t reserved, mmap_len; int xflags; - void *p = prepare_address_space (fd, total, &reserved, &xflags); + void *mmap_base; + void *p = prepare_address_space (fd, total, &reserved, &xflags, &mmap_base, + &mmap_len); /* Map the header and all the administration data structures. */ p = mmap64 (p, total, PROT_READ | PROT_WRITE, MAP_SHARED | xflags, fd, 0); @@ -423,6 +443,8 @@ enlarge_archive (struct locarhandle *ah, const struct locarhead *head) } new_ah.mmaped = total; + new_ah.mmap_base = mmap_base; + new_ah.mmap_len = mmap_len; new_ah.addr = p; new_ah.fd = fd; new_ah.reserved = reserved; @@ -606,9 +628,11 @@ open_archive (struct locarhandle *ah, bool readonly) ah->fd = fd; ah->mmaped = st.st_size; - size_t reserved; + size_t reserved, mmap_len; int xflags; - void *p = prepare_address_space (fd, st.st_size, &reserved, &xflags); + void *mmap_base; + void *p = prepare_address_space (fd, st.st_size, &reserved, &xflags, + &mmap_base, &mmap_len); /* Map the entire file. We might need to compare the category data in the file with the newly added data. */ @@ -620,6 +644,8 @@ open_archive (struct locarhandle *ah, bool readonly) error (EXIT_FAILURE, errno, _("cannot map archive header")); } ah->reserved = reserved; + ah->mmap_base = mmap_base; + ah->mmap_len = mmap_len; } @@ -628,7 +654,10 @@ close_archive (struct locarhandle *ah) { if (ah->fd != -1) { - munmap (ah->addr, ah->reserved); + if (ah->mmap_base) + munmap (ah->mmap_base, ah->mmap_len); + else + munmap (ah->addr, ah->reserved); close (ah->fd); } } diff --git a/sysdeps/generic/libc-mmap.h b/sysdeps/generic/libc-mmap.h new file mode 100644 index 0000000000..0ddd20d42a --- /dev/null +++ b/sysdeps/generic/libc-mmap.h @@ -0,0 +1,26 @@ +/* Internal logic for dealing with mmap quirks. + Copyright (C) 2013 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef _LIBC_MMAP_H +#define _LIBC_MMAP_H 1 + +/* Using MAP_FIXED with mmap sometimes requires larger alignment. */ +#include <sys/shm.h> +#define MAP_FIXED_ALIGNMENT SHMLBA + +#endif |