diff options
author | Adhemerval Zanella <adhemerval.zanella@linaro.org> | 2017-11-22 18:02:20 -0200 |
---|---|---|
committer | Adhemerval Zanella <adhemerval.zanella@linaro.org> | 2017-11-24 12:16:15 -0200 |
commit | c45d78aac47db08bc8ea7641c5330cccaecd3ddb (patch) | |
tree | 769aca2259f4781214044cb87e1d326955bc866e /sysdeps/posix | |
parent | 3ffc4cc1ad37fb36e419c9a3a72e1916d7d893d3 (diff) | |
download | glibc-c45d78aac47db08bc8ea7641c5330cccaecd3ddb.zip glibc-c45d78aac47db08bc8ea7641c5330cccaecd3ddb.tar.gz glibc-c45d78aac47db08bc8ea7641c5330cccaecd3ddb.tar.bz2 |
posix: Fix generic p{read,write}v buffer allocation (BZ#22457)
As described in BZ#22457 an interpose malloc can free an invalid
pointer for fallback preadv implementation. Fortunately this is
just and issue on microblaze-linux-gnu running kernels older than
3.15. This patch fixes it by calling mmap/unmap instead of
posix_memalign/ free.
Checked on microblaze-linux-gnu check with run-built-tests=no and
by using the sysdeps/posix implementation on x86_64-linux-gnu (just
for sanity test where it shown no regression).
[BZ #22457]
* sysdeps/posix/preadv_common.c (PREADV): Use mmap/munmap instead of
posix_memalign/free.
* sysdeps/posix/pwritev_common.c (PWRITEV): Likewise.
Diffstat (limited to 'sysdeps/posix')
-rw-r--r-- | sysdeps/posix/preadv_common.c | 8 | ||||
-rw-r--r-- | sysdeps/posix/pwritev_common.c | 8 |
2 files changed, 10 insertions, 6 deletions
diff --git a/sysdeps/posix/preadv_common.c b/sysdeps/posix/preadv_common.c index 37efdc0..76cf261 100644 --- a/sysdeps/posix/preadv_common.c +++ b/sysdeps/posix/preadv_common.c @@ -24,6 +24,7 @@ #include <malloc.h> #include <ldsodefs.h> +#include <libc-pointer-arith.h> /* Read data from file descriptor FD at the given position OFFSET without change the file pointer, and put the result in the buffers @@ -54,8 +55,9 @@ PREADV (int fd, const struct iovec *vector, int count, OFF_T offset) but 1. it is system specific (not meant in generic implementation), and 2. it would make the implementation more complex, and 3. it will require another syscall (fcntl). */ - void *buffer = NULL; - if (__posix_memalign (&buffer, GLRO(dl_pagesize), bytes) != 0) + void *buffer = __mmap (NULL, bytes, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (__glibc_unlikely (buffer == MAP_FAILED)) return -1; ssize_t bytes_read = PREAD (fd, buffer, bytes, offset); @@ -78,6 +80,6 @@ PREADV (int fd, const struct iovec *vector, int count, OFF_T offset) } end: - free (buffer); + __munmap (buffer, bytes); return bytes_read; } diff --git a/sysdeps/posix/pwritev_common.c b/sysdeps/posix/pwritev_common.c index 0383065..3528fd8 100644 --- a/sysdeps/posix/pwritev_common.c +++ b/sysdeps/posix/pwritev_common.c @@ -24,6 +24,7 @@ #include <malloc.h> #include <ldsodefs.h> +#include <libc-pointer-arith.h> /* Write data pointed by the buffers described by IOVEC, which is a vector of COUNT 'struct iovec's, to file descriptor FD at the given @@ -54,8 +55,9 @@ PWRITEV (int fd, const struct iovec *vector, int count, OFF_T offset) but 1. it is system specific (not meant in generic implementation), and 2. it would make the implementation more complex, and 3. it will require another syscall (fcntl). */ - void *buffer = NULL; - if (__posix_memalign (&buffer, GLRO(dl_pagesize), bytes) != 0) + void *buffer = __mmap (NULL, bytes, PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (__glibc_unlikely (buffer == MAP_FAILED)) return -1; /* Copy the data from BUFFER into the memory specified by VECTOR. */ @@ -66,7 +68,7 @@ PWRITEV (int fd, const struct iovec *vector, int count, OFF_T offset) ssize_t ret = PWRITE (fd, buffer, bytes, offset); - free (buffer); + __munmap (buffer, bytes); return ret; } |