From 86eb2dc3bc78db95a900543bbd72a66c8717d6e3 Mon Sep 17 00:00:00 2001 From: Christian Spielberger Date: Tue, 7 Mar 2023 16:07:51 +0100 Subject: [PATCH] udp: add a lock for the helpers list --- src/udp/udp.c | 63 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 55 insertions(+), 8 deletions(-) diff --git a/src/udp/udp.c b/src/udp/udp.c index 5168b3ffd..52a5891a4 100644 --- a/src/udp/udp.c +++ b/src/udp/udp.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -74,6 +75,7 @@ struct udp_sock { QOS_FLOWID qos_id; /**< QOS IPv4 flow id */ QOS_FLOWID qos_id6; /**< QOS IPv6 flow id */ #endif + mtx_t *lock; /**< A lock for helpers */ }; /** Defines a UDP helper */ @@ -120,8 +122,16 @@ static void udp_destructor(void *data) { struct udp_sock *us = data; + if (us->lock) + mtx_lock(us->lock); + list_flush(&us->helpers); + if (us->lock) { + mtx_unlock(us->lock); + mem_deref(us->lock); + } + #ifdef WIN32 if (us->qos && us->qos_id) (void)QOSRemoveSocketFromFlow(us->qos, 0, us->qos_id, 0); @@ -185,6 +195,7 @@ static void udp_read(struct udp_sock *us, re_sock_t fd) (void)mbuf_resize(mb, mb->end); /* call helpers */ + mtx_lock(us->lock); le = us->helpers.head; while (le) { struct udp_helper *uh = le->data; @@ -200,6 +211,7 @@ static void udp_read(struct udp_sock *us, re_sock_t fd) us->rh(&src, mb, us->arg); out: + mtx_unlock(us->lock); mem_deref(mb); } @@ -250,6 +262,10 @@ int udp_listen(struct udp_sock **usp, const struct sa *local, if (!us) return ENOMEM; + err = mutex_alloc(&us->lock); + if (err) + goto out; + list_init(&us->helpers); us->fd = RE_BAD_SOCK; @@ -382,6 +398,10 @@ int udp_alloc_sockless(struct udp_sock **usp, if (!us) return ENOMEM; + int err = mutex_alloc(&us->lock); + if (err) + goto out; + list_init(&us->helpers); us->fd = RE_BAD_SOCK; @@ -391,9 +411,13 @@ int udp_alloc_sockless(struct udp_sock **usp, us->arg = arg; us->rxsz = UDP_RXSZ_DEFAULT; - *usp = us; +out: + if (err) + mem_deref(us); + else + *usp = us; - return 0; + return err; } @@ -407,6 +431,10 @@ int udp_alloc_fd(struct udp_sock **usp, re_sock_t fd, if (!us) return ENOMEM; + int err = mutex_alloc(&us->lock); + if (err) + goto out; + list_init(&us->helpers); us->fd = fd; @@ -415,7 +443,11 @@ int udp_alloc_fd(struct udp_sock **usp, re_sock_t fd, us->arg = arg; us->rxsz = UDP_RXSZ_DEFAULT; - *usp = us; +out: + if (err) + mem_deref(us); + else + *usp = us; return 0; } @@ -442,6 +474,10 @@ int udp_open(struct udp_sock **usp, int af) if (!us) return ENOMEM; + err = mutex_alloc(&us->lock); + if (err) + goto out; + us->fd = RE_BAD_SOCK; us->fd6 = RE_BAD_SOCK; @@ -879,6 +915,7 @@ int udp_register_helper(struct udp_helper **uhp, struct udp_sock *us, if (!uh) return ENOMEM; + mtx_lock(us->lock); list_append(&us->helpers, &uh->le, uh); uh->layer = layer; @@ -891,6 +928,7 @@ int udp_register_helper(struct udp_helper **uhp, struct udp_sock *us, if (uhp) *uhp = uh; + mtx_unlock(us->lock); return 0; } @@ -957,19 +995,24 @@ void udp_recv_helper(struct udp_sock *us, const struct sa *src, struct udp_helper *udp_helper_find(const struct udp_sock *us, int layer) { struct le *le; + struct udp_helper *uhf = NULL; if (!us) return NULL; + mtx_lock(us->lock); for (le = us->helpers.head; le; le = le->next) { struct udp_helper *uh = le->data; - if (layer == uh->layer) - return uh; + if (layer == uh->layer) { + uhf = uh; + break; + } } - return NULL; + mtx_unlock(us->lock); + return uhf; } @@ -1005,11 +1048,13 @@ void udp_recv_packet(struct udp_sock *us, const struct sa *src, struct mbuf *mb) { struct sa hsrc; + struct le *le; if (!us || !src || !mb) return; - struct le *le = us->helpers.head; + mtx_lock(us->lock); + le = us->helpers.head; while (le) { struct udp_helper *uh = le->data; bool hdld; @@ -1023,8 +1068,10 @@ void udp_recv_packet(struct udp_sock *us, const struct sa *src, hdld = uh->recvh(&hsrc, mb, uh->arg); if (hdld) - return; + goto out; } us->rh(src, mb, us->arg); +out: + mtx_unlock(us->lock); }