mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-11-07 04:36:52 -10:00
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
This commit is contained in:
1 parent
2ab5515001
commit
bc06c51419
3 files changed
+7
-11
No files matched your search
+2
-4
@@ -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;
|
||||
|
||||
+2
-4
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)));
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user