git: 620cf65c2bc4 - main - netinet: prevent NULL pointer dereference in in_aifaddr_ioctl()
Warner Losh
imp at FreeBSD.org
Thu Aug 26 18:15:12 UTC 2021
The branch main has been updated by imp:
URL: https://cgit.FreeBSD.org/src/commit/?id=620cf65c2bc4035a07e1152da419a4e60d36ff9b
commit 620cf65c2bc4035a07e1152da419a4e60d36ff9b
Author: Artem Khramov <akhramov at pm.me>
AuthorDate: 2021-08-24 14:26:35 +0000
Commit: Warner Losh <imp at FreeBSD.org>
CommitDate: 2021-08-26 18:08:03 +0000
netinet: prevent NULL pointer dereference in in_aifaddr_ioctl()
It appears that maliciously crafted ifaliasreq can lead to NULL
pointer dereference in in_aifaddr_ioctl(). In order to replicate
that, one needs to
1. Ensure that carp(4) is not loaded
2. Issue SIOCAIFADDR call setting ifra_vhid field of the request
to a negative value.
A repro code would look like this.
int main() {
struct ifaliasreq req;
struct sockaddr_in sin, mask;
int fd, error;
bzero(&sin, sizeof(struct sockaddr_in));
bzero(&mask, sizeof(struct sockaddr_in));
sin.sin_len = sizeof(struct sockaddr_in);
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = inet_addr("192.168.88.2");
mask.sin_len = sizeof(struct sockaddr_in);
mask.sin_family = AF_INET;
mask.sin_addr.s_addr = inet_addr("255.255.255.0");
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0)
return (-1);
memset(&req, 0, sizeof(struct ifaliasreq));
strlcpy(req.ifra_name, "lo0", sizeof(req.ifra_name));
memcpy(&req.ifra_addr, &sin, sin.sin_len);
memcpy(&req.ifra_mask, &mask, mask.sin_len);
req.ifra_vhid = -1;
return ioctl(fd, SIOCAIFADDR, (char *)&req);
}
To fix, discard both positive and negative vhid values in
in_aifaddr_ioctl, if carp(4) is not loaded. This prevents NULL pointer
dereference and kernel panic.
Reviewed by: imp@
Pull Request: https://github.com/freebsd/freebsd-src/pull/530
---
sys/netinet/in.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/sys/netinet/in.c b/sys/netinet/in.c
index d1dd2b31b6ef..f9b46b414007 100644
--- a/sys/netinet/in.c
+++ b/sys/netinet/in.c
@@ -376,7 +376,7 @@ in_aifaddr_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp, struct thread *td)
(dstaddr->sin_len != sizeof(struct sockaddr_in) ||
dstaddr->sin_addr.s_addr == INADDR_ANY))
return (EDESTADDRREQ);
- if (vhid > 0 && carp_attach_p == NULL)
+ if (vhid != 0 && carp_attach_p == NULL)
return (EPROTONOSUPPORT);
/*
More information about the dev-commits-src-main
mailing list