/* PGRP of process */
Int VG_(main_pgrp);
-/* Maximum allowed application-visible file descriptor */
-Int VG_(max_fd) = -1;
+/* Application-visible file descriptor limits */
+Int VG_(fd_soft_limit) = -1;
+Int VG_(fd_hard_limit) = -1;
/* As deduced from esp_at_startup, the client's argc, argv[] and
envp[] as extracted from the client's stack at startup-time. */
}
/* Move log_fd into the safe range, so it doesn't conflict with any app fds */
- eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(max_fd)+1);
+ eventually_log_fd = VG_(fcntl)(VG_(clo_log_fd), VKI_F_DUPFD, VG_(fd_hard_limit));
if (eventually_log_fd < 0)
VG_(message)(Vg_UserMsg, "valgrind: failed to move logfile fd into safe range");
else {
}
/* Reserve some file descriptors for our use. */
- VG_(max_fd) = rl.rlim_cur - VG_N_RESERVED_FDS;
+ VG_(fd_soft_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
+ VG_(fd_hard_limit) = rl.rlim_cur - VG_N_RESERVED_FDS;
/* Update the soft limit. */
VG_(setrlimit)(VKI_RLIMIT_NOFILE, &rl);
//--------------------------------------------------------------
// Process Valgrind's + tool's command-line options
// p: load_tool() [for 'tool']
- // p: setup_file_descriptors() [for 'VG_(max_fd)']
+ // p: setup_file_descriptors() [for 'VG_(fd_xxx_limit)']
// p: sk_pre_clo_init [to set 'command_line_options' need]
//--------------------------------------------------------------
process_cmd_line_options(client_auxv, tool);
{
OpenFd *i = allocated_fds;
- if (fd > VG_(max_fd))
+ if (fd >= VG_(fd_hard_limit))
return; /* Valgrind internal */
while(i) {
{
OpenFd *i;
- if (fd > VG_(max_fd))
+ if (fd >= VG_(fd_hard_limit))
return; /* Valgrind internal */
/* Check to see if this fd is already open. */
------------------------------------------------------------------ */
/* Return true if we're allowed to use or create this fd */
-static Bool fd_allowed(Int fd, const Char *syscall, ThreadId tid)
+static Bool fd_allowed(Int fd, const Char *syscall, ThreadId tid, Bool soft)
{
- if (fd < 0 || fd > VG_(max_fd) || fd == VG_(clo_log_fd)) {
+ if (fd < 0 || fd >= VG_(fd_hard_limit) || fd == VG_(clo_log_fd)) {
VG_(message)(Vg_UserMsg,
"Warning: invalid file descriptor %d in syscall %s()",
fd, syscall);
}
return False;
}
+ else if (soft && fd >= VG_(fd_soft_limit)) {
+ return False;
+ }
return True;
}
/* int close(int fd); */
MAYBE_PRINTF("close ( %d )\n",arg1);
/* Detect and negate attempts by the client to close Valgrind's log fd */
- if (!fd_allowed(arg1, "close", tid))
+ if (!fd_allowed(arg1, "close", tid, False))
res = -VKI_EBADF;
}
POST(dup)
{
MAYBE_PRINTF("%d\n", res);
- if (!fd_allowed(res, "dup", tid)) {
+ if (!fd_allowed(res, "dup", tid, True)) {
VG_(close)(res);
res = -VKI_EMFILE;
} else {
{
/* int dup2(int oldfd, int newfd); */
MAYBE_PRINTF("dup2 ( %d, %d ) ...\n", arg1,arg2);
- if (!fd_allowed(arg2, "dup2", tid))
+ if (!fd_allowed(arg2, "dup2", tid, True))
res = -VKI_EBADF;
}
POST(fcntl)
{
if (arg2 == VKI_F_DUPFD) {
- if (!fd_allowed(res, "fcntl(DUPFD)", tid)) {
+ if (!fd_allowed(res, "fcntl(DUPFD)", tid, True)) {
VG_(close)(res);
res = -VKI_EMFILE;
} else {
POST(fcntl64)
{
if (arg2 == VKI_F_DUPFD) {
- if (!fd_allowed(res, "fcntl64(DUPFD)", tid)) {
+ if (!fd_allowed(res, "fcntl64(DUPFD)", tid, True)) {
VG_(close)(res);
res = -VKI_EMFILE;
} else {
switch(arg1) {
case VKI_RLIMIT_NOFILE:
- ((vki_rlimit *)arg2)->rlim_cur = VG_(max_fd);
+ ((vki_rlimit *)arg2)->rlim_cur = VG_(fd_soft_limit);
+ ((vki_rlimit *)arg2)->rlim_max = VG_(fd_hard_limit);
break;
case VKI_RLIMIT_DATA:
POST(open)
{
- if (!fd_allowed(res, "open", tid)) {
+ if (!fd_allowed(res, "open", tid, True)) {
VG_(close)(res);
res = -VKI_EMFILE;
} else {
/* size_t read(int fd, void *buf, size_t count); */
MAYBE_PRINTF("read ( %d, %p, %d )\n", arg1, arg2, arg3);
- if (!fd_allowed(arg1, "read", tid))
+ if (!fd_allowed(arg1, "read", tid, False))
res = -VKI_EBADF;
}
{
/* size_t write(int fd, const void *buf, size_t count); */
MAYBE_PRINTF("write ( %d, %p, %d )\n", arg1, arg2, arg3);
- if (!fd_allowed(arg1, "write", tid))
+ if (!fd_allowed(arg1, "write", tid, False))
res = -VKI_EBADF;
else
SYSCALL_TRACK( pre_mem_read, tid, "write(buf)", arg2, arg3 );
POST(creat)
{
- if (!fd_allowed(res, "creat", tid)) {
+ if (!fd_allowed(res, "creat", tid, True)) {
VG_(close)(res);
res = -VKI_EMFILE;
} else {
{
Int *p = (Int *)arg1;
- if (!fd_allowed(p[0], "pipe", tid) ||
- !fd_allowed(p[1], "pipe", tid)) {
+ if (!fd_allowed(p[0], "pipe", tid, True) ||
+ !fd_allowed(p[1], "pipe", tid, True)) {
VG_(close)(p[0]);
VG_(close)(p[1]);
res = -VKI_EMFILE;
POST(epoll_create)
{
- if (!fd_allowed(res, "open", tid)) {
+ if (!fd_allowed(res, "open", tid, True)) {
VG_(close)(res);
res = -VKI_EMFILE;
} else {
Int i;
struct iovec * vec;
MAYBE_PRINTF("readv ( %d, %p, %d )\n",arg1,arg2,arg3);
- if (!fd_allowed(arg1, "readv", tid)) {
+ if (!fd_allowed(arg1, "readv", tid, False)) {
res = -VKI_EBADF;
} else {
SYSCALL_TRACK( pre_mem_read, tid, "readv(vector)",
SYSCALL_TRACK( pre_mem_read, tid, "setrlimit(rlim)",
arg2, sizeof(struct vki_rlimit) );
- if (arg1 == VKI_RLIMIT_DATA) {
+ if (arg1 == VKI_RLIMIT_NOFILE) {
+ if (((vki_rlimit *)arg2)->rlim_cur > VG_(fd_hard_limit) ||
+ ((vki_rlimit *)arg2)->rlim_max != VG_(fd_hard_limit)) {
+ res = -VKI_EPERM;
+ }
+ else {
+ VG_(fd_soft_limit) = ((vki_rlimit *)arg2)->rlim_cur;
+ res = 0;
+ }
+ }
+ else if (arg1 == VKI_RLIMIT_DATA) {
VG_(client_rlimit_data) = *(vki_rlimit *)arg2;
res = 0;
}
Int fd1 = ((UInt*)((UInt*)arg2)[3])[0];
Int fd2 = ((UInt*)((UInt*)arg2)[3])[1];
VG_TRACK( post_mem_write, ((UInt*)arg2)[3], 2*sizeof(int) );
- if (!fd_allowed(fd1, "socketcall.socketpair", tid) ||
- !fd_allowed(fd2, "socketcall.socketpair", tid)) {
+ if (!fd_allowed(fd1, "socketcall.socketpair", tid, True) ||
+ !fd_allowed(fd2, "socketcall.socketpair", tid, True)) {
VG_(close)(fd1);
VG_(close)(fd2);
res = -VKI_EMFILE;
}
case SYS_SOCKET:
- if (!fd_allowed(res, "socket", tid)) {
+ if (!fd_allowed(res, "socket", tid, True)) {
VG_(close)(res);
res = -VKI_EMFILE;
} else {
case SYS_ACCEPT: {
/* int accept(int s, struct sockaddr *addr, int *addrlen); */
- if (!fd_allowed(res, "accept", tid)) {
+ if (!fd_allowed(res, "accept", tid, True)) {
VG_(close)(res);
res = -VKI_EMFILE;
} else {
Int i;
struct iovec * vec;
MAYBE_PRINTF("writev ( %d, %p, %d )\n",arg1,arg2,arg3);
- if (!fd_allowed(arg1, "writev", tid)) {
+ if (!fd_allowed(arg1, "writev", tid, False)) {
res = -VKI_EBADF;
} else {
SYSCALL_TRACK( pre_mem_read, tid, "writev(vector)",
if (!VG_(is_kerror)(res)) {
VG_TRACK( post_mem_write, arg1, sizeof(int) );
if (arg2 == VKI_FUTEX_FD) {
- if (!fd_allowed(res, "futex", tid)) {
+ if (!fd_allowed(res, "futex", tid, True)) {
VG_(close)(res);
- res = -VKI_ENFILE;
+ res = -VKI_EMFILE;
} else {
if (VG_(clo_track_fds))
record_fd_open(tid, res, VG_(arena_strdup)(VG_AR_CORE, (Char*)arg1));