aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>2017-11-22 18:02:20 -0200
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>2017-11-24 12:16:15 -0200
commitc45d78aac47db08bc8ea7641c5330cccaecd3ddb (patch)
tree769aca2259f4781214044cb87e1d326955bc866e
parent3ffc4cc1ad37fb36e419c9a3a72e1916d7d893d3 (diff)
downloadglibc-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.
-rw-r--r--ChangeLog7
-rw-r--r--sysdeps/posix/preadv_common.c8
-rw-r--r--sysdeps/posix/pwritev_common.c8
3 files changed, 17 insertions, 6 deletions
diff --git a/ChangeLog b/ChangeLog
index e60983a..6791c51 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2017-11-24 Adhemerval Zanella <adhemerval.zanella@linaro.org>
+
+ [BZ #22457]
+ * sysdeps/posix/preadv_common.c (PREADV): Use mmap/munmap instead of
+ posix_memalign/free.
+ * sysdeps/posix/pwritev_common.c (PWRITEV): Likewise.
+
2017-11-22 Mike FABIAN <mfabian@redhat.com>
[BZ #22469]
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;
}