diff --git a/adapt-bugfix-allow-binding-mac-with-ipv6.patch b/adapt-bugfix-allow-binding-mac-with-ipv6.patch new file mode 100644 index 0000000000000000000000000000000000000000..e6225b26e41fae9fad14c49871d303848251e9ee --- /dev/null +++ b/adapt-bugfix-allow-binding-mac-with-ipv6.patch @@ -0,0 +1,148 @@ +From fc7ad95ef2ffd09098a9687f08efb9ef39f5d830 Mon Sep 17 00:00:00 2001 +From: huyizhen +Date: Thu, 13 Feb 2025 22:41:17 +0800 +Subject: [PATCH] adapt bugfix allow binding mac with ipv6 + +fix bind-mac-with-ip6 function failure. +--- + src/rfc3315.c | 62 +++++++++++++++++---------------------------------- + 1 file changed, 20 insertions(+), 42 deletions(-) + +diff --git a/src/rfc3315.c b/src/rfc3315.c +index cdb4b64..e6f3664 100644 +--- a/src/rfc3315.c ++++ b/src/rfc3315.c +@@ -48,9 +48,8 @@ static int build_ia(struct state *state, int *t1cntr); + static void end_ia(int t1cntr, unsigned int min_time, int do_fuzz); + static void mark_context_used(struct state *state, struct in6_addr *addr); + static void mark_config_used(struct dhcp_context *context, struct in6_addr *addr); +-static int check_address(struct state *state, struct in6_addr *addr); +-static int check_and_try_preempte_address(struct state *state, struct in6_addr *addr, time_t now, struct dhcp_config *config); +-static int config_valid(struct dhcp_config *config, struct dhcp_context *context, struct in6_addr *addr, struct state *state, time_t now); ++static int check_address(struct dhcp_config *config, struct state *state, struct in6_addr *addr, time_t now, int preempte); ++static int config_valid(struct dhcp_config *config, struct dhcp_context *context, struct in6_addr *addr, struct state *state, time_t now, int preempte); + static struct addrlist *config_implies(struct dhcp_config *config, struct dhcp_context *context, struct in6_addr *addr); + static void add_address(struct state *state, struct dhcp_context *context, unsigned int lease_time, void *ia_option, + unsigned int *min_time, struct in6_addr *addr, time_t now); +@@ -681,7 +680,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, unsigned char *inbu + /* If the client asks for an address on the same network as a configured address, + offer the configured address instead, to make moving to newly-configured + addresses automatic. */ +- if (!(c->flags & CONTEXT_CONF_USED) && config_valid(config, c, &addr, state, now)) ++ if (!(c->flags & CONTEXT_CONF_USED) && config_valid(config, c, &addr, state, now, 0)) + { + req_addr = addr; + mark_config_used(c, &addr); +@@ -690,7 +689,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, unsigned char *inbu + } + else if (!(c = address6_available(state->context, &req_addr, solicit_tags, plain_range))) + continue; /* not an address we're allowed */ +- else if (!check_address(state, &req_addr)) ++ else if (!check_address(config, state, &req_addr, now, 0)) + continue; /* address leased elsewhere */ + + /* add address to output packet */ +@@ -705,8 +704,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, unsigned char *inbu + for (c = state->context; c; c = c->current) + if (!(c->flags & CONTEXT_CONF_USED) && + match_netid(c->filter, solicit_tags, plain_range) && +- config_valid(config, c, &addr, state, now) && +- check_and_try_preempte_address(state, &addr, now, config)) ++ config_valid(config, c, &addr, state, now, 1)) + { + mark_config_used(state->context, &addr); + if (have_config(config, CONFIG_TIME)) +@@ -862,7 +860,7 @@ static int dhcp6_no_relay(struct state *state, int msg_type, unsigned char *inbu + put_opt6_string(_("address unavailable")); + end_opt6(o1); + } +- else if (!check_address(state, &req_addr)) ++ else if (!check_address(config, state, &req_addr, now, 0)) + { + /* Address leased to another DUID/IAID */ + o1 = new_opt6(OPTION6_STATUS_CODE); +@@ -1319,37 +1317,6 @@ static int dhcp6_no_relay(struct state *state, int msg_type, unsigned char *inbu + + } + +-static int check_and_try_preempte_address(struct state *state, struct in6_addr *addr, time_t now, struct dhcp_config *config) +-{ +- struct dhcp_lease *lease; +- +- if (!(lease = lease6_find_by_addr(addr, 128, 0))) +- { +- return 1; +- } +- +- +- if(daemon->bind_mac_with_ip6) { +- // break rfc3315 here +- // bind mac address with a lease +- if ((state->mac) && !(config->flags & CONFIG_CLID) && +- config_has_mac(config, state->mac, state->mac_len, state->mac_type)) { +- lease_prune(lease, now); +- return 1; +- } +- } +- +- // what rfc3315 do +- if (lease->clid_len != state->clid_len || +- memcmp(lease->clid, state->clid, state->clid_len) != 0 || +- lease->iaid != state->iaid) +- { +- return 0; +- } +- +- return 1; +-} +- + static struct dhcp_netid *add_options(struct state *state, int do_refresh) + { + void *oro; +@@ -1760,13 +1727,24 @@ static void mark_config_used(struct dhcp_context *context, struct in6_addr *addr + } + + /* make sure address not leased to another CLID/IAID */ +-static int check_address(struct state *state, struct in6_addr *addr) ++static int check_address(struct dhcp_config *config, struct state *state, struct in6_addr *addr, time_t now, int preempte) + { + struct dhcp_lease *lease; + + if (!(lease = lease6_find_by_addr(addr, 128, 0))) + return 1; + ++ if (preempte && daemon->bind_mac_with_ip6) { ++ // break rfc3315 here ++ // bind mac address with a lease ++ if ((state->mac) && !(config->flags & CONFIG_CLID) && ++ config_has_mac(config, state->mac, state->mac_len, state->mac_type)) { ++ lease_prune(lease, now); ++ return 1; ++ } ++ } ++ ++ // what rfc3315 do + if (lease->clid_len != state->clid_len || + memcmp(lease->clid, state->clid, state->clid_len) != 0 || + lease->iaid != state->iaid) +@@ -1806,7 +1784,7 @@ static struct addrlist *config_implies(struct dhcp_config *config, struct dhcp_c + return NULL; + } + +-static int config_valid(struct dhcp_config *config, struct dhcp_context *context, struct in6_addr *addr, struct state *state, time_t now) ++static int config_valid(struct dhcp_config *config, struct dhcp_context *context, struct in6_addr *addr, struct state *state, time_t now, int preempte) + { + u64 addrpart, i, addresses; + struct addrlist *addr_list; +@@ -1840,7 +1818,7 @@ static int config_valid(struct dhcp_config *config, struct dhcp_context *context + { + setaddr6part(addr, addrpart+i); + +- if (check_address(state, addr)) ++ if (check_address(config, state, addr, now, preempte)) + return 1; + } + } +-- +2.33.0 + diff --git a/backport-Fix-possible-SIGSEGV-in-bpf.c.patch b/backport-Fix-possible-SIGSEGV-in-bpf.c.patch new file mode 100644 index 0000000000000000000000000000000000000000..4332495e7a2f31c766eb4cb51601314f47b4d555 --- /dev/null +++ b/backport-Fix-possible-SIGSEGV-in-bpf.c.patch @@ -0,0 +1,215 @@ +From 535be2f5d355d61332043c7fdc06e095e52a3937 Mon Sep 17 00:00:00 2001 +From: Simon Kelley +Date: Sat, 8 Feb 2025 22:58:42 +0000 +Subject: [PATCH] Fix possible SIGSEGV in bpf.c + +Conflict:Context adaptation +Reference:https://thekelleys.org.uk/gitweb/?p=dnsmasq.git;a=patch;h=535be2f5d355d61332043c7fdc06e095e52a3937 + +--- + src/bpf.c | 170 ++++++++++++++++++++++++++---------------------------- + 1 file changed, 83 insertions(+), 87 deletions(-) + +diff --git a/src/bpf.c b/src/bpf.c +index 15c42fc..4620b3f 100644 +--- a/src/bpf.c ++++ b/src/bpf.c +@@ -126,112 +126,108 @@ int iface_enumerate(int family, void *parm, int (*callback)()) + + for (addrs = head; addrs; addrs = addrs->ifa_next) + { +- if (addrs->ifa_addr->sa_family == family) +- { +- int iface_index = if_nametoindex(addrs->ifa_name); +- +- if (iface_index == 0 || !addrs->ifa_addr || +- (!addrs->ifa_netmask && family != AF_LINK)) +- continue; ++ int iface_index = if_nametoindex(addrs->ifa_name); + +- if (family == AF_INET) +- { +- struct in_addr addr, netmask, broadcast; +- addr = ((struct sockaddr_in *) addrs->ifa_addr)->sin_addr; ++ if (iface_index == 0 || !addrs->ifa_addr || ++ addrs->ifa_addr->sa_family != family || ++ (!addrs->ifa_netmask && family != AF_LINK)) ++ continue; ++ if (family == AF_INET) ++ { ++ struct in_addr addr, netmask, broadcast; ++ addr = ((struct sockaddr_in *) addrs->ifa_addr)->sin_addr; + #ifdef HAVE_BSD_NETWORK +- if (del_family == AF_INET && del_addr.addr4.s_addr == addr.s_addr) +- continue; ++ if (del_family == AF_INET && del_addr.addr4.s_addr == addr.s_addr) ++ continue; + #endif +- netmask = ((struct sockaddr_in *) addrs->ifa_netmask)->sin_addr; +- if (addrs->ifa_broadaddr) +- broadcast = ((struct sockaddr_in *) addrs->ifa_broadaddr)->sin_addr; +- else +- broadcast.s_addr = 0; +- if (!((*callback)(addr, iface_index, NULL, netmask, broadcast, parm))) +- goto err; +- } +- else if (family == AF_INET6) +- { +- struct in6_addr *addr = &((struct sockaddr_in6 *) addrs->ifa_addr)->sin6_addr; +- unsigned char *netmask = (unsigned char *) &((struct sockaddr_in6 *) addrs->ifa_netmask)->sin6_addr; +- int scope_id = ((struct sockaddr_in6 *) addrs->ifa_addr)->sin6_scope_id; +- int i, j, prefix = 0; +- u32 valid = 0xffffffff, preferred = 0xffffffff; +- int flags = 0; ++ netmask = ((struct sockaddr_in *) addrs->ifa_netmask)->sin_addr; ++ if (addrs->ifa_broadaddr) ++ broadcast = ((struct sockaddr_in *) addrs->ifa_broadaddr)->sin_addr; ++ else ++ broadcast.s_addr = 0; ++ if (!callback.af_inet(addr, iface_index, NULL, netmask, broadcast, parm)) ++ goto err; ++ } ++ else if (family == AF_INET6) ++ { ++ struct in6_addr *addr = &((struct sockaddr_in6 *) addrs->ifa_addr)->sin6_addr; ++ unsigned char *netmask = (unsigned char *) &((struct sockaddr_in6 *) addrs->ifa_netmask)->sin6_addr; ++ int scope_id = ((struct sockaddr_in6 *) addrs->ifa_addr)->sin6_scope_id; ++ int i, j, prefix = 0; ++ u32 valid = 0xffffffff, preferred = 0xffffffff; ++ int flags = 0; + #ifdef HAVE_BSD_NETWORK +- if (del_family == AF_INET6 && IN6_ARE_ADDR_EQUAL(&del_addr.addr6, addr)) +- continue; ++ if (del_family == AF_INET6 && IN6_ARE_ADDR_EQUAL(&del_addr.addr6, addr)) ++ continue; + #endif + #if defined(HAVE_BSD_NETWORK) && !defined(__APPLE__) +- struct in6_ifreq ifr6; +- +- memset(&ifr6, 0, sizeof(ifr6)); +- safe_strncpy(ifr6.ifr_name, addrs->ifa_name, sizeof(ifr6.ifr_name)); ++ struct in6_ifreq ifr6; ++ ++ memset(&ifr6, 0, sizeof(ifr6)); ++ safe_strncpy(ifr6.ifr_name, addrs->ifa_name, sizeof(ifr6.ifr_name)); ++ ++ ifr6.ifr_addr = *((struct sockaddr_in6 *) addrs->ifa_addr); ++ if (fd != -1 && ioctl(fd, SIOCGIFAFLAG_IN6, &ifr6) != -1) ++ { ++ if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_TENTATIVE) ++ flags |= IFACE_TENTATIVE; + +- ifr6.ifr_addr = *((struct sockaddr_in6 *) addrs->ifa_addr); +- if (fd != -1 && ioctl(fd, SIOCGIFAFLAG_IN6, &ifr6) != -1) +- { +- if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_TENTATIVE) +- flags |= IFACE_TENTATIVE; +- +- if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DEPRECATED) +- flags |= IFACE_DEPRECATED; ++ if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DEPRECATED) ++ flags |= IFACE_DEPRECATED; + + #ifdef IN6_IFF_TEMPORARY +- if (!(ifr6.ifr_ifru.ifru_flags6 & (IN6_IFF_AUTOCONF | IN6_IFF_TEMPORARY))) +- flags |= IFACE_PERMANENT; ++ if (!(ifr6.ifr_ifru.ifru_flags6 & (IN6_IFF_AUTOCONF | IN6_IFF_TEMPORARY))) ++ flags |= IFACE_PERMANENT; + #endif + + #ifdef IN6_IFF_PRIVACY +- if (!(ifr6.ifr_ifru.ifru_flags6 & (IN6_IFF_AUTOCONF | IN6_IFF_PRIVACY))) +- flags |= IFACE_PERMANENT; +-#endif +- } +- +- ifr6.ifr_addr = *((struct sockaddr_in6 *) addrs->ifa_addr); +- if (fd != -1 && ioctl(fd, SIOCGIFALIFETIME_IN6, &ifr6) != -1) +- { +- valid = ifr6.ifr_ifru.ifru_lifetime.ia6t_vltime; +- preferred = ifr6.ifr_ifru.ifru_lifetime.ia6t_pltime; +- } ++ if (!(ifr6.ifr_ifru.ifru_flags6 & (IN6_IFF_AUTOCONF | IN6_IFF_PRIVACY))) ++ flags |= IFACE_PERMANENT; + #endif +- +- for (i = 0; i < IN6ADDRSZ; i++, prefix += 8) +- if (netmask[i] != 0xff) +- break; +- +- if (i != IN6ADDRSZ && netmask[i]) +- for (j = 7; j > 0; j--, prefix++) +- if ((netmask[i] & (1 << j)) == 0) +- break; +- +- /* voodoo to clear interface field in address */ +- if (!option_bool(OPT_NOWILD) && IN6_IS_ADDR_LINKLOCAL(addr)) +- { +- addr->s6_addr[2] = 0; +- addr->s6_addr[3] = 0; +- } +- +- if (!((*callback)(addr, prefix, scope_id, iface_index, flags, +- (int) preferred, (int)valid, parm))) +- goto err; +- } + +-#ifdef HAVE_DHCP6 +- else if (family == AF_LINK) +- { +- /* Assume ethernet again here */ +- struct sockaddr_dl *sdl = (struct sockaddr_dl *) addrs->ifa_addr; +- if (sdl->sdl_alen != 0 && +- !((*callback)(iface_index, ARPHRD_ETHER, LLADDR(sdl), sdl->sdl_alen, parm))) +- goto err; ++ ifr6.ifr_addr = *((struct sockaddr_in6 *) addrs->ifa_addr); ++ if (fd != -1 && ioctl(fd, SIOCGIFALIFETIME_IN6, &ifr6) != -1) ++ { ++ valid = ifr6.ifr_ifru.ifru_lifetime.ia6t_vltime; ++ preferred = ifr6.ifr_ifru.ifru_lifetime.ia6t_pltime; + } +-#endif ++#endif ++ ++ for (i = 0; i < IN6ADDRSZ; i++, prefix += 8) ++ if (netmask[i] != 0xff) ++ break; ++ ++ if (i != IN6ADDRSZ && netmask[i]) ++ for (j = 7; j > 0; j--, prefix++) ++ if ((netmask[i] & (1 << j)) == 0) ++ break; ++ ++ /* voodoo to clear interface field in address */ ++ if (!option_bool(OPT_NOWILD) && IN6_IS_ADDR_LINKLOCAL(addr)) ++ { ++ addr->s6_addr[2] = 0; ++ addr->s6_addr[3] = 0; ++ } ++ ++ if (!callback.af_inet6(addr, prefix, scope_id, iface_index, flags, ++ (unsigned int) preferred, (unsigned int)valid, parm)) ++ goto err; ++ } ++ ++#ifdef HAVE_DHCP6 ++ else if (family == AF_LINK) ++ { ++ /* Assume ethernet again here */ ++ struct sockaddr_dl *sdl = (struct sockaddr_dl *) addrs->ifa_addr; ++ if (sdl->sdl_alen != 0 && ++ !callback.af_local(iface_index, ARPHRD_ETHER, LLADDR(sdl), sdl->sdl_alen, parm)) ++ goto err; + } ++#endif + } + + ret = 1; +- ++ + err: + errsave = errno; + freeifaddrs(head); +-- +2.33.0 + diff --git a/backport-Fix-potential-memory-leak.patch b/backport-Fix-potential-memory-leak.patch new file mode 100644 index 0000000000000000000000000000000000000000..9ad0a7be5fa554a08a7b7fde2600cd81e6ac375d --- /dev/null +++ b/backport-Fix-potential-memory-leak.patch @@ -0,0 +1,61 @@ +From efb8f104502c0d8efcd45101a767225042ef21d3 Mon Sep 17 00:00:00 2001 +From: Brian Haley +Date: Thu, 23 Jan 2025 18:26:45 -0500 +Subject: [PATCH] Fix potential memory leak + +When a new IPv6 address is being added to a dhcp_config +struct, if there is anything invalid regarding the prefix +it looks like there is a potential memory leak. +ret_err_free() should be used to free it. + +Also, the new addrlist struct is being linked into +the existing addr6 list in the dhcp_config before the +validity check, it is best to defer this insertion +until later so an invalid entry is not present, since +the CONFIG_ADDR6 flag might not have been set yet. + +Signed-off-by: Brian Haley + +Reference:https://thekelleys.org.uk/gitweb/?p=dnsmasq.git;a=commit;h=efb8f104502c0d8efcd45101a767225042ef21d3 +Conflict:NA + +--- + src/option.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/option.c b/src/option.c +index 16afb13..f3dee87 100644 +--- a/src/option.c ++++ b/src/option.c +@@ -4043,10 +4043,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma + } + + new_addr = opt_malloc(sizeof(struct addrlist)); +- new_addr->next = new->addr6; + new_addr->flags = 0; + new_addr->addr.addr6 = in6; +- new->addr6 = new_addr; + + if (pref) + { +@@ -4057,7 +4055,7 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma + ((((u64)1<<(128-new_addr->prefixlen))-1) & addrpart) != 0) + { + dhcp_config_free(new); +- ret_err(_("bad IPv6 prefix")); ++ ret_err_free(_("bad IPv6 prefix"), new_addr); + } + + new_addr->flags |= ADDRLIST_PREFIX; +@@ -4071,6 +4069,8 @@ static int one_opt(int option, char *arg, char *errstr, char *gen_err, int comma + if (i == 8) + new_addr->flags |= ADDRLIST_WILDCARD; + ++ new_addr->next = new->addr6; ++ new->addr6 = new_addr; + new->flags |= CONFIG_ADDR6; + } + #endif +-- +2.33.0 + diff --git a/backport-Update-DNS-records-after-pruning-DHCP-leases.patch b/backport-Update-DNS-records-after-pruning-DHCP-leases.patch new file mode 100644 index 0000000000000000000000000000000000000000..867d8a16707e508b5a8630745db5a89e68b276fd --- /dev/null +++ b/backport-Update-DNS-records-after-pruning-DHCP-leases.patch @@ -0,0 +1,34 @@ +From 80498fab01342243707a482f9b42c38a7c564026 Mon Sep 17 00:00:00 2001 +From: Erik Karlsson +Date: Mon, 29 Apr 2024 20:44:13 +0200 +Subject: [PATCH] Update DNS records after pruning DHCP leases + +Not doing so can result in a use after free since the name for DHCP +derived DNS records is represented as a pointer into the DHCP lease +table. Update will only happen when necessary since lease_update_dns +tests internally on dns_dirty and the force argument is zero. + +Signed-off-by: Erik Karlsson + +Reference:https://thekelleys.org.uk/gitweb/?p=dnsmasq.git;a=commit;h=80498fab01342243707a482f9b42c38a7c564026 +Conflict:NA + +--- + src/dnsmasq.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/dnsmasq.c b/src/dnsmasq.c +index c14240e..48e402f 100644 +--- a/src/dnsmasq.c ++++ b/src/dnsmasq.c +@@ -1517,6 +1517,7 @@ static void async_event(int pipe, time_t now) + { + lease_prune(NULL, now); + lease_update_file(now); ++ lease_update_dns(0); + } + #ifdef HAVE_DHCP6 + else if (daemon->doing_ra) +-- +2.33.0 + diff --git a/dnsmasq.spec b/dnsmasq.spec index 5e7ce94084f28f3c2fc2f82085b4f95a3890fd22..88387d52b88d17fb7225f702ad216afdb20319a9 100644 --- a/dnsmasq.spec +++ b/dnsmasq.spec @@ -1,6 +1,6 @@ Name: dnsmasq Version: 2.86 -Release: 10 +Release: 11 Summary: Dnsmasq provides network infrastructure for small networks License: GPLv2 or GPLv3 URL: http://www.thekelleys.org.uk/dnsmasq/ @@ -51,6 +51,11 @@ Patch40: backport-CVE-2023-49441-Fix-standalone-SHA256-implementation.pat Patch41: backport-Fix-crash-when-reloading-DHCP-config-on-SIGHUP.patch Patch42: backport-Fix-out-of-bounds-heap-read-in-order_qsort.patch Patch43: backport-Fix-buffer-overflow-when-configured-lease-change-scr.patch +Patch44: backport-Update-DNS-records-after-pruning-DHCP-leases.patch +Patch45: backport-Fix-potential-memory-leak.patch +Patch46: backport-Fix-possible-SIGSEGV-in-bpf.c.patch + +Patch9000: adapt-bugfix-allow-binding-mac-with-ipv6.patch BuildRequires: gcc BuildRequires: dbus-devel pkgconfig libidn2-devel nettle-devel systemd @@ -140,6 +145,15 @@ install -Dpm644 %{SOURCE2} $RPM_BUILD_ROOT%{_sysusersdir}/dnsmasq.conf %{_mandir}/man8/dnsmasq* %changelog +* Fri Mar 21 2025 lingsheng - 2.86-11 +- Type:bugfix +- CVE:NA +- SUG:NA +- DESC:Update DNS records after pruning DHCP leases + Fix potential memory leak + Fix possible SIGSEGV in bpf.c + adapt bugfix allow binding mac with ipv6 + * Thu Dec 12 2024 huyizhen - 2.86-10 - Type:bugfix - CVE: