1
0
mirror of https://github.com/systemd/systemd.git synced 2025-01-11 09:18:07 +03:00

Merge pull request #25142 from yuwata/network-fix-race-in-device-renaming-vs-dhcp

network,dhcp: fix theoretical race in device renaming
This commit is contained in:
Luca Boccassi 2022-10-31 21:01:57 +01:00 committed by GitHub
commit 7319adcd1b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 61 additions and 50 deletions

View File

@ -4,15 +4,11 @@
#include <net/ethernet.h>
#include <net/if_arp.h>
#include "sd-device.h"
#include "sd-id128.h"
#include "dhcp-identifier.h"
#include "netif-util.h"
#include "siphash24.h"
#include "sparse-endian.h"
#include "string-table.h"
#include "udev-util.h"
#define HASH_KEY SD_ID128_MAKE(80,11,8c,c2,fe,4a,03,ee,3e,d6,0c,6f,36,39,14,09)
#define APPLICATION_ID SD_ID128_MAKE(a5,0a,d1,12,bf,60,45,77,a2,fb,74,1a,b1,95,5b,03)
@ -207,48 +203,20 @@ int dhcp_identifier_set_duid(
}
int dhcp_identifier_set_iaid(
int ifindex,
sd_device *dev,
const struct hw_addr_data *hw_addr,
bool legacy_unstable_byteorder,
bool use_mac,
void *ret) {
/* name is a pointer to memory in the sd_device struct, so must
* have the same scope */
_cleanup_(sd_device_unrefp) sd_device *device = NULL;
const char *name = NULL;
uint32_t id32;
uint64_t id;
int r;
assert(ifindex > 0);
assert(hw_addr);
assert(ret);
if (udev_available() && !use_mac) {
/* udev should be around */
r = sd_device_new_from_ifindex(&device, ifindex);
if (r < 0)
return r;
r = sd_device_get_is_initialized(device);
if (r < 0)
return r;
if (r == 0)
/* not yet ready */
return -EBUSY;
r = device_is_renaming(device);
if (r < 0)
return r;
if (r > 0)
/* device is under renaming */
return -EBUSY;
name = net_get_persistent_name(device);
}
if (dev)
name = net_get_persistent_name(dev);
if (name)
id = siphash24(name, strlen(name), HASH_KEY.bytes);
else

View File

@ -1,6 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include "sd-device.h"
#include "sd-id128.h"
#include "ether-addr-util.h"
@ -66,10 +67,9 @@ int dhcp_identifier_set_duid(
struct duid *ret_duid,
size_t *ret_len);
int dhcp_identifier_set_iaid(
int ifindex,
sd_device *dev,
const struct hw_addr_data *hw_addr,
bool legacy_unstable_byteorder,
bool use_mac,
void *ret);
const char *duid_type_to_string(DUIDType t) _const_;

View File

@ -48,6 +48,8 @@ struct sd_dhcp6_client {
int event_priority;
int fd;
sd_device *dev;
DHCP6State state;
bool information_request;
usec_t information_request_time_usec;
@ -78,7 +80,7 @@ struct sd_dhcp6_client {
sd_dhcp6_client_callback_t callback;
void *userdata;
/* Ignore ifindex when generating iaid. See dhcp_identifier_set_iaid(). */
/* Ignore machine-ID when generating DUID. See dhcp_identifier_set_duid_en(). */
bool test_mode;
};

View File

@ -14,6 +14,7 @@
#include "sd-dhcp-client.h"
#include "alloc-util.h"
#include "device-util.h"
#include "dhcp-identifier.h"
#include "dhcp-internal.h"
#include "dhcp-lease-internal.h"
@ -77,8 +78,12 @@ struct sd_dhcp_client {
sd_event *event;
int event_priority;
sd_event_source *timeout_resend;
int ifindex;
char *ifname;
sd_device *dev;
int fd;
uint16_t port;
union sockaddr_union link;
@ -117,7 +122,7 @@ struct sd_dhcp_client {
usec_t start_delay;
int ip_service_type;
/* Ignore ifindex when generating iaid. See dhcp_identifier_set_iaid(). */
/* Ignore machine-ID when generating DUID. See dhcp_identifier_set_duid_en(). */
bool test_mode;
};
@ -420,9 +425,8 @@ static int dhcp_client_set_iaid_duid_internal(
if (iaid_set)
client->client_id.ns.iaid = htobe32(iaid);
else {
r = dhcp_identifier_set_iaid(client->ifindex, &client->hw_addr,
r = dhcp_identifier_set_iaid(client->dev, &client->hw_addr,
/* legacy_unstable_byteorder = */ true,
/* use_mac = */ client->test_mode,
&client->client_id.ns.iaid);
if (r < 0)
return log_dhcp_client_errno(client, r, "Failed to set IAID: %m");
@ -799,9 +803,8 @@ static int client_message_init(
client->client_id.type = 255;
r = dhcp_identifier_set_iaid(client->ifindex, &client->hw_addr,
r = dhcp_identifier_set_iaid(client->dev, &client->hw_addr,
/* legacy_unstable_byteorder = */ true,
/* use_mac = */ client->test_mode,
&client->client_id.ns.iaid);
if (r < 0)
return r;
@ -2153,6 +2156,12 @@ sd_event *sd_dhcp_client_get_event(sd_dhcp_client *client) {
return client->event;
}
int sd_dhcp_client_attach_device(sd_dhcp_client *client, sd_device *dev) {
assert_return(client, -EINVAL);
return device_unref_and_replace(client->dev, dev);
}
static sd_dhcp_client *dhcp_client_free(sd_dhcp_client *client) {
if (!client)
return NULL;
@ -2168,6 +2177,8 @@ static sd_dhcp_client *dhcp_client_free(sd_dhcp_client *client) {
sd_dhcp_client_detach_event(client);
sd_device_unref(client->dev);
set_free(client->req_opts);
free(client->hostname);
free(client->vendor_class_identifier);

View File

@ -11,6 +11,7 @@
#include "sd-dhcp6-client.h"
#include "alloc-util.h"
#include "device-util.h"
#include "dhcp-identifier.h"
#include "dhcp6-internal.h"
#include "dhcp6-lease-internal.h"
@ -299,9 +300,8 @@ static int client_ensure_iaid(sd_dhcp6_client *client) {
if (client->iaid_set)
return 0;
r = dhcp_identifier_set_iaid(client->ifindex, &client->hw_addr,
r = dhcp_identifier_set_iaid(client->dev, &client->hw_addr,
/* legacy_unstable_byteorder = */ true,
/* use_mac = */ client->test_mode,
&iaid);
if (r < 0)
return r;
@ -1446,6 +1446,12 @@ sd_event *sd_dhcp6_client_get_event(sd_dhcp6_client *client) {
return client->event;
}
int sd_dhcp6_client_attach_device(sd_dhcp6_client *client, sd_device *dev) {
assert_return(client, -EINVAL);
return device_unref_and_replace(client->dev, dev);
}
static sd_dhcp6_client *dhcp6_client_free(sd_dhcp6_client *client) {
if (!client)
return NULL;
@ -1461,6 +1467,8 @@ static sd_dhcp6_client *dhcp6_client_free(sd_dhcp6_client *client) {
client->fd = safe_close(client->fd);
sd_device_unref(client->dev);
free(client->req_opts);
free(client->fqdn);
free(client->mudurl);

View File

@ -144,10 +144,8 @@ static void test_dhcp_identifier_set_iaid(void) {
uint32_t iaid_legacy;
be32_t iaid;
assert_se(dhcp_identifier_set_iaid(42, &hw_addr, /* legacy = */ true,
/* use_mac = */ true, &iaid_legacy) >= 0);
assert_se(dhcp_identifier_set_iaid(42, &hw_addr, /* legacy = */ false,
/* use_mac = */ true, &iaid) >= 0);
assert_se(dhcp_identifier_set_iaid(NULL, &hw_addr, /* legacy = */ true, &iaid_legacy) >= 0);
assert_se(dhcp_identifier_set_iaid(NULL, &hw_addr, /* legacy = */ false, &iaid) >= 0);
/* we expect, that the MAC address was hashed. The legacy value is in native
* endianness. */
@ -169,7 +167,7 @@ static int check_options(uint8_t code, uint8_t len, const void *option, void *us
size_t duid_len;
assert_se(dhcp_identifier_set_duid_en(/* test_mode = */ true, &duid, &duid_len) >= 0);
assert_se(dhcp_identifier_set_iaid(42, &hw_addr, /* legacy = */ true, /* use_mac = */ true, &iaid) >= 0);
assert_se(dhcp_identifier_set_iaid(NULL, &hw_addr, /* legacy = */ true, &iaid) >= 0);
assert_se(len == sizeof(uint8_t) + sizeof(uint32_t) + duid_len);
assert_se(len == 19);

View File

@ -1357,6 +1357,10 @@ static int dhcp4_configure(Link *link) {
if (r < 0)
return log_link_debug_errno(link, r, "DHCPv4 CLIENT: Failed to attach event to DHCPv4 client: %m");
r = sd_dhcp_client_attach_device(link->dhcp_client, link->dev);
if (r < 0)
return log_link_debug_errno(link, r, "DHCPv4 CLIENT: Failed to attach device: %m");
r = sd_dhcp_client_set_mac(link->dhcp_client,
link->hw_addr.bytes,
link->bcast_addr.length > 0 ? link->bcast_addr.bytes : NULL,

View File

@ -594,6 +594,10 @@ static int dhcp6_configure(Link *link) {
if (r < 0)
return log_link_debug_errno(link, r, "DHCPv6 CLIENT: Failed to attach event: %m");
r = sd_dhcp6_client_attach_device(client, link->dev);
if (r < 0)
return log_link_debug_errno(link, r, "DHCPv6 CLIENT: Failed to attach device: %m");
r = dhcp6_set_identifier(link, client);
if (r < 0)
return log_link_debug_errno(link, r, "DHCPv6 CLIENT: Failed to set identifier: %m");

View File

@ -1410,6 +1410,18 @@ static int link_initialized(Link *link, sd_device *device) {
* or sysattrs) may be outdated. */
device_unref_and_replace(link->dev, device);
if (link->dhcp_client) {
r = sd_dhcp_client_attach_device(link->dhcp_client, link->dev);
if (r < 0)
log_link_warning_errno(link, r, "Failed to attach device to DHCPv4 client, ignoring: %m");
}
if (link->dhcp6_client) {
r = sd_dhcp6_client_attach_device(link->dhcp6_client, link->dev);
if (r < 0)
log_link_warning_errno(link, r, "Failed to attach device to DHCPv6 client, ignoring: %m");
}
r = link_set_sr_iov_ifindices(link);
if (r < 0)
log_link_warning_errno(link, r, "Failed to manage SR-IOV PF and VF ports, ignoring: %m");

View File

@ -25,6 +25,7 @@
#include <sys/types.h>
#include <stdbool.h>
#include "sd-device.h"
#include "sd-dhcp-lease.h"
#include "sd-dhcp-option.h"
#include "sd-event.h"
@ -337,6 +338,7 @@ int sd_dhcp_client_attach_event(
int64_t priority);
int sd_dhcp_client_detach_event(sd_dhcp_client *client);
sd_event *sd_dhcp_client_get_event(sd_dhcp_client *client);
int sd_dhcp_client_attach_device(sd_dhcp_client *client, sd_device *dev);
_SD_DEFINE_POINTER_CLEANUP_FUNC(sd_dhcp_client, sd_dhcp_client_unref);

View File

@ -23,6 +23,7 @@
#include <net/ethernet.h>
#include <sys/types.h>
#include "sd-device.h"
#include "sd-dhcp6-lease.h"
#include "sd-dhcp6-option.h"
#include "sd-event.h"
@ -279,6 +280,7 @@ int sd_dhcp6_client_attach_event(
int64_t priority);
int sd_dhcp6_client_detach_event(sd_dhcp6_client *client);
sd_event *sd_dhcp6_client_get_event(sd_dhcp6_client *client);
int sd_dhcp6_client_attach_device(sd_dhcp6_client *client, sd_device *dev);
sd_dhcp6_client *sd_dhcp6_client_ref(sd_dhcp6_client *client);
sd_dhcp6_client *sd_dhcp6_client_unref(sd_dhcp6_client *client);
int sd_dhcp6_client_new(sd_dhcp6_client **ret);