Reputation: 491
I am writing a shared library that overrides some syscalls. Among them is the read(int fd, void *buf, size_t count)
syscall. This library is, of course, in User Space.
So, in my library, I'm catching the read()
call from the application (which uses LD_PRELOAD
to preload my lib), do a bunch of things and, at some point, write data to the application buffer (void *buf
).
Is there a way for me to check whether the whole application buffer is writable?
Most of the time it is not an issue but I've come across applications that were so poorly written that they would post read-only buffer in their read()
call, leading to a segfault in my code when I'm performing a memcpy()
with their buffer as destination, which makes sense, of course.
Note 1: I'm currently having a look at how the Kernel is handling that situation in the actual sys_read()
in fs/read_write.c
but it's not that trivial to understand.
Note 2: The solution should add as little overhead as possible.
Upvotes: 0
Views: 310
Reputation: 1572
This is a tweak of @R. response to mitigate performance hit.
It is not necessary to keep opening and closing /dev/zero. Just open it once and leave it open. Then, every time you are attempting to do a read, just read one byte to find out if the buffer is writable.
#include <sys/types.h>
#include <sys/fcntl.h>
#include <unistd.h>
int
check_writable(char *buf)
{
static int fd;
int r;
if (fd == 0) {
fd = open("/dev/zero", O_RDONLY);
}
r = read(fd, buf, 1);
if (r != 1) {
return(0);
}
return(1);
}
int
main()
{
char *s, wr[8], *rd = "read-only buf";
int j, r;
for (j = 0; j < 2; j++) {
if (j == 0) {
s = rd;
}
else {
s = wr;
}
r = check_writable(s);
if (r == 0) {
printf("read-only buffer\n");
}
else {
printf("writable buffer\n");
}
}
}
Upvotes: 0
Reputation: 215193
Try this:
int fd = open("/dev/zero", O_RDONLY);
ssize_t ret = read(fd, dest, amt_to_write);
int err = errno;
close(fd);
if (ret<0 && err==EFAULT) ...
Upvotes: 1