summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormbuhl <mbuhl@cvs.openbsd.org>2022-04-29 09:55:44 +0000
committermbuhl <mbuhl@cvs.openbsd.org>2022-04-29 09:55:44 +0000
commit54e18a1ff2c235a987e5cd3b602f8509683291a6 (patch)
tree2dec6cdbb8c7e4eeaa3366f5f21658c9533ecff5
parent528be97265d7bd9240a452cc8332a0e996598226 (diff)
Release PF und NET lock before calling copyout for DIOCIGETIFACES.
OK sashan@ Reported-by: syzbot+b6afd166e314799e3809@syzkaller.appspotmail.com
-rw-r--r--sys/net/pf_if.c12
-rw-r--r--sys/net/pf_ioctl.c20
-rw-r--r--sys/net/pfvar.h4
3 files changed, 21 insertions, 15 deletions
diff --git a/sys/net/pf_if.c b/sys/net/pf_if.c
index 7d12cfe934d..e5dd4ad963b 100644
--- a/sys/net/pf_if.c
+++ b/sys/net/pf_if.c
@@ -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
diff --git a/sys/net/pf_ioctl.c b/sys/net/pf_ioctl.c
index b6d9a26545e..8315b115474 100644
--- a/sys/net/pf_ioctl.c
+++ b/sys/net/pf_ioctl.c
@@ -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;
}
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index 4abcbaf0b90..93394e6da5c 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -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);