Release PF und NET lock before calling copyout for DIOCIGETIFACES.
authormbuhl <mbuhl@openbsd.org>
Fri, 29 Apr 2022 09:55:43 +0000 (09:55 +0000)
committermbuhl <mbuhl@openbsd.org>
Fri, 29 Apr 2022 09:55:43 +0000 (09:55 +0000)
OK sashan@
Reported-by: syzbot+b6afd166e314799e3809@syzkaller.appspotmail.com
sys/net/pf_if.c
sys/net/pf_ioctl.c
sys/net/pfvar.h

index 7d12cfe..e5dd4ad 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pf_if.c,v 1.103 2021/12/26 01:00:32 sashan Exp $ */
+/*     $OpenBSD: pf_if.c,v 1.104 2022/04/29 09:55:43 mbuhl Exp $ */
 
 /*
  * Copyright 2005 Henning Brauer <henning@openbsd.org>
@@ -755,7 +755,7 @@ pfi_update_status(const char *name, struct pf_status *pfs)
        }
 }
 
-int
+void
 pfi_get_ifaces(const char *name, struct pfi_kif *buf, int *size)
 {
        struct pfi_kif  *p, *nextp;
@@ -768,17 +768,11 @@ pfi_get_ifaces(const char *name, struct pfi_kif *buf, int *size)
                if (*size > n++) {
                        if (!p->pfik_tzero)
                                p->pfik_tzero = gettime();
-                       pfi_kif_ref(p, PFI_KIF_REF_RULE);
-                       if (copyout(p, buf++, sizeof(*buf))) {
-                               pfi_kif_unref(p, PFI_KIF_REF_RULE);
-                               return (EFAULT);
-                       }
+                       memcpy(buf++, p, sizeof(*buf));
                        nextp = RB_NEXT(pfi_ifhead, &pfi_ifs, p);
-                       pfi_kif_unref(p, PFI_KIF_REF_RULE);
                }
        }
        *size = n;
-       return (0);
 }
 
 int
index b6d9a26..8315b11 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pf_ioctl.c,v 1.379 2022/04/09 13:15:44 mbuhl Exp $ */
+/*     $OpenBSD: pf_ioctl.c,v 1.380 2022/04/29 09:55:43 mbuhl Exp $ */
 
 /*
  * Copyright (c) 2001 Daniel Hartmeier
@@ -2921,18 +2921,30 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
                break;
 
        case DIOCIGETIFACES: {
-               struct pfioc_iface *io = (struct pfioc_iface *)addr;
+               struct pfioc_iface      *io = (struct pfioc_iface *)addr;
+               struct pfi_kif          *kif_buf;
+               int                      apfiio_size = io->pfiio_size;
 
                if (io->pfiio_esize != sizeof(struct pfi_kif)) {
                        error = ENODEV;
                        goto fail;
                }
+
+               if ((kif_buf = mallocarray(sizeof(*kif_buf), apfiio_size,
+                   M_TEMP, M_WAITOK|M_CANFAIL)) == NULL) {
+                       error = EINVAL;
+                       goto fail;
+               }
+
                NET_LOCK();
                PF_LOCK();
-               error = pfi_get_ifaces(io->pfiio_name, io->pfiio_buffer,
-                   &io->pfiio_size);
+               pfi_get_ifaces(io->pfiio_name, kif_buf, &io->pfiio_size);
                PF_UNLOCK();
                NET_UNLOCK();
+               if (copyout(kif_buf, io->pfiio_buffer, sizeof(*kif_buf) *
+                   io->pfiio_size))
+                       error = EFAULT;
+               free(kif_buf, M_TEMP, sizeof(*kif_buf) * apfiio_size);
                break;
        }
 
index 4abcbaf..93394e6 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pfvar.h,v 1.506 2022/04/21 15:22:49 sashan Exp $ */
+/*     $OpenBSD: pfvar.h,v 1.507 2022/04/29 09:55:43 mbuhl Exp $ */
 
 /*
  * Copyright (c) 2001 Daniel Hartmeier
@@ -1879,7 +1879,7 @@ int                pfi_dynaddr_setup(struct pf_addr_wrap *, sa_family_t);
 void            pfi_dynaddr_remove(struct pf_addr_wrap *);
 void            pfi_dynaddr_copyout(struct pf_addr_wrap *);
 void            pfi_update_status(const char *, struct pf_status *);
-int             pfi_get_ifaces(const char *, struct pfi_kif *, int *);
+void            pfi_get_ifaces(const char *, struct pfi_kif *, int *);
 int             pfi_set_flags(const char *, int);
 int             pfi_clear_flags(const char *, int);
 void            pfi_xcommit(void);