From: Wouter Wijngaards Date: Fri, 5 Oct 2007 08:05:06 +0000 (+0000) Subject: fptr whitelist network code callbacks. X-Git-Tag: release-0.6~85 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9a60182c86324548f6cf6edbe4e4f2f53ac91ca3;p=thirdparty%2Funbound.git fptr whitelist network code callbacks. git-svn-id: file:///svn/unbound/trunk@659 be551aaa-1e26-0410-a405-d3ace91eadb9 --- diff --git a/checkconf/worker_cb.c b/checkconf/worker_cb.c index 84f95d313..a83e283e5 100644 --- a/checkconf/worker_cb.c +++ b/checkconf/worker_cb.c @@ -61,6 +61,22 @@ int worker_handle_request(struct comm_point* ATTR_UNUSED(c), return 0; } +int worker_handle_reply(struct comm_point* ATTR_UNUSED(c), + void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), + struct comm_reply* ATTR_UNUSED(reply_info)) +{ + log_assert(0); + return 0; +} + +int worker_handle_service_reply(struct comm_point* ATTR_UNUSED(c), + void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), + struct comm_reply* ATTR_UNUSED(reply_info)) +{ + log_assert(0); + return 0; +} + void worker_sighandler(int ATTR_UNUSED(sig), void* ATTR_UNUSED(arg)) { log_assert(0); diff --git a/daemon/worker.c b/daemon/worker.c index 1d69aac4d..cf4e91917 100644 --- a/daemon/worker.c +++ b/daemon/worker.c @@ -174,8 +174,7 @@ worker_send_cmd(struct worker* worker, ldns_buffer* buffer, log_err("write socket: %s", strerror(errno)); } -/** process incoming replies from the network */ -static int +int worker_handle_reply(struct comm_point* c, void* arg, int error, struct comm_reply* reply_info) { @@ -206,8 +205,7 @@ worker_handle_reply(struct comm_point* c, void* arg, int error, return 0; } -/** process incoming serviced query replies from the network */ -static int +int worker_handle_service_reply(struct comm_point* c, void* arg, int error, struct comm_reply* reply_info) { diff --git a/daemon/worker.h b/daemon/worker.h index fa92bedb9..de30e935c 100644 --- a/daemon/worker.h +++ b/daemon/worker.h @@ -206,4 +206,12 @@ int worker_handle_control_cmd(struct comm_point* c, void* arg, int error, int worker_handle_request(struct comm_point* c, void* arg, int error, struct comm_reply* repinfo); +/** process incoming replies from the network */ +int worker_handle_reply(struct comm_point* c, void* arg, int error, + struct comm_reply* reply_info); + +/** process incoming serviced query replies from the network */ +int worker_handle_service_reply(struct comm_point* c, void* arg, int error, + struct comm_reply* reply_info); + #endif /* DAEMON_WORKER_H */ diff --git a/doc/Changelog b/doc/Changelog index 8883edfc4..b289b6387 100644 --- a/doc/Changelog +++ b/doc/Changelog @@ -1,3 +1,6 @@ +5 October 2007: Wouter + - function pointer whitelist. + 4 October 2007: Wouter - overwrite sensitive random seed value after use. - switch to logfile very soon if not -d (console attached). diff --git a/services/outside_network.c b/services/outside_network.c index b05b9e482..0ba80457a 100644 --- a/services/outside_network.c +++ b/services/outside_network.c @@ -50,6 +50,7 @@ #include "util/log.h" #include "util/net_help.h" #include "util/random.h" +#include "util/fptr_wlist.h" #ifdef HAVE_SYS_TYPES_H # include @@ -62,9 +63,6 @@ /** number of retries on outgoing UDP queries */ #define OUTBOUND_UDP_RETRY 4 -/** callback for serviced query UDP answers */ -static int serviced_udp_callback(struct comm_point* c, void* arg, int error, - struct comm_reply* rep); /** initiate TCP transaction for serviced query */ static void serviced_tcp_initiate(struct outside_network* outnet, struct serviced_query* sq, ldns_buffer* buff); @@ -176,6 +174,7 @@ use_free_buffer(struct outside_network* outnet) comm_point_callback_t* cb = w->cb; void* cb_arg = w->cb_arg; waiting_tcp_delete(w); + log_assert(fptr_whitelist_pending_tcp(cb)); (void)(*cb)(NULL, cb_arg, NETEVENT_CLOSED, NULL); } } @@ -194,8 +193,7 @@ decomission_pending_tcp(struct outside_network* outnet, use_free_buffer(outnet); } -/** callback for pending tcp connections */ -static int +int outnet_tcp_cb(struct comm_point* c, void* arg, int error, struct comm_reply *reply_info) { @@ -214,6 +212,7 @@ outnet_tcp_cb(struct comm_point* c, void* arg, int error, error = NETEVENT_CLOSED; } } + log_assert(fptr_whitelist_pending_tcp(pend->query->cb)); (void)(*pend->query->cb)(c, pend->query->cb_arg, error, reply_info); decomission_pending_tcp(outnet, pend); return 0; @@ -272,6 +271,7 @@ outnet_udp_cb(struct comm_point* c, void* arg, int error, verbose(VERB_ALGO, "outnet handle udp reply"); /* delete from tree first in case callback creates a retry */ (void)rbtree_delete(outnet->pending, p->node.key); + log_assert(fptr_whitelist_pending_udp(p->cb)); (void)(*p->cb)(p->c, p->cb_arg, NETEVENT_NOERROR, reply_info); pending_delete(NULL, p); return 0; @@ -386,6 +386,7 @@ pending_udp_timer_cb(void *arg) struct pending* p = (struct pending*)arg; /* it timed out */ verbose(VERB_ALGO, "timeout udp"); + log_assert(fptr_whitelist_pending_udp(p->cb)); (void)(*p->cb)(p->c, p->cb_arg, NETEVENT_TIMEOUT, NULL); pending_delete(p->outnet, p); } @@ -738,6 +739,7 @@ outnet_tcptimer(void* arg) cb = w->cb; cb_arg = w->cb_arg; waiting_tcp_delete(w); + log_assert(fptr_whitelist_pending_tcp(cb)); (void)(*cb)(NULL, cb_arg, NETEVENT_TIMEOUT, NULL); use_free_buffer(outnet); } @@ -1003,6 +1005,7 @@ serviced_callbacks(struct serviced_query* sq, int error, struct comm_point* c, ldns_buffer_write(c->buffer, backup_p, backlen); ldns_buffer_flip(c->buffer); } + log_assert(fptr_whitelist_serviced_query(p->cb)); (void)(*p->cb)(c, p->cb_arg, error, rep); p = n; } @@ -1015,8 +1018,7 @@ serviced_callbacks(struct serviced_query* sq, int error, struct comm_point* c, serviced_delete(sq); } -/** TCP reply or error callback for serviced queries */ -static int +int serviced_tcp_callback(struct comm_point* c, void* arg, int error, struct comm_reply* rep) { @@ -1063,7 +1065,7 @@ serviced_tcp_initiate(struct outside_network* outnet, } } -static int +int serviced_udp_callback(struct comm_point* c, void* arg, int error, struct comm_reply* rep) { diff --git a/services/outside_network.h b/services/outside_network.h index 5350bf411..28e775598 100644 --- a/services/outside_network.h +++ b/services/outside_network.h @@ -373,10 +373,22 @@ size_t serviced_get_mem(struct serviced_query* sq); int outnet_udp_cb(struct comm_point* c, void* arg, int error, struct comm_reply *reply_info); +/** callback for pending tcp connections */ +int outnet_tcp_cb(struct comm_point* c, void* arg, int error, + struct comm_reply *reply_info); + /** callback for udp timeout */ void pending_udp_timer_cb(void *arg); /** callback for outgoing TCP timer event */ void outnet_tcptimer(void* arg); +/** callback for serviced query UDP answers */ +int serviced_udp_callback(struct comm_point* c, void* arg, int error, + struct comm_reply* rep); + +/** TCP reply or error callback for serviced queries */ +int serviced_tcp_callback(struct comm_point* c, void* arg, int error, + struct comm_reply* rep); + #endif /* OUTSIDE_NETWORK_H */ diff --git a/testcode/fake_event.c b/testcode/fake_event.c index 4d3c3aaf9..12ca2013e 100644 --- a/testcode/fake_event.c +++ b/testcode/fake_event.c @@ -968,6 +968,14 @@ int outnet_udp_cb(struct comm_point* ATTR_UNUSED(c), return 0; } +int outnet_tcp_cb(struct comm_point* ATTR_UNUSED(c), + void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), + struct comm_reply *ATTR_UNUSED(reply_info)) +{ + log_assert(0); + return 0; +} + void pending_udp_timer_cb(void *ATTR_UNUSED(arg)) { log_assert(0); @@ -978,4 +986,56 @@ void outnet_tcptimer(void* ATTR_UNUSED(arg)) log_assert(0); } +void comm_point_udp_callback(int ATTR_UNUSED(fd), short ATTR_UNUSED(event), + void* ATTR_UNUSED(arg)) +{ + log_assert(0); +} + +void comm_point_tcp_accept_callback(int ATTR_UNUSED(fd), + short ATTR_UNUSED(event), void* ATTR_UNUSED(arg)) +{ + log_assert(0); +} + +void comm_point_tcp_handle_callback(int ATTR_UNUSED(fd), + short ATTR_UNUSED(event), void* ATTR_UNUSED(arg)) +{ + log_assert(0); +} + +void comm_timer_callback(int ATTR_UNUSED(fd), + short ATTR_UNUSED(event), void* ATTR_UNUSED(arg)) +{ + log_assert(0); +} + +void comm_signal_callback(int ATTR_UNUSED(fd), + short ATTR_UNUSED(event), void* ATTR_UNUSED(arg)) +{ + log_assert(0); +} + +void comm_point_local_handle_callback(int ATTR_UNUSED(fd), + short ATTR_UNUSED(event), void* ATTR_UNUSED(arg)) +{ + log_assert(0); +} + +int serviced_udp_callback(struct comm_point* ATTR_UNUSED(c), + void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), + struct comm_reply* ATTR_UNUSED(reply_info)) +{ + log_assert(0); + return 0; +} + +int serviced_tcp_callback(struct comm_point* ATTR_UNUSED(c), + void* ATTR_UNUSED(arg), int ATTR_UNUSED(error), + struct comm_reply* ATTR_UNUSED(reply_info)) +{ + log_assert(0); + return 0; +} + /*********** End of Dummy routines ***********/ diff --git a/util/fptr_wlist.c b/util/fptr_wlist.c index 0a45684be..4de74785e 100644 --- a/util/fptr_wlist.c +++ b/util/fptr_wlist.c @@ -51,17 +51,16 @@ int fptr_whitelist_comm_point(comm_point_callback_t *fptr) { - return 1; - if(fptr == &worker_handle_control_cmd) return 1; - else if(fptr == &worker_handle_request) return 1; + if(fptr == &worker_handle_request) return 1; else if(fptr == &outnet_udp_cb) return 1; + else if(fptr == &outnet_tcp_cb) return 1; + else if(fptr == &worker_handle_control_cmd) return 1; return 0; } int fptr_whitelist_comm_timer(void (*fptr)(void*)) { - return 1; if(fptr == &pending_udp_timer_cb) return 1; else if(fptr == &outnet_tcptimer) return 1; return 0; @@ -70,7 +69,6 @@ fptr_whitelist_comm_timer(void (*fptr)(void*)) int fptr_whitelist_comm_signal(void (*fptr)(int, void*)) { - return 1; if(fptr == &worker_sighandler) return 1; return 0; } @@ -78,5 +76,34 @@ fptr_whitelist_comm_signal(void (*fptr)(int, void*)) int fptr_whitelist_event(void (*fptr)(int, short, void *)) { + if(fptr == &comm_point_udp_callback) return 1; + else if(fptr == &comm_point_tcp_accept_callback) return 1; + else if(fptr == &comm_point_tcp_handle_callback) return 1; + else if(fptr == &comm_timer_callback) return 1; + else if(fptr == &comm_signal_callback) return 1; + else if(fptr == &comm_point_local_handle_callback) return 1; + return 0; +} + +int +fptr_whitelist_pending_udp(comm_point_callback_t *fptr) +{ + if(fptr == &serviced_udp_callback) return 1; + else if(fptr == &worker_handle_reply) return 1; + return 0; +} + +int +fptr_whitelist_pending_tcp(comm_point_callback_t *fptr) +{ + if(fptr == &serviced_tcp_callback) return 1; + else if(fptr == &worker_handle_reply) return 1; + return 0; +} + +int +fptr_whitelist_serviced_query(comm_point_callback_t *fptr) +{ + if(fptr == &worker_handle_service_reply) return 1; return 0; } diff --git a/util/fptr_wlist.h b/util/fptr_wlist.h index 5e0577787..5f48b06bd 100644 --- a/util/fptr_wlist.h +++ b/util/fptr_wlist.h @@ -87,4 +87,32 @@ int fptr_whitelist_comm_signal(void (*fptr)(int, void*)); */ int fptr_whitelist_event(void (*fptr)(int, short, void *)); +/** + * Check function pointer whitelist for pending udp callback values. + * This is not called by libevent itself, but checked by netevent. + * + * @param fptr: function pointer to check. + * @return false if not in whitelist. + */ +int fptr_whitelist_pending_udp(comm_point_callback_t *fptr); + +/** + * Check function pointer whitelist for pending tcp callback values. + * This is not called by libevent itself, but checked by netevent. + * + * @param fptr: function pointer to check. + * @return false if not in whitelist. + */ +int fptr_whitelist_pending_tcp(comm_point_callback_t *fptr); + +/** + * Check function pointer whitelist for serviced query callback values. + * This is not called by libevent itself, but checked by netevent. + * + * @param fptr: function pointer to check. + * @return false if not in whitelist. + */ +int fptr_whitelist_serviced_query(comm_point_callback_t *fptr); + + #endif /* UTIL_FPTR_WLIST_H */ diff --git a/util/netevent.c b/util/netevent.c index b3eb8d312..d238bcea4 100644 --- a/util/netevent.c +++ b/util/netevent.c @@ -93,54 +93,6 @@ struct internal_signal { struct internal_signal* next; }; -/** - * handle libevent callback for udp comm point. - * @param fd: file descriptor. - * @param event: event bits from libevent: - * EV_READ, EV_WRITE, EV_SIGNAL, EV_TIMEOUT. - * @param arg: the comm_point structure. - */ -static void comm_point_udp_callback(int fd, short event, void* arg); - -/** - * handle libevent callback for tcp accept comm point - * @param fd: file descriptor. - * @param event: event bits from libevent: - * EV_READ, EV_WRITE, EV_SIGNAL, EV_TIMEOUT. - * @param arg: the comm_point structure. - */ -static void comm_point_tcp_accept_callback(int fd, short event, void* arg); - -/** - * handle libevent callback for tcp data comm point - * @param fd: file descriptor. - * @param event: event bits from libevent: - * EV_READ, EV_WRITE, EV_SIGNAL, EV_TIMEOUT. - * @param arg: the comm_point structure. - */ -static void comm_point_tcp_handle_callback(int fd, short event, void* arg); - -/** - * handle libevent callback for timer comm. - * @param fd: file descriptor (always -1). - * @param event: event bits from libevent: - * EV_READ, EV_WRITE, EV_SIGNAL, EV_TIMEOUT. - * @param arg: the comm_timer structure. - */ -static void comm_timer_callback(int fd, short event, void* arg); - -/** - * handle libevent callback for signal comm. - * @param fd: file descriptor (used for the signal number). - * @param event: event bits from libevent: - * EV_READ, EV_WRITE, EV_SIGNAL, EV_TIMEOUT. - * @param arg: the internal commsignal structure. - */ -static void comm_signal_callback(int fd, short event, void* arg); - -/** libevent callback for AF_UNIX fds */ -static void comm_point_local_handle_callback(int fd, short event, void* arg); - /** create a tcp handler with a parent */ static struct comm_point* comm_point_create_tcp_handler( struct comm_base *base, struct comm_point* parent, size_t bufsize, @@ -223,7 +175,7 @@ comm_point_send_udp_msg(struct comm_point *c, ldns_buffer* packet, return 1; } -static void +void comm_point_udp_callback(int fd, short event, void* arg) { struct comm_reply rep; @@ -254,6 +206,7 @@ comm_point_udp_callback(int fd, short event, void* arg) (void)comm_point_send_udp_msg(rep.c, rep.c->buffer, (struct sockaddr*)&rep.addr, rep.addrlen); } + log_assert(fptr_whitelist_event(rep.c->ev->ev.ev_callback)); } /** Use a new tcp handler for new query fd, set to read query */ @@ -268,7 +221,7 @@ setup_tcp_handler(struct comm_point* c, int fd) comm_point_start_listening(c, fd, TCP_QUERY_TIMEOUT); } -static void +void comm_point_tcp_accept_callback(int fd, short event, void* arg) { struct comm_point* c = (struct comm_point*)arg, *c_hdl; @@ -310,6 +263,7 @@ comm_point_tcp_accept_callback(int fd, short event, void* arg) } /* addr is dropped. Not needed for tcp reply. */ setup_tcp_handler(c_hdl, new_fd); + log_assert(fptr_whitelist_event(c->ev->ev.ev_callback)); } /** Make tcp handler free for next assignment */ @@ -496,7 +450,7 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c) return 1; } -static void +void comm_point_tcp_handle_callback(int fd, short event, void* arg) { struct comm_point* c = (struct comm_point*)arg; @@ -512,6 +466,7 @@ comm_point_tcp_handle_callback(int fd, short event, void* arg) NETEVENT_CLOSED, NULL); } } + log_assert(fptr_whitelist_event(c->ev->ev.ev_callback)); return; } if(event&EV_WRITE) { @@ -524,6 +479,7 @@ comm_point_tcp_handle_callback(int fd, short event, void* arg) NETEVENT_CLOSED, NULL); } } + log_assert(fptr_whitelist_event(c->ev->ev.ev_callback)); return; } if(event&EV_TIMEOUT) { @@ -534,12 +490,14 @@ comm_point_tcp_handle_callback(int fd, short event, void* arg) (void)(*c->callback)(c, c->cb_arg, NETEVENT_TIMEOUT, NULL); } + log_assert(fptr_whitelist_event(c->ev->ev.ev_callback)); return; } log_err("Ignored event %d for tcphdl.", event); + log_assert(fptr_whitelist_event(c->ev->ev.ev_callback)); } -static void comm_point_local_handle_callback(int fd, short event, void* arg) +void comm_point_local_handle_callback(int fd, short event, void* arg) { struct comm_point* c = (struct comm_point*)arg; log_assert(c->type == comm_local); @@ -550,9 +508,11 @@ static void comm_point_local_handle_callback(int fd, short event, void* arg) (void)(*c->callback)(c, c->cb_arg, NETEVENT_CLOSED, NULL); } + log_assert(fptr_whitelist_event(c->ev->ev.ev_callback)); return; } log_err("Ignored event %d for localhdl.", event); + log_assert(fptr_whitelist_event(c->ev->ev.ev_callback)); } struct comm_point* @@ -1069,7 +1029,7 @@ comm_timer_delete(struct comm_timer* timer) free(timer); } -static void +void comm_timer_callback(int ATTR_UNUSED(fd), short event, void* arg) { struct comm_timer* tm = (struct comm_timer*)arg; @@ -1078,6 +1038,7 @@ comm_timer_callback(int ATTR_UNUSED(fd), short event, void* arg) tm->ev_timer->enabled = 0; log_assert(fptr_whitelist_comm_timer(tm->callback)); (*tm->callback)(tm->cb_arg); + log_assert(fptr_whitelist_event(tm->ev_timer->ev.ev_callback)); } int @@ -1109,7 +1070,7 @@ comm_signal_create(struct comm_base* base, return com; } -static void +void comm_signal_callback(int sig, short event, void* arg) { struct comm_signal* comsig = (struct comm_signal*)arg; @@ -1117,6 +1078,7 @@ comm_signal_callback(int sig, short event, void* arg) return; log_assert(fptr_whitelist_comm_signal(comsig->callback)); (*comsig->callback)(sig, comsig->cb_arg); + log_assert(fptr_whitelist_event(comsig->ev_signal->ev.ev_callback)); } int diff --git a/util/netevent.h b/util/netevent.h index a1bb56bbb..c63944e39 100644 --- a/util/netevent.h +++ b/util/netevent.h @@ -461,4 +461,68 @@ int comm_signal_bind(struct comm_signal* comsig, int sig); */ void comm_signal_delete(struct comm_signal* comsig); + +/**** internal routines ****/ + +/** + * This routine is published for checks and tests, and is only used internally. + * handle libevent callback for udp comm point. + * @param fd: file descriptor. + * @param event: event bits from libevent: + * EV_READ, EV_WRITE, EV_SIGNAL, EV_TIMEOUT. + * @param arg: the comm_point structure. + */ +void comm_point_udp_callback(int fd, short event, void* arg); + +/** + * This routine is published for checks and tests, and is only used internally. + * handle libevent callback for tcp accept comm point + * @param fd: file descriptor. + * @param event: event bits from libevent: + * EV_READ, EV_WRITE, EV_SIGNAL, EV_TIMEOUT. + * @param arg: the comm_point structure. + */ +void comm_point_tcp_accept_callback(int fd, short event, void* arg); + +/** + * This routine is published for checks and tests, and is only used internally. + * handle libevent callback for tcp data comm point + * @param fd: file descriptor. + * @param event: event bits from libevent: + * EV_READ, EV_WRITE, EV_SIGNAL, EV_TIMEOUT. + * @param arg: the comm_point structure. + */ +void comm_point_tcp_handle_callback(int fd, short event, void* arg); + +/** + * This routine is published for checks and tests, and is only used internally. + * handle libevent callback for timer comm. + * @param fd: file descriptor (always -1). + * @param event: event bits from libevent: + * EV_READ, EV_WRITE, EV_SIGNAL, EV_TIMEOUT. + * @param arg: the comm_timer structure. + */ +void comm_timer_callback(int fd, short event, void* arg); + +/** + * This routine is published for checks and tests, and is only used internally. + * handle libevent callback for signal comm. + * @param fd: file descriptor (used for the signal number). + * @param event: event bits from libevent: + * EV_READ, EV_WRITE, EV_SIGNAL, EV_TIMEOUT. + * @param arg: the internal commsignal structure. + */ +void comm_signal_callback(int fd, short event, void* arg); + +/** + * This routine is published for checks and tests, and is only used internally. + * libevent callback for AF_UNIX fds + * @param fd: file descriptor. + * @param event: event bits from libevent: + * EV_READ, EV_WRITE, EV_SIGNAL, EV_TIMEOUT. + * @param arg: the comm_point structure. + */ +void comm_point_local_handle_callback(int fd, short event, void* arg); + + #endif /* NET_EVENT_H */