Fix select decoding for glibc in _FORTIFY_SOURCE mode

glibc in _FORTIFY_SOURCE mode raises SIGABRT when descriptor greater
or equal to FD_SETSIZE is passed to FD_ISSET.  Select family syscalls,
however, can legitimately accept such descriptors.  To overcome this
limitation, we have to replace FD_ISSET with an equivalent that imposes
no such restrictions.

* desc.c (fd_isset): New function.
(decode_select): Use it instead of FD_ISSET.
This commit is contained in:
Дмитрий Левин 2013-11-05 23:00:22 +00:00
parent f3696b3c8b
commit c2982b5b72

12
desc.c
View File

@ -477,6 +477,14 @@ sys_getdtablesize(struct tcb *tcp)
}
#endif
static int
fd_isset(int d, fd_set *fds)
{
const int bpl = 8 * sizeof(long);
long *s = (long *) fds;
return !!(s[d / bpl] & (1L << (d % bpl)));
}
static int
decode_select(struct tcb *tcp, long *args, enum bitness_t bitness)
{
@ -528,7 +536,7 @@ decode_select(struct tcb *tcp, long *args, enum bitness_t bitness)
}
tprints(", [");
for (j = 0, sep = ""; j < nfds; j++) {
if (FD_ISSET(j, fds)) {
if (fd_isset(j, fds)) {
tprints(sep);
printfd(tcp, j);
sep = " ";
@ -568,7 +576,7 @@ decode_select(struct tcb *tcp, long *args, enum bitness_t bitness)
if (!arg || umoven(tcp, arg, fdsize, (char *) fds) < 0)
continue;
for (j = 0; j < nfds; j++) {
if (FD_ISSET(j, fds)) {
if (fd_isset(j, fds)) {
/* +2 chars needed at the end: ']',NUL */
if (outptr < end_outstr - (sizeof(", except [") + sizeof(int)*3 + 2)) {
if (first) {