diff options
author | 2018-12-21 18:00:42 +0100 | |
---|---|---|
committer | 2018-12-21 18:00:42 +0100 | |
commit | 5848a9eb4d4c937012461d440eb798db265a65f9 (patch) | |
tree | b68ba747a1adfd1c8836823e7d6a7492b71f29ab | |
parent | tree-wide: make new/new0/malloc_multiply/reallocarray safe for size 0 (diff) | |
parent | dhcp6: don't enforce DUID content for sd_dhcp6_client_set_duid() (diff) | |
download | systemd-5848a9eb4d4c937012461d440eb798db265a65f9.tar.gz systemd-5848a9eb4d4c937012461d440eb798db265a65f9.tar.bz2 systemd-5848a9eb4d4c937012461d440eb798db265a65f9.zip |
Merge pull request #11210 from thom311/dhcp-set-client-id-no-inval
dhcp: don't enforce hardware address length for sd_dhcp_client_set_client_id()
-rw-r--r-- | src/libsystemd-network/dhcp-identifier.c | 8 | ||||
-rw-r--r-- | src/libsystemd-network/dhcp-identifier.h | 2 | ||||
-rw-r--r-- | src/libsystemd-network/sd-dhcp-client.c | 29 | ||||
-rw-r--r-- | src/libsystemd-network/sd-dhcp6-client.c | 10 |
4 files changed, 27 insertions, 22 deletions
diff --git a/src/libsystemd-network/dhcp-identifier.c b/src/libsystemd-network/dhcp-identifier.c index c768adeb6..07496adaa 100644 --- a/src/libsystemd-network/dhcp-identifier.c +++ b/src/libsystemd-network/dhcp-identifier.c @@ -18,13 +18,19 @@ #define APPLICATION_ID SD_ID128_MAKE(a5,0a,d1,12,bf,60,45,77,a2,fb,74,1a,b1,95,5b,03) #define USEC_2000 ((usec_t) 946684800000000) /* 2000-01-01 00:00:00 UTC */ -int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len) { +int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len, bool strict) { struct duid d; assert_cc(sizeof(d.raw) >= MAX_DUID_LEN); if (duid_len > MAX_DUID_LEN) return -EINVAL; + if (!strict) { + /* Strict validation is not requested. We only ensure that the + * DUID is not too long. */ + return 0; + } + switch (duid_type) { case DUID_TYPE_LLT: if (duid_len <= sizeof(d.llt)) diff --git a/src/libsystemd-network/dhcp-identifier.h b/src/libsystemd-network/dhcp-identifier.h index a544f38ab..b3115125d 100644 --- a/src/libsystemd-network/dhcp-identifier.h +++ b/src/libsystemd-network/dhcp-identifier.h @@ -52,7 +52,7 @@ struct duid { }; } _packed_; -int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len); +int dhcp_validate_duid_len(uint16_t duid_type, size_t duid_len, bool strict); int dhcp_identifier_set_duid_llt(struct duid *duid, usec_t t, const uint8_t *addr, size_t addr_len, uint16_t arp_type, size_t *len); int dhcp_identifier_set_duid_ll(struct duid *duid, const uint8_t *addr, size_t addr_len, uint16_t arp_type, size_t *len); int dhcp_identifier_set_duid_en(struct duid *duid, size_t *len); diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c index 3bdd584bb..2d7ffd22c 100644 --- a/src/libsystemd-network/sd-dhcp-client.c +++ b/src/libsystemd-network/sd-dhcp-client.c @@ -300,27 +300,22 @@ int sd_dhcp_client_set_client_id( assert_return(data, -EINVAL); assert_return(data_len > 0 && data_len <= MAX_CLIENT_ID_LEN, -EINVAL); - switch (type) { - - case ARPHRD_ETHER: - if (data_len != ETH_ALEN) - return -EINVAL; - break; - - case ARPHRD_INFINIBAND: - if (data_len != INFINIBAND_ALEN) - return -EINVAL; - break; - - default: - break; - } - if (client->client_id_len == data_len + sizeof(client->client_id.type) && client->client_id.type == type && memcmp(&client->client_id.raw.data, data, data_len) == 0) return 0; + /* For hardware types, log debug message about unexpected data length. + * + * Note that infiniband's INFINIBAND_ALEN is 20 bytes long, but only + * last last 8 bytes of the address are stable and suitable to put into + * the client-id. The caller is advised to account for that. */ + if ((type == ARPHRD_ETHER && data_len != ETH_ALEN) || + (type == ARPHRD_INFINIBAND && data_len != 8)) + log_dhcp_client(client, "Changing client ID to hardware type %u with " + "unexpected address length %zu", + type, data_len); + if (!IN_SET(client->state, DHCP_STATE_INIT, DHCP_STATE_STOPPED)) { log_dhcp_client(client, "Changing client ID on running DHCP " "client, restarting"); @@ -361,7 +356,7 @@ static int dhcp_client_set_iaid_duid_internal( assert_return(duid_len == 0 || duid != NULL, -EINVAL); if (duid != NULL) { - r = dhcp_validate_duid_len(duid_type, duid_len); + r = dhcp_validate_duid_len(duid_type, duid_len, true); if (r < 0) return r; } diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c index 8ff4585f6..593ffd1b6 100644 --- a/src/libsystemd-network/sd-dhcp6-client.c +++ b/src/libsystemd-network/sd-dhcp6-client.c @@ -206,9 +206,13 @@ static int dhcp6_client_set_duid_internal( assert_return(IN_SET(client->state, DHCP6_STATE_STOPPED), -EBUSY); if (duid != NULL) { - r = dhcp_validate_duid_len(duid_type, duid_len); - if (r < 0) - return r; + r = dhcp_validate_duid_len(duid_type, duid_len, true); + if (r < 0) { + r = dhcp_validate_duid_len(duid_type, duid_len, false); + if (r < 0) + return r; + log_dhcp6_client(client, "Setting DUID of type %u with unexpected content", duid_type); + } client->duid.type = htobe16(duid_type); memcpy(&client->duid.raw.data, duid, duid_len); |