aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGleb Smirnoff <glebius@FreeBSD.org>2024-11-18 22:12:42 +0000
committerGleb Smirnoff <glebius@FreeBSD.org>2024-11-18 22:12:42 +0000
commitdae64402b3e8ef7488db0df8003361f242573905 (patch)
treec05b82cfa9ae69ed573f37c7c0362fea97b190dc
parent43e045c1733d50fad79f3a53e05140b8dc0d7fa6 (diff)
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
-rw-r--r--sys/net/rtsock.c35
1 files 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: