git: dae64402b3e8 - main - rtsock: fix panic in rtsock_msg_buffer()
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 18 Nov 2024 22:13:22 UTC
The branch main has been updated by glebius: URL: https://cgit.FreeBSD.org/src/commit/?id=dae64402b3e8ef7488db0df8003361f242573905 commit dae64402b3e8ef7488db0df8003361f242573905 Author: Gleb Smirnoff <glebius@FreeBSD.org> AuthorDate: 2024-11-18 22:12:42 +0000 Commit: Gleb Smirnoff <glebius@FreeBSD.org> CommitDate: 2024-11-18 22:12:42 +0000 rtsock: fix panic in rtsock_msg_buffer() The rtsock_msg_buffer() can be called without walkarg, just to calculate required length. It can also be called with a degenerate walkarg, that doesn't have a w_req. The latter happens when the function is called from update_rtm_from_info() for the second time. Zero init walkarg in update_rtm_from_info() and don't pass random stack garbage as w_req. In rtsock_msg_buffer() initialize compat32 boolean only once and take of possible empty w_req. Simplify the rest of code once compat32 is already set. Reviewed by: melifaro Differential Revision: https://reviews.freebsd.org/D47662 Reported-by: syzbot+d4a2682059e23179e76e@syzkaller.appspotmail.com Reported-by: syzbot+66d7c9b3062e27a56f3f@syzkaller.appspotmail.com --- sys/net/rtsock.c | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c index 09d463dc17af..a5395dcf1469 100644 --- a/sys/net/rtsock.c +++ b/sys/net/rtsock.c @@ -921,8 +921,10 @@ update_rtm_from_info(struct rt_addrinfo *info, struct rt_msghdr **prtm, */ } - w.w_tmem = (caddr_t)rtm; - w.w_tmemsize = alloc_len; + w = (struct walkarg ){ + .w_tmem = (caddr_t)rtm, + .w_tmemsize = alloc_len, + }; rtsock_msg_buffer(rtm->rtm_type, info, &w, &len); rtm->rtm_addrs = info->rti_addrs; @@ -1774,7 +1776,10 @@ rtsock_msg_buffer(int type, struct rt_addrinfo *rtinfo, struct walkarg *w, int * struct sockaddr_in6 *sin6; #endif #ifdef COMPAT_FREEBSD32 - bool compat32 = false; + bool compat32; + + compat32 = w != NULL && w->w_req != NULL && + (w->w_req->flags & SCTL_MASK32); #endif switch (type) { @@ -1782,10 +1787,9 @@ rtsock_msg_buffer(int type, struct rt_addrinfo *rtinfo, struct walkarg *w, int * case RTM_NEWADDR: if (w != NULL && w->w_op == NET_RT_IFLISTL) { #ifdef COMPAT_FREEBSD32 - if (w->w_req->flags & SCTL_MASK32) { + if (compat32) len = sizeof(struct ifa_msghdrl32); - compat32 = true; - } else + else #endif len = sizeof(struct ifa_msghdrl); } else @@ -1793,20 +1797,21 @@ rtsock_msg_buffer(int type, struct rt_addrinfo *rtinfo, struct walkarg *w, int * break; case RTM_IFINFO: + if (w != NULL && w->w_op == NET_RT_IFLISTL) { #ifdef COMPAT_FREEBSD32 - if (w != NULL && w->w_req->flags & SCTL_MASK32) { - if (w->w_op == NET_RT_IFLISTL) + if (compat32) len = sizeof(struct if_msghdrl32); else +#endif + len = sizeof(struct if_msghdrl); + } else { +#ifdef COMPAT_FREEBSD32 + if (compat32) len = sizeof(struct if_msghdr32); - compat32 = true; - break; - } + else #endif - if (w != NULL && w->w_op == NET_RT_IFLISTL) - len = sizeof(struct if_msghdrl); - else - len = sizeof(struct if_msghdr); + len = sizeof(struct if_msghdr); + } break; case RTM_NEWMADDR: