From 1dcd82a7bf4906b6d35cd742a272eede63a3c2b7 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 27 Jan 2022 00:17:23 +0900 Subject: [PATCH] sd-dhcp-server: set DHCPLease::server before hashmap_put() Otherwise, if the second push is failed, then the first hashmap contains dirty entry. Also, this makes hashmap_remove_value() used when removing leases to make not wrong lease is removed from the hashmap. Note, this just hide the root cause of the issue #22253, which will be fixed in later commit. Fixes #22253. (cherry picked from commit 8a7d048d1ddb8916482f1422405d3e0e4bccb279) --- src/libsystemd-network/sd-dhcp-server.c | 34 ++++++++++--------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c index d1a0bbd0b7..1ca7fa3412 100644 --- a/src/libsystemd-network/sd-dhcp-server.c +++ b/src/libsystemd-network/sd-dhcp-server.c @@ -29,19 +29,10 @@ static DHCPLease *dhcp_lease_free(DHCPLease *lease) { return NULL; if (lease->server) { - DHCPLease *e; - - e = hashmap_get(lease->server->bound_leases_by_client_id, &lease->client_id); - if (e == lease) { - hashmap_remove(lease->server->bound_leases_by_address, UINT32_TO_PTR(lease->address)); - hashmap_remove(lease->server->bound_leases_by_client_id, &lease->client_id); - } - - e = hashmap_get(lease->server->static_leases_by_client_id, &lease->client_id); - if (e == lease) { - hashmap_remove(lease->server->static_leases_by_address, UINT32_TO_PTR(lease->address)); - hashmap_remove(lease->server->static_leases_by_client_id, &lease->client_id); - } + hashmap_remove_value(lease->server->bound_leases_by_address, UINT32_TO_PTR(lease->address), lease); + hashmap_remove_value(lease->server->bound_leases_by_client_id, &lease->client_id, lease); + hashmap_remove_value(lease->server->static_leases_by_address, UINT32_TO_PTR(lease->address), lease); + hashmap_remove_value(lease->server->static_leases_by_client_id, &lease->client_id, lease); } free(lease->client_id.data); @@ -1068,7 +1059,10 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, siz log_dhcp_server(server, "ACK (0x%x)", be32toh(req->message->xid)); - dhcp_lease_free(hashmap_remove(server->bound_leases_by_client_id, &lease->client_id)); + dhcp_lease_free(hashmap_get(server->bound_leases_by_client_id, &lease->client_id)); + + lease->server = server; /* This must be set just before hashmap_put(). */ + r = hashmap_ensure_put(&server->bound_leases_by_client_id, &dhcp_lease_hash_ops, &lease->client_id, lease); if (r < 0) return log_dhcp_server_errno(server, r, "Could not save lease: %m"); @@ -1077,7 +1071,6 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, siz if (r < 0) return log_dhcp_server_errno(server, r, "Could not save lease: %m"); - lease->server = server; TAKE_PTR(lease); if (server->callback) @@ -1117,6 +1110,8 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, siz log_dhcp_server(server, "ACK (0x%x)", be32toh(req->message->xid)); + lease->server = server; /* This must be set just before hashmap_put(). */ + r = hashmap_ensure_put(&server->bound_leases_by_client_id, &dhcp_lease_hash_ops, &lease->client_id, lease); if (r < 0) return log_dhcp_server_errno(server, r, "Could not save lease: %m"); @@ -1124,7 +1119,6 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message, siz if (r < 0) return log_dhcp_server_errno(server, r, "Could not save lease: %m"); - lease->server = server; TAKE_PTR(new_lease); if (server->callback) @@ -1553,13 +1547,10 @@ int sd_dhcp_server_set_static_lease( .data = data, }; - dhcp_lease_free(hashmap_remove(server->static_leases_by_client_id, &c)); + dhcp_lease_free(hashmap_get(server->static_leases_by_client_id, &c)); return 0; } - if (hashmap_contains(server->static_leases_by_address, UINT32_TO_PTR(address->s_addr))) - return -EEXIST; - lease = new(DHCPLease, 1); if (!lease) return -ENOMEM; @@ -1574,6 +1565,8 @@ int sd_dhcp_server_set_static_lease( if (!lease->client_id.data) return -ENOMEM; + lease->server = server; /* This must be set just before hashmap_put(). */ + r = hashmap_ensure_put(&server->static_leases_by_client_id, &dhcp_lease_hash_ops, &lease->client_id, lease); if (r < 0) return r; @@ -1581,7 +1574,6 @@ int sd_dhcp_server_set_static_lease( if (r < 0) return r; - lease->server = server; TAKE_PTR(lease); return 0; }