Skip to content

Commit 33fcd7c

Browse files
committed
check the handler is used as expected and prevent strange clients from triggering incorrect events
1 parent 089c9fd commit 33fcd7c

8 files changed

Lines changed: 129 additions & 104 deletions

File tree

src/core/connection.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,19 +74,24 @@ static bool connection_event_update(int fd, uint32_t events) {
7474
return res == 0;
7575
}
7676

77-
bool connection_register_write(int fd) {
78-
return connection_event_update(fd, EPOLLOUT | EPOLLHUP);
77+
bool connection_register_write(struct scache_connection* c) {
78+
c->epollout = true;
79+
c->epollin = false;
80+
return connection_event_update(c->client_sock, EPOLLOUT | EPOLLHUP);
7981
}
8082

81-
bool connection_register_read(int fd) {
82-
return connection_event_update(fd, EPOLLIN | EPOLLHUP | EPOLLRDHUP);
83+
bool connection_register_read(struct scache_connection* c) {
84+
c->epollout = false;
85+
c->epollin = true;
86+
return connection_event_update(c->client_sock, EPOLLIN | EPOLLHUP | EPOLLRDHUP);
8387
}
8488

8589
void connection_setup(struct scache_binds cache_binds, struct scache_binds monitor_binds) {
8690
int i;
8791

8892
for (i = 0; i < CONNECTION_HASH_ENTRIES; i++) {
8993
ctable[i].connection.client_sock = -1;
94+
ctable[i].connection.epollin = ctable[i].connection.epollout = false;
9095
}
9196

9297
// Allocate for all listeners
@@ -291,6 +296,7 @@ static scache_connection* connection_add(int fd, listener_type client_type) {
291296

292297
// do last as marks connection slot as used
293298
newNode->connection.client_sock = fd;
299+
newNode->connection.epollout = newNode->connection.epollin = false;
294300

295301
// this is a chained connection
296302
if(node != newNode){
@@ -634,6 +640,7 @@ void connection_event_loop(void (*connection_handler)(scache_connection* connect
634640
DEBUG("[#%d] A new %s socket was accepted %d\n", fd, listener_type_string(client_type), client_sock);
635641
scache_connection* connection = connection_add(client_sock, client_type);
636642
assert(connection->client_sock == client_sock);
643+
connection->epollin = true;
637644
connection_handler(connection);
638645
}
639646
}
@@ -729,6 +736,8 @@ void connection_cleanup_http(scache_connection_node* connection, bool toFree = f
729736
close_fd(fd);
730737
}
731738

739+
connection->connection.epollout = connection->connection.epollin = false;
740+
732741
//Handle chained connections
733742
if (connection->next != NULL) {
734743
connection_cleanup_http(connection->next, true);

src/core/connection.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
#include "config.h"
55
#include "connection_structures.h"
66

7-
bool connection_register_write(int fd);
8-
bool connection_register_read(int fd);
7+
bool connection_register_write(struct scache_connection* c);
8+
bool connection_register_read(struct scache_connection* c);
99
int connection_open_listener(struct scache_bind bind);
1010
void connection_close_listeners();
1111
void connection_event_loop(void(*connection_handler)(scache_connection* connection));
@@ -17,11 +17,14 @@ bool connection_stop_soon();
1717

1818
void close_fd(int fd);
1919

20+
#define CONNECTION_HANDLER_ACTUAL(con, value) (con)->handler = (value)
2021
#define _DEBUG_CONNECTION_HANDLER
2122
#ifdef DEBUG_CONNECTION_HANDLER
2223
#define CONNECTION_HANDLER(con, value) printf("Setting connection handler to " #value "\n"); (con)->handler = (value)
24+
#elif defined(DEBUG_BUILD)
25+
#define CONNECTION_HANDLER(con, value) (con)->handler_name=#value;CONNECTION_HANDLER_ACTUAL(con, value)
2326
#else
24-
#define CONNECTION_HANDLER(con, value) (con)->handler = (value)
27+
#define CONNECTION_HANDLER(con, value) CONNECTION_HANDLER_ACTUAL(con, value)
2528
#endif
2629

2730
#define CONNECTION_HASH_KEY(x) (x)%CONNECTION_HASH_ENTRIES

src/core/connection_structures.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,17 @@ struct scache_connection {
3636
int output_length;
3737
char* output_buffer_free;
3838
state_action(*handler)(scache_connection* connection);
39+
#ifdef DEBUG_BUILD
40+
const char* handler_name;
41+
#endif
3942
uint32_t state;
4043
int client_sock;
4144
struct read_buffer input;
4245

43-
unsigned int type : 15;
44-
unsigned int writing : 1;
46+
uint16_t method;
47+
bool cache_writing,
48+
epollin,
49+
epollout;
4550

4651
listener_type ltype;
4752

src/core/http.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,14 +76,19 @@ state_action http_read_handle(scache_connection* connection) {
7676
state_action run;
7777
int to_end = -1, to_end_old;
7878
do {
79+
if(!connection->epollin) break;
7980
run = http_read_handle_state(connection);
8081
to_end_old = to_end;
8182
to_end = rbuf_read_remaining(&connection->input);
8283
} while (run == needs_more_read && to_end != 0 && to_end != to_end_old);
8384

8485
//Handle buffer is full, not being processed
8586
if (num == 0 && rbuf_write_remaining(&connection->input) == 0) {
86-
WARN("Buffer full, not processed, disconnecting.");
87+
const char* handling = "<unknown>";
88+
#ifdef DEBUG_BUILD
89+
handling = connection->handler_name;
90+
#endif
91+
WARN("Buffer overlowed while handling %s (epollin=%d), will disconnect", handling, connection->epollin);
8792
return close_connection;
8893
}
8994

@@ -128,7 +133,7 @@ state_action http_write_handle(scache_connection* connection) {
128133
}
129134

130135
state_action run = continue_processing;
131-
if (connection->output_buffer == NULL) {
136+
if (connection->output_buffer == NULL && connection->epollout) {
132137
// do {
133138
run = http_write_handle_state(connection);
134139
// } while (run == needs_more_write);

src/core/http_parse.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ state_action http_read_eoltoend(scache_connection* connection, char* buffer, int
8282
// register a handler to write the output (and then the request is over)
8383
connection->state = 0;
8484
CONNECTION_HANDLER(connection, http_respond_writeonly);
85-
bool res = connection_register_write(connection->client_sock);
85+
bool res = connection_register_write(connection);
8686

8787
if (!res) {
8888
return close_connection;
@@ -114,7 +114,7 @@ state_action http_handle_eolwritetoend(scache_connection* connection) {
114114

115115
state_action http_discard_input(scache_connection* connection) {
116116
//todo discard from readbuffer
117-
connection_register_read(connection->client_sock);
117+
connection_register_read(connection);
118118
rbuf_read_to_end(&connection->input);
119119
return continue_processing;
120120
}

0 commit comments

Comments
 (0)