mirror of
https://github.com/freebsd/freebsd-src.git
synced 2024-11-30 04:22:44 +00: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:
parent
2ab5515001
commit
bc06c51419
@ -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;
|
||||
|
@ -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)));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user