git: bc06c51419b3 - main - netinet: correct SIOCDIFADDR{,_IN6} calls to use {,in6_}ifreq
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 22 Jul 2024 14:22:38 UTC
The branch main has been updated by def:
URL: https://cgit.FreeBSD.org/src/commit/?id=bc06c51419b338c3d6efa6543308f9905c12c79b
commit bc06c51419b338c3d6efa6543308f9905c12c79b
Author: Konrad Witaszczyk <def@FreeBSD.org>
AuthorDate: 2024-06-27 12:54:14 +0000
Commit: Konrad Witaszczyk <def@FreeBSD.org>
CommitDate: 2024-07-22 14:17:21 +0000
netinet: correct SIOCDIFADDR{,_IN6} calls to use {,in6_}ifreq
The SIOCDIFADDR{,_IN6} ioctls take an ifreq structure object, not an
ifaliasreq/in_aliasreq/in6_aliasreq structure object, as their argument.
As opposed to ifaliasreq/in_aliasreq/in6_aliasreq used by
SIOCAIFADDR{,_IN6}, the ifreq/in6_ifreq structures used by the
SIOCDIFADDR{,_IN6} ioctls do not include a separate field for a
broadcast address and other values required to add an address to a
network interface with SIOCAIFADDR{,_IN6}.
Whilst this issue is not specific to CHERI-extended architectures, it
was first observed on CheriBSD running on Arm Morello. For example,
incorrect calls using the in6_aliasreq object result in CHERI capability
violations. A pointer to the ifra_addr field in in6_aliasreq cast to the
ifru_addr union member of in6_ifreq results in bounds being set to the
union's larger size. Such bounds exceed the bounds of of in6_aliasreq
object and the bounds-setting instruction clears a tag of the object's
capability.
Reviewed by: brooks, kp, oshogbo
Accepted by: oshogbo (mentor)
Reported by: CHERI
Obtained from: CheriBSD
Differential Revision: https://reviews.freebsd.org/D46016
---
sys/net/if.c | 6 ++----
sys/netinet/in.c | 6 ++----
sys/netlink/route/iface.c | 6 +++---
3 files changed, 7 insertions(+), 11 deletions(-)
diff --git a/sys/net/if.c b/sys/net/if.c
index 604a93aa7cba..c71643a41bc5 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -1037,12 +1037,10 @@ if_purgeaddrs(struct ifnet *ifp)
#ifdef INET
/* XXX: Ugly!! ad hoc just for INET */
if (ifa->ifa_addr->sa_family == AF_INET) {
- struct ifaliasreq ifr;
+ struct ifreq ifr;
bzero(&ifr, sizeof(ifr));
- ifr.ifra_addr = *ifa->ifa_addr;
- if (ifa->ifa_dstaddr)
- ifr.ifra_broadaddr = *ifa->ifa_dstaddr;
+ ifr.ifr_addr = *ifa->ifa_addr;
if (in_control(NULL, SIOCDIFADDR, (caddr_t)&ifr, ifp,
NULL) == 0)
continue;
diff --git a/sys/netinet/in.c b/sys/netinet/in.c
index cc2f37863ea1..c78f0f5758f7 100644
--- a/sys/netinet/in.c
+++ b/sys/netinet/in.c
@@ -1222,7 +1222,7 @@ in_ifscrub_all(void)
{
struct ifnet *ifp;
struct ifaddr *ifa, *nifa;
- struct ifaliasreq ifr;
+ struct ifreq ifr;
IFNET_RLOCK();
CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) {
@@ -1237,9 +1237,7 @@ in_ifscrub_all(void)
* cleanly remove addresses and everything attached.
*/
bzero(&ifr, sizeof(ifr));
- ifr.ifra_addr = *ifa->ifa_addr;
- if (ifa->ifa_dstaddr)
- ifr.ifra_broadaddr = *ifa->ifa_dstaddr;
+ ifr.ifr_addr = *ifa->ifa_addr;
(void)in_control(NULL, SIOCDIFADDR, (caddr_t)&ifr,
ifp, NULL);
}
diff --git a/sys/netlink/route/iface.c b/sys/netlink/route/iface.c
index 81db54ab12d4..7d33c89a396a 100644
--- a/sys/netlink/route/iface.c
+++ b/sys/netlink/route/iface.c
@@ -1194,17 +1194,17 @@ static int
handle_deladdr_inet(struct nlmsghdr *hdr, struct nl_parsed_ifa *attrs,
if_t ifp, struct nlpcb *nlp, struct nl_pstate *npt)
{
- struct sockaddr_in *addr = (struct sockaddr_in *)attrs->ifa_local;
+ struct sockaddr *addr = attrs->ifa_local;
if (addr == NULL)
- addr = (struct sockaddr_in *)attrs->ifa_address;
+ addr = attrs->ifa_address;
if (addr == NULL) {
nlmsg_report_err_msg(npt, "empty IFA_ADDRESS/IFA_LOCAL");
return (EINVAL);
}
- struct ifreq req = { .ifr_addr = *(struct sockaddr *)addr };
+ struct ifreq req = { .ifr_addr = *addr };
return (in_control_ioctl(SIOCDIFADDR, &req, ifp, nlp_get_cred(nlp)));
}