-
Notifications
You must be signed in to change notification settings - Fork 2.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
netinet: prevent NULL pointer dereference in in_aifaddr_ioctl() #530
Conversation
@bsdimp can you take a look at this one, please? 🙂
|
2ef0575
to
6dd5ccc
Compare
share/man/man4/netintro.4
Outdated
@@ -397,6 +397,7 @@ struct ifaliasreq { | |||
struct sockaddr ifra_addr; | |||
struct sockaddr ifra_broadaddr; | |||
struct sockaddr ifra_mask; | |||
int ifra_vhid; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks unrelated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
eg, should be a separate change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it, thanks.
sys/netinet/in.c
Outdated
@@ -452,7 +452,7 @@ in_aifaddr_ioctl(u_long cmd, caddr_t data, struct ifnet *ifp, struct thread *td) | |||
if (ifp->if_flags & IFF_POINTOPOINT) | |||
ia->ia_dstaddr = *dstaddr; | |||
|
|||
if (vhid != 0) { | |||
if (vhid != 0 && carp_attach_p != NULL) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So why isn't the check at line 380 enough to keep this from happening? (silly github doesn't let me toss a comment on that line)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lines 379 to 380 in 80b1995
if (vhid > 0 && carp_attach_p == NULL) | |
return (EPROTONOSUPPORT); |
In our case vhid
is negative
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In other places, we reject as invalide vhids < 0... I think that someone more familiar with carp than I am is going to look at this...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds like a plan, thanks! I hope the repro's going to be of use.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I asked Kristof to take a look. His question was why not change the above to vhid != 0? It's not valid to set vhid to any value when carp isn't loaded.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, great suggestion. Implemented it.
7d64200
to
60b0320
Compare
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. ```c 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); } ``` This change * in addition to positive, discards negative `vhid` values in `in_aifaddr_ioctl`, if `carp(4)` is not loaded. This prevents NULL pointer dereference and kernel panic.
60b0320
to
ca4ab95
Compare
@bsdimp sorry to bug you, but what'd be the next steps? Should we backport the fix to previous releases? They seem to be affected too. |
I'll merge it to -current. If there's issues in the back port, I'll be in touch, but it's simple enough it should just apply to stable/12 and stable/13. |
Committed in 620cf65 |
And the cherry-pick succeeded, so I'll commit those to stable/12 and 13 maybe next week... |
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: #530
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: #530 (cherry picked from commit 620cf65)
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: #530 (cherry picked from commit 620cf65)
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: freebsd/freebsd-src#530
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: freebsd/freebsd-src#530
* Rename to use Config, rather than StateHandle/Globals/Backend * Make Backend a type on Config that contains the address space management implementation * Make Ranges part of the Backend configuration, so we can reuse code for different ways of managing memory * Pull the common chains of range definitions into separate files for reuse. * Move PagemapEntry to CommonConfig * Expose Pagemap through backend, so frontend doesn't see Pagemap directly * Remove global Pal and use DefaultPal, where one is not pass explicitly. Co-authored-by: David Chisnall <davidchisnall@users.noreply.github.com> Co-authored-by: Nathaniel Filardo <105816689+nwf-msr@users.noreply.github.com>
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 replicatethat, one needs to
Ensure that
carp(4)
is not loadedIssue
SIOCAIFADDR
call settingifra_vhid
field of the requestto a negative value.
A repro code would look like this.
This change
vhid
values inin_aifaddr_ioctl
, ifcarp(4)
is not loaded. This prevents NULLpointer dereference and kernel panic.