]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
assertions, zero termination for gethostname, log_hex without malloc.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Tue, 16 Oct 2007 12:26:09 +0000 (12:26 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Tue, 16 Oct 2007 12:26:09 +0000 (12:26 +0000)
git-svn-id: file:///svn/unbound/trunk@679 be551aaa-1e26-0410-a405-d3ace91eadb9

12 files changed:
daemon/daemon.c
daemon/worker.c
doc/Changelog
services/outside_network.c
testcode/unitmsgparse.c
util/data/msgparse.c
util/locks.c
util/log.c
util/log.h
util/net_help.c
util/net_help.h
util/netevent.c

index 5813a3e5db9fed0f3bd4b0df922f6b8ce22249e8..5447e9f290298cff384b73a2a28fde4b3832212d 100644 (file)
@@ -269,8 +269,6 @@ static void daemon_setup_modules(struct daemon* daemon)
        daemon->env->cfg = daemon->cfg;
        daemon->env->alloc = &daemon->superalloc;
        daemon->env->worker = NULL;
-       daemon->env->send_packet = &worker_send_packet;
-       daemon->env->send_query = &worker_send_query;
        daemon->env->need_to_validate = 0; /* set by module init below */
        for(i=0; i<daemon->num_modules; i++) {
                log_info("init module %d: %s", i, daemon->modfunc[i]->name);
@@ -384,7 +382,7 @@ daemon_stop_others(struct daemon* daemon)
                worker_send_cmd(daemon->workers[i], 
                        daemon->workers[0]->front->udp_buff, worker_cmd_quit);
        }
-       /** wait for them to quit */
+       /* wait for them to quit */
        for(i=1; i<daemon->num; i++) {
                /* join it to make sure its dead */
                verbose(VERB_ALGO, "join %d", i);
index c4f7953837f806129db6520062c3781ea5b6ca21..25091f8e5987733ddad2eb0936b9e01e31e85df1 100644 (file)
@@ -624,10 +624,11 @@ answer_chaos(struct worker* w, struct query_info* qinfo,
                if(cfg->hide_identity) 
                        return 0;
                if(cfg->identity==NULL || cfg->identity[0]==0) {
-                       char buf[MAXHOSTNAMELEN];
-                       if (gethostname(buf, MAXHOSTNAMELEN) == 0)
+                       char buf[MAXHOSTNAMELEN+1];
+                       if (gethostname(buf, MAXHOSTNAMELEN) == 0) {
+                               buf[MAXHOSTNAMELEN] = 0;
                                chaos_replystr(pkt, buf, edns);
-                       else    {
+                       } else  {
                                log_err("gethostname: %s", strerror(errno));
                                chaos_replystr(pkt, "no hostname", edns);
                        }
@@ -797,22 +798,22 @@ worker_sighandler(int sig, void* arg)
        struct worker* worker = (struct worker*)arg;
        switch(sig) {
                case SIGHUP:
-                       log_info("caught signal SIGHUP");
+                       verbose(VERB_DETAIL, "caught signal SIGHUP");
                        worker->need_to_restart = 1;
                        comm_base_exit(worker->base);
                        break;
                case SIGINT:
-                       log_info("caught signal SIGINT");
+                       verbose(VERB_DETAIL, "caught signal SIGINT");
                        worker->need_to_restart = 0;
                        comm_base_exit(worker->base);
                        break;
                case SIGQUIT:
-                       log_info("caught signal SIGQUIT");
+                       verbose(VERB_DETAIL, "caught signal SIGQUIT");
                        worker->need_to_restart = 0;
                        comm_base_exit(worker->base);
                        break;
                case SIGTERM:
-                       log_info("caught signal SIGTERM");
+                       verbose(VERB_DETAIL, "caught signal SIGTERM");
                        worker->need_to_restart = 0;
                        comm_base_exit(worker->base);
                        break;
@@ -949,6 +950,8 @@ worker_init(struct worker* worker, struct config_file *cfg,
                worker->thread_num);
        worker->env = *worker->daemon->env;
        worker->env.worker = worker;
+       worker->env.send_packet = &worker_send_packet;
+       worker->env.send_query = &worker_send_query;
        worker->env.alloc = &worker->alloc;
        worker->env.rnd = worker->rndstate;
        worker->env.scratch = worker->scratchpad;
index 6a2d58c2bb1d61ec11f690d8323fc55987695971..638db8be6efaeb0748f5a65e0075c9e560b273ab 100644 (file)
@@ -1,3 +1,8 @@
+16 October 2007: Wouter
+       - no malloc in log_hex.
+       - assertions around system calls.
+       - protect against gethostname without ending zero.
+
 15 October 2007: Wouter
        - nicer warning.
        - fix IP6 TCP, wrong definition check. With test package.
index 986674875bdc30f060a0869ed4311906f9ef13ff..cf1e347c351e8acf4130d031e2e6db9e8f8cdd42 100644 (file)
@@ -91,7 +91,7 @@ serviced_cmp(const void* key1, const void* key2)
        if(q1->qbuflen > q2->qbuflen)
                return 1;
        log_assert(q1->qbuflen == q2->qbuflen);
-       /* FIXME: will not detect alternate casing of qname */
+       /* will not detect alternate casing of qname */
        if((r = memcmp(q1->qbuf, q2->qbuf, q1->qbuflen)) != 0)
                return r;
        if(q1->dnssec != q2->dnssec) {
@@ -122,6 +122,7 @@ outnet_tcp_take_into_use(struct waiting_tcp* w, uint8_t* pkt, size_t pkt_len)
        int s;
        log_assert(pend);
        log_assert(pkt);
+       log_assert(w->addrlen > 0);
        /* open socket */
 #ifdef INET6
        if(addr_is_ip6(&w->addr, w->addrlen))
@@ -249,17 +250,12 @@ outnet_udp_cb(struct comm_point* c, void* arg, int error,
        p = (struct pending*)rbtree_search(outnet->pending, &key);
        if(!p) {
                verbose(VERB_DETAIL, "received unwanted or unsolicited udp reply dropped.");
-               if(verbosity >= VERB_ALGO)
-                       log_hex("dropped message", 
-                               ldns_buffer_begin(c->buffer), 
-                               ldns_buffer_limit(c->buffer));
+               log_buf(VERB_ALGO, "dropped message", c->buffer);
                return 0;
        }
 
        verbose(VERB_ALGO, "received udp reply.");
-       if(verbosity >= VERB_ALGO)
-               log_hex("udp message", ldns_buffer_begin(c->buffer), 
-                               ldns_buffer_limit(c->buffer));
+       log_buf(VERB_ALGO, "udp message", c->buffer);
        if(p->c != c) {
                verbose(VERB_DETAIL, "received reply id,addr on wrong port. "
                        "dropped.");
@@ -1125,6 +1121,7 @@ serviced_udp_callback(struct comm_point* c, void* arg, int error,
                int roundtime = (now.tv_sec - sq->last_sent_time.tv_sec)*1000
                  + ((int)now.tv_usec - (int)sq->last_sent_time.tv_usec)/1000;
                verbose(VERB_ALGO, "measured roundtrip at %d msec", roundtime);
+               log_assert(roundtime >= 0);
                if(!infra_rtt_update(outnet->infra, &sq->addr, sq->addrlen, 
                        roundtime, (time_t)now.tv_sec))
                        log_err("out of memory noting rtt.");
index 784aaefb838b374120df16e3aa5c4cff7feffa3c..43e5c37234b1c159ff97a3bd571acdabbecd9ecd 100644 (file)
@@ -206,10 +206,8 @@ test_buffers(ldns_buffer* pkt, ldns_buffer* out)
        s1 = ldns_buffer2pkt_wire(&p1, pkt);
        s2 = ldns_buffer2pkt_wire(&p2, out);
        if(vbmp) {
-               log_hex("orig in hex", ldns_buffer_begin(pkt),
-                       ldns_buffer_limit(pkt));
-               log_hex("unbound out in hex", ldns_buffer_begin(out),
-                       ldns_buffer_limit(out));
+               log_buf(0, "orig in hex", pkt);
+               log_buf(0, "unbound out in hex", out);
                printf("\npacket from unbound (%d):\n", 
                        (int)ldns_buffer_limit(out));
                ldns_pkt_print(stdout, p2);
index 383a1ceb072af1e974c362c1bc3fa3bab9d264f1..f13c9c6d077f360841624b098ddea430491014ad 100644 (file)
@@ -701,8 +701,7 @@ add_rr_to_rrset(struct rrset_parse* rrset, ldns_buffer* pkt,
                /*
                verbose(VERB_DETAIL, "Packet contains rrset data in "
                        "multiple sections, dropped last part.");
-               log_hex("packet was: ", ldns_buffer_begin(pkt), 
-                       ldns_buffer_limit(pkt));
+               log_buf(VERB_DETAIL, "packet was", pkt);
                */
                /* forwards */
                if(!skip_ttl_rdata(pkt))
index e78b22de6b540999f4cec0137eb4e9b80d2acd57..b2b1f49e3492333023fce0c101100fd57574d0e8 100644 (file)
@@ -81,7 +81,7 @@ void ub_thread_sig_unblock(int sig)
        if((err=thr_sigsetmask(SIG_UNBLOCK, &sigset, NULL)))
                fatal_exit("thr_sigsetmask: %s", strerror(err));
 #  else 
-       /* have nothing, do nothing */
+       /* have nothing, do single thread case */
        if((err=sigprocmask(SIG_UNBLOCK, &sigset, NULL)))
                fatal_exit("sigprocmask: %s", strerror(errno));
 #  endif /* HAVE_SOLARIS_THREADS */
index b596dbd669b69a7d6cd9df055b1a6cebe788bdc4..a0b33a9ecf974eb39b4e6c0588916c0e6716dbc8 100644 (file)
@@ -83,7 +83,7 @@ log_init(const char* filename, int use_syslog)
        || log_to_syslog
 #endif
        )
-               verbose(VERB_DETAIL, "switching log to %s", 
+       verbose(VERB_DETAIL, "switching log to %s", 
                use_syslog?"syslog":(filename&&filename[0]?filename:"stderr"));
        if(logfile && logfile != stderr)
                fclose(logfile);
@@ -218,23 +218,35 @@ verbose(enum verbosity_value level, const char* format, ...)
 void 
 log_hex(const char* msg, void* data, size_t length)
 {
-       size_t i;
+       size_t i, j;
        uint8_t* data8 = (uint8_t*)data;
        const char* hexchar = "0123456789ABCDEF";
-       char* buf = malloc(length*2 + 1); /* alloc hex chars + \0 */
-       size_t blocksize = 1024;
-       for(i=0; i<length; i++) {
-               buf[i*2] = hexchar[ data8[i] >> 4 ];
-               buf[i*2 + 1] = hexchar[ data8[i] & 0xF ];
+       char buf[1024+1]; /* alloc blocksize hex chars + \0 */
+       const size_t blocksize = 1024;
+       size_t len;
+
+       if(length == 0) {
+               log_info("%s[%u]", msg, (unsigned)length);
+               return;
        }
-       buf[length*2] = 0;
-       if(length < blocksize/2)
-               log_info("%s[%u] %s", msg, (unsigned)length, buf);
-       else {
-               for(i=0; i<length*2; i+=blocksize) {
-                       log_info("%s[%u:%u] %.*s", msg, (unsigned)length, 
-                               (unsigned)i/2, (int)blocksize, buf+i);
+
+       for(i=0; i<length; i+=blocksize/2) {
+               len = blocksize/2;
+               if(length - i < blocksize/2)
+                       len = length - i;
+               for(j=0; j<len; j++) {
+                       buf[j*2] = hexchar[ data8[i+j] >> 4 ];
+                       buf[j*2 + 1] = hexchar[ data8[i+j] & 0xF ];
                }
+               buf[len*2] = 0;
+               log_info("%s[%u:%u] %.*s", msg, (unsigned)length, 
+                       (unsigned)i, (int)len*2, buf);
        }
-       free(buf);
+}
+
+void log_buf(enum verbosity_value level, const char* msg, ldns_buffer* buf)
+{
+       if(verbosity < level)
+               return;
+       log_hex(msg, ldns_buffer_begin(buf), ldns_buffer_limit(buf));
 }
index 12dc6bfe5663b6cfe5701bc9c9e78d2c5d4c26fa..f14256f17ff58089521b61ef561dfade8fa14cbd 100644 (file)
@@ -125,6 +125,15 @@ void log_warn(const char* format, ...) ATTR_FORMAT(printf, 1, 2);
  */
 void log_hex(const char* msg, void* data, size_t length);
 
+/**
+ * Easy alternative for log_hex, takes a ldns_buffer.
+ * @param level: verbosity level for this message, compared to global 
+ *     verbosity setting.
+ * @param msg: string desc to print
+ * @param buf: the buffer.
+ */
+void log_buf(enum verbosity_value level, const char* msg, ldns_buffer* buf);
+
 /**
  * Log fatal error message, and exit the current process.
  * Pass printf formatted arguments. No trailing newline is needed.
index bddcf0dbe6c5897c38a77a23f457985bc9a76cd8..7eadca4fd78611fe58c2aea456dab5db73e101b5 100644 (file)
@@ -61,11 +61,13 @@ write_socket(int s, const void *buf, size_t size)
         const char* data = (const char*)buf;
         size_t total_count = 0;
 
+       fd_set_block(s);
         while (total_count < size) {
                 ssize_t count
                         = write(s, data + total_count, size - total_count);
                 if (count == -1) {
                         if (errno != EAGAIN && errno != EINTR) {
+                               fd_set_nonblock(s);
                                 return 0;
                         } else {
                                 continue;
@@ -73,6 +75,7 @@ write_socket(int s, const void *buf, size_t size)
                 }
                 total_count += count;
         }
+       fd_set_nonblock(s);
         return 1;
 }
 
@@ -92,6 +95,22 @@ fd_set_nonblock(int s)
        return 1;
 }
 
+int 
+fd_set_block(int s) 
+{
+       int flag;
+       if((flag = fcntl(s, F_GETFL)) == -1) {
+               log_err("cannot fcntl F_GETFL: %s", strerror(errno));
+               flag = 0;
+       }
+       flag &= ~O_NONBLOCK;
+       if(fcntl(s, F_SETFL, flag) == -1) {
+               log_err("cannot fcntl F_SETFL: %s", strerror(errno));
+               return 0;
+       }
+       return 1;
+}
+
 int 
 is_pow2(size_t num)
 {
index 83e631e8ed227e659821079f5e77e5f09c09ffa8..aeb3802bcd68e135f5731296b6cd0a0cb9232579 100644 (file)
@@ -98,7 +98,7 @@ int str_is_ip6(const char* str);
 
 /**
  * Write (blocking) to a nonblocking socket.
- * @param s: fd.
+ * @param s: fd. Is set to be nonblocking at exit.
  * @param buf: data buffer.
  * @param size: length of data to send.
  * @return: 0 on error. errno is set.
@@ -113,6 +113,13 @@ write_socket(int s, const void *buf, size_t size);
  */
 int fd_set_nonblock(int s); 
 
+/**
+ * Set fd (back to) blocking.
+ * @param s: file descriptor.
+ * @return: 0 on error (error is printed to log).
+ */
+int fd_set_block(int s); 
+
 /**
  * See if number is a power of 2.
  * @param num: the value.
index df3882760f2b96237f3579d57f475ea87812d097..696fd31444b9515b09bcb6d688e1af9791e60d40 100644 (file)
@@ -161,6 +161,9 @@ comm_point_send_udp_msg(struct comm_point *c, ldns_buffer* packet,
        struct sockaddr* addr, socklen_t addrlen) 
 {
        ssize_t sent;
+       log_assert(c->fd != -1);
+       log_assert(ldns_buffer_remaining(packet) > 0);
+       log_assert(addr && addrlen > 0);
        sent = sendto(c->fd, ldns_buffer_begin(packet), 
                ldns_buffer_remaining(packet), 0,
                addr, addrlen);
@@ -189,6 +192,8 @@ comm_point_udp_callback(int fd, short event, void* arg)
        log_assert(rep.c && rep.c->buffer && rep.c->fd == fd);
        ldns_buffer_clear(rep.c->buffer);
        rep.addrlen = (socklen_t)sizeof(rep.addr);
+       log_assert(fd != -1);
+       log_assert(ldns_buffer_remaining(rep.c->buffer) > 0);
        recv = recvfrom(fd, ldns_buffer_begin(rep.c->buffer), 
                ldns_buffer_remaining(rep.c->buffer), 0, 
                (struct sockaddr*)&rep.addr, &rep.addrlen);
@@ -234,6 +239,7 @@ comm_point_tcp_accept_callback(int fd, short event, void* arg)
        /* accept incoming connection. */
        rep.c = NULL;
        rep.addrlen = (socklen_t)sizeof(rep.addr);
+       log_assert(fd != -1);
        new_fd = accept(fd, (struct sockaddr*)&rep.addr, &rep.addrlen);
        if(new_fd == -1) {
                /* EINTR is signal interrupt. others are closed connection. */
@@ -244,7 +250,8 @@ comm_point_tcp_accept_callback(int fd, short event, void* arg)
                        && errno != EPROTO
 #endif /* EPROTO */
                        )
-                       log_err("accept failed: %s", strerror(errno));
+                       return;
+               log_err("accept failed: %s", strerror(errno));
                return;
        }
        /* find free tcp handler. */
@@ -330,6 +337,7 @@ comm_point_tcp_handle_read(int fd, struct comm_point* c, int short_ok)
        if(!c->tcp_is_reading)
                return 0;
 
+       log_assert(fd != -1);
        if(c->tcp_byte_count < sizeof(uint16_t)) {
                /* read length bytes */
                r = read(fd, ldns_buffer_at(c->buffer, c->tcp_byte_count), 
@@ -361,6 +369,7 @@ comm_point_tcp_handle_read(int fd, struct comm_point* c, int short_ok)
                        (int)ldns_buffer_limit(c->buffer));
        }
 
+       log_assert(ldns_buffer_remaining(c->buffer) > 0);
        r = read(fd, ldns_buffer_current(c->buffer), 
                ldns_buffer_remaining(c->buffer));
        if(r == 0) {
@@ -391,6 +400,7 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c)
        log_assert(c->type == comm_tcp);
        if(c->tcp_is_reading)
                return 0;
+       log_assert(fd != -1);
        if(c->tcp_byte_count == 0 && c->tcp_check_nb_connect) {
                /* check for pending error from nonblocking connect */
                /* from Stevens, unix network programming, vol1, 3rd ed, p450*/
@@ -414,6 +424,8 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c)
                iov[0].iov_len = sizeof(uint16_t) - c->tcp_byte_count;
                iov[1].iov_base = ldns_buffer_begin(c->buffer);
                iov[1].iov_len = ldns_buffer_limit(c->buffer);
+               log_assert(iov[0].iov_len > 0);
+               log_assert(iov[1].iov_len > 0);
                r = writev(fd, iov, 2);
                if(r == -1) {
                        if(errno == EINTR || errno == EAGAIN)
@@ -431,6 +443,7 @@ comm_point_tcp_handle_write(int fd, struct comm_point* c)
                }
                return 1;
        }
+       log_assert(ldns_buffer_remaining(c->buffer) > 0);
        r = write(fd, ldns_buffer_current(c->buffer), 
                ldns_buffer_remaining(c->buffer));
        if(r == -1) {
@@ -832,6 +845,8 @@ comm_point_send_reply_iov(struct comm_reply* repinfo, struct iovec* iov,
         size_t iovlen)
 {
        log_assert(repinfo && repinfo->c);
+       log_assert(repinfo->c->fd != -1);
+       log_assert(repinfo->addrlen > 0);
        if(repinfo->c->type == comm_udp) {
                struct msghdr hdr;
                memset(&hdr, 0, sizeof(hdr));
@@ -1005,6 +1020,7 @@ comm_timer_disable(struct comm_timer* timer)
 void 
 comm_timer_set(struct comm_timer* timer, struct timeval* tv)
 {
+       log_assert(tv);
        if(timer->ev_timer->enabled)
                comm_timer_disable(timer);
        evtimer_add(&timer->ev_timer->ev, tv);