From a4ce5e7d47d27c8b582e27b38ce61c9cb9735992 Mon Sep 17 00:00:00 2001 From: dimitri staessens Date: Thu, 6 Apr 2017 16:46:52 +0200 Subject: ipcpd: Fix race condition with concurrent allocs --- src/ipcpd/shim-eth-llc/main.c | 43 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 5 deletions(-) (limited to 'src/ipcpd/shim-eth-llc') diff --git a/src/ipcpd/shim-eth-llc/main.c b/src/ipcpd/shim-eth-llc/main.c index 1b6e02c2..20189e08 100644 --- a/src/ipcpd/shim-eth-llc/main.c +++ b/src/ipcpd/shim-eth-llc/main.c @@ -352,10 +352,22 @@ static int eth_llc_ipcp_sap_req(uint8_t r_sap, char * dst_name, qoscube_t cube) { - int fd; + struct timespec ts = {0, EVENT_WAIT_TIMEOUT * 1000}; + int fd; pthread_mutex_lock(&ipcpi.alloc_lock); + while (ipcpi.alloc_id != -1 && ipcp_get_state() == IPCP_OPERATIONAL) + pthread_cond_timedwait(&ipcpi.alloc_cond, + &ipcpi.alloc_lock, + &ts); + + if (ipcp_get_state() != IPCP_OPERATIONAL) { + log_dbg("Won't allocate over non-operational IPCP."); + pthread_mutex_unlock(&ipcpi.alloc_lock); + return -1; + } + /* reply to IRM, called under lock to prevent race */ fd = ipcp_flow_req_arr(getpid(), dst_name, cube); if (fd < 0) { @@ -369,6 +381,9 @@ static int eth_llc_ipcp_sap_req(uint8_t r_sap, eth_llc_data.fd_to_ef[fd].r_sap = r_sap; memcpy(eth_llc_data.fd_to_ef[fd].r_addr, r_addr, MAC_SIZE); + ipcpi.alloc_id = fd; + pthread_cond_broadcast(&ipcpi.alloc_cond); + pthread_rwlock_unlock(ð_llc_data.flows_lock); pthread_mutex_unlock(&ipcpi.alloc_lock); @@ -630,12 +645,12 @@ static void * eth_llc_ipcp_sdu_reader(void * o) static void * eth_llc_ipcp_sdu_writer(void * o) { + struct timespec timeout = {0, EVENT_WAIT_TIMEOUT * 1000}; int fd; struct shm_du_buff * sdb; uint8_t ssap; uint8_t dsap; uint8_t r_addr[MAC_SIZE]; - struct timespec timeout = {0, EVENT_WAIT_TIMEOUT * 1000}; (void) o; @@ -956,9 +971,27 @@ static int eth_llc_ipcp_flow_alloc(int fd, static int eth_llc_ipcp_flow_alloc_resp(int fd, int response) { - uint8_t ssap = 0; - uint8_t r_sap = 0; - uint8_t r_addr[MAC_SIZE]; + struct timespec ts = {0, EVENT_WAIT_TIMEOUT * 1000}; + uint8_t ssap = 0; + uint8_t r_sap = 0; + uint8_t r_addr[MAC_SIZE]; + + pthread_mutex_lock(&ipcpi.alloc_lock); + + while (ipcpi.alloc_id != fd && ipcp_get_state() == IPCP_OPERATIONAL) + pthread_cond_timedwait(&ipcpi.alloc_cond, + &ipcpi.alloc_lock, + &ts); + + if (ipcp_get_state() != IPCP_OPERATIONAL) { + pthread_mutex_unlock(&ipcpi.alloc_lock); + return -1; + } + + ipcpi.alloc_id = -1; + pthread_cond_broadcast(&ipcpi.alloc_cond); + + pthread_mutex_unlock(&ipcpi.alloc_lock); pthread_rwlock_wrlock(ð_llc_data.flows_lock); -- cgit v1.2.3