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.
This commit is contained in:
Adhemerval Zanella 2017-11-22 18:02:20 -02:00
parent 3ffc4cc1ad
commit c45d78aac4
3 changed files with 17 additions and 6 deletions

View File

@ -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> 2017-11-22 Mike FABIAN <mfabian@redhat.com>
[BZ #22469] [BZ #22469]

View File

@ -24,6 +24,7 @@
#include <malloc.h> #include <malloc.h>
#include <ldsodefs.h> #include <ldsodefs.h>
#include <libc-pointer-arith.h>
/* Read data from file descriptor FD at the given position OFFSET /* Read data from file descriptor FD at the given position OFFSET
without change the file pointer, and put the result in the buffers 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 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 2. it would make the implementation more complex, and 3. it will require
another syscall (fcntl). */ another syscall (fcntl). */
void *buffer = NULL; void *buffer = __mmap (NULL, bytes, PROT_READ | PROT_WRITE,
if (__posix_memalign (&buffer, GLRO(dl_pagesize), bytes) != 0) MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (__glibc_unlikely (buffer == MAP_FAILED))
return -1; return -1;
ssize_t bytes_read = PREAD (fd, buffer, bytes, offset); 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: end:
free (buffer); __munmap (buffer, bytes);
return bytes_read; return bytes_read;
} }

View File

@ -24,6 +24,7 @@
#include <malloc.h> #include <malloc.h>
#include <ldsodefs.h> #include <ldsodefs.h>
#include <libc-pointer-arith.h>
/* Write data pointed by the buffers described by IOVEC, which is a /* 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 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 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 2. it would make the implementation more complex, and 3. it will require
another syscall (fcntl). */ another syscall (fcntl). */
void *buffer = NULL; void *buffer = __mmap (NULL, bytes, PROT_WRITE,
if (__posix_memalign (&buffer, GLRO(dl_pagesize), bytes) != 0) MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (__glibc_unlikely (buffer == MAP_FAILED))
return -1; return -1;
/* Copy the data from BUFFER into the memory specified by VECTOR. */ /* 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); ssize_t ret = PWRITE (fd, buffer, bytes, offset);
free (buffer); __munmap (buffer, bytes);
return ret; return ret;
} }