Skip to content

Commit 00b3c78

Browse files
penguin359apconole
authored andcommitted
Protect uses of select() from crash on too many file descriptors
The fd_set macros don't check for overflow and will cause an out-of-bounds access when given a file description >= FD_SETSIZE (1024) This doesn't fix the fundamental issue, but prevents a crash and should allow partial functionality. The full fix requires switching to poll() instead. Signed-off-by: "Loren M. Lang" <loren.lang@intel.com> Signed-off-by: Aaron Conole <aconole@redhat.com>
1 parent 1e56468 commit 00b3c78

1 file changed

Lines changed: 27 additions & 2 deletions

File tree

eloop.c

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,17 @@ static void eloop_sock_table_remove_sock(struct eloop_sock_table *table,
180180
}
181181

182182

183+
static inline void warn_too_many_fds()
184+
{
185+
static bool warned = false;
186+
187+
if (!warned) {
188+
fprintf(stderr, "unable to handle more than %d file descriptors\n", FD_SETSIZE);
189+
fprintf(stderr, "too many interfaces being watched\n");
190+
warned = true;
191+
}
192+
}
193+
183194
static void eloop_sock_table_set_fds(struct eloop_sock_table *table,
184195
fd_set *fds)
185196
{
@@ -190,8 +201,13 @@ static void eloop_sock_table_set_fds(struct eloop_sock_table *table,
190201
if (table->table == NULL)
191202
return;
192203

193-
for (i = 0; i < table->count; i++)
204+
for (i = 0; i < table->count; i++) {
205+
if (table->table[i].sock >= FD_SETSIZE) {
206+
warn_too_many_fds();
207+
continue;
208+
}
194209
FD_SET(table->table[i].sock, fds);
210+
}
195211
}
196212

197213

@@ -205,6 +221,9 @@ static void eloop_sock_table_dispatch(struct eloop_sock_table *table,
205221

206222
table->changed = 0;
207223
for (i = 0; i < table->count; i++) {
224+
if (table->table[i].sock >= FD_SETSIZE) {
225+
return;
226+
}
208227
if (FD_ISSET(table->table[i].sock, fds)) {
209228
table->table[i].handler(table->table[i].sock,
210229
table->table[i].eloop_data,
@@ -497,7 +516,8 @@ void eloop_run(void)
497516
eloop_sock_table_set_fds(&eloop.readers, rfds);
498517
eloop_sock_table_set_fds(&eloop.writers, wfds);
499518
eloop_sock_table_set_fds(&eloop.exceptions, efds);
500-
res = select(eloop.max_sock + 1, rfds, wfds, efds,
519+
res = select(eloop.max_sock < FD_SETSIZE ? eloop.max_sock + 1 : FD_SETSIZE,
520+
rfds, wfds, efds,
501521
eloop.timeout ? &_tv : NULL);
502522
if (res < 0 && errno != EINTR && errno != 0) {
503523
perror("select");
@@ -571,6 +591,11 @@ void eloop_wait_for_read_sock(int sock)
571591
if (sock < 0)
572592
return;
573593

594+
if (sock >= FD_SETSIZE) {
595+
warn_too_many_fds();
596+
return;
597+
}
598+
574599
FD_ZERO(&rfds);
575600
FD_SET(sock, &rfds);
576601
select(sock + 1, &rfds, NULL, NULL, NULL);

0 commit comments

Comments
 (0)