The branch main has been updated by glebius:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=dae64402b3e8ef7488db0df8003361f242573905

commit dae64402b3e8ef7488db0df8003361f242573905
Author:     Gleb Smirnoff <gleb...@freebsd.org>
AuthorDate: 2024-11-18 22:12:42 +0000
Commit:     Gleb Smirnoff <gleb...@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+d4a2682059e23179e...@syzkaller.appspotmail.com
    Reported-by: syzbot+66d7c9b3062e27a56...@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:

Reply via email to