diff --git a/libc/wqueue/work_thread.c b/libc/wqueue/work_thread.c index 285f7183cd..c0474ad692 100644 --- a/libc/wqueue/work_thread.c +++ b/libc/wqueue/work_thread.c @@ -148,26 +148,44 @@ static void work_process(FAR struct wqueue_s *wqueue) */ worker = work->worker; - arg = work->arg; - /* Mark the work as no longer being queued */ - - work->worker = NULL; - - /* Do the work. Re-enable interrupts while the work is being - * performed... we don't have any idea how long that will take! + /* Check for a race condition where the work may be nullified + * before it is removed from the queue. */ - irqrestore(flags); - worker(arg); + if (worker != NULL) + { + /* Extract the work argument (before re-enabling interrupts) */ - /* Now, unfortunately, since we re-enabled interrupts we don't - * know the state of the work list and we will have to start - * back at the head of the list. - */ + arg = work->arg; - flags = irqsave(); - work = (FAR struct work_s *)wqueue->q.head; + /* Mark the work as no longer being queued */ + + work->worker = NULL; + + /* Do the work. Re-enable interrupts while the work is being + * performed... we don't have any idea how long that will take! + */ + + irqrestore(flags); + worker(arg); + + /* Now, unfortunately, since we re-enabled interrupts we don't + * know the state of the work list and we will have to start + * back at the head of the list. + */ + + flags = irqsave(); + work = (FAR struct work_s *)wqueue->q.head; + } + else + { + /* Cancelled.. Just move to the next work in the list with + * interrupts still disabled. + */ + + work = (FAR struct work_s *)work->dq.flink; + } } else { diff --git a/net/socket/net_sendfile.c b/net/socket/net_sendfile.c index 5b43f297d6..bc4181ab42 100644 --- a/net/socket/net_sendfile.c +++ b/net/socket/net_sendfile.c @@ -60,10 +60,12 @@ #include #include #include +#include #include "socket/socket.h" #include "netdev/netdev.h" #include "devif/devif.h" +#include "tcp/tcp.h" /**************************************************************************** * Definitions diff --git a/net/utils/net_chksum.c b/net/utils/net_chksum.c index ff8438678c..789646f50a 100644 --- a/net/utils/net_chksum.c +++ b/net/utils/net_chksum.c @@ -126,6 +126,13 @@ static uint16_t upper_layer_chksum(FAR struct net_driver_s *dev, uint8_t proto) upper_layer_len = (((uint16_t)(pbuf->len[0]) << 8) + pbuf->len[1]) - UIP_IPH_LEN; #endif /* CONFIG_NET_IPv6 */ + /* Verify some minimal assumptions */ + + if (upper_layer_len > CONFIG_NET_BUFSIZE) + { + return 0; + } + /* First sum pseudo-header. */ /* IP protocol and length fields. This addition cannot carry. */