Assure that no large file descriptors are passed to FD_SET().
authorFlorian Forster <ff@octo.it>
Thu, 4 May 2017 11:57:22 +0000 (13:57 +0200)
committerFlorian Forster <ff@octo.it>
Thu, 4 May 2017 12:06:13 +0000 (14:06 +0200)
When passing a large file descriptor, on many systems large means >= 1024,
FD_SET()s behavior is undefined. Mostly, it will corrupt the stack
because an out-of-bounds bit is flipped.

src/liboping.c

index f8c5bfb..fc9ed65 100644 (file)
@@ -694,6 +694,7 @@ static int ping_receive_all (pingobj_t *obj)
                        if (!timerisset (ptr->timer))
                                continue;
 
+                       assert (ptr->fd < FD_SETSIZE);
                        FD_SET (ptr->fd, &read_fds);
                        FD_SET (ptr->fd, &err_fds);
                        num_fds++;
@@ -1481,6 +1482,16 @@ int ping_host_add (pingobj_t *obj, const char *host)
                        ping_set_errno (obj, errno);
                        continue;
                }
+               else if (ph->fd >= FD_SETSIZE)
+               {
+                       dprintf("socket(2) returned file descriptor %d, which is above the file "
+                               "descriptor limit for select(2) (FD_SETSIZE = %d)\n",
+                               ph->fd, FD_SETSIZE);
+                       close(ph->fd);
+                       ph->fd = -1;
+                       ping_set_errno(obj, EMFILE);
+                       continue;
+               }
 
                if (obj->srcaddr != NULL)
                {