The branch main has been updated by kp:

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

commit ea36212bf5711206bbaf5362a23ebb52c7f7e2a4
Author:     Kristof Provost <k...@freebsd.org>
AuthorDate: 2021-01-13 18:30:01 +0000
Commit:     Kristof Provost <k...@freebsd.org>
CommitDate: 2021-01-13 18:49:42 +0000

    pf: Don't hold PF_RULES_WLOCK during copyin() on DIOCRCLRTSTATS
    
    We cannot hold a non-sleepable lock during copyin(). This means we can't
    safely count the table, so instead we fall back to the pf_ioctl_maxcount
    used in other ioctls to protect against overly large requests.
    
    Reported by:    syzbot+81e380344d4a6c37d...@syzkaller.appspotmail.com
    MFC after:      1 week
---
 sys/netpfil/pf/pf_ioctl.c | 17 ++++++++---------
 1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c
index b6e2ec98ddce..60c38a980d1e 100644
--- a/sys/netpfil/pf/pf_ioctl.c
+++ b/sys/netpfil/pf/pf_ioctl.c
@@ -3363,36 +3363,35 @@ DIOCCHANGEADDR_error:
                struct pfioc_table *io = (struct pfioc_table *)addr;
                struct pfr_table *pfrts;
                size_t totlen;
-               int n;
 
                if (io->pfrio_esize != sizeof(struct pfr_table)) {
                        error = ENODEV;
                        break;
                }
 
-               PF_RULES_WLOCK();
-               n = pfr_table_count(&io->pfrio_table, io->pfrio_flags);
-               if (n < 0) {
-                       PF_RULES_WUNLOCK();
-                       error = EINVAL;
+               if (io->pfrio_size < 0 || io->pfrio_size > pf_ioctl_maxcount ||
+                   WOULD_OVERFLOW(io->pfrio_size, sizeof(struct pfr_table))) {
+                       /* We used to count tables and use the minimum required
+                        * size, so we didn't fail on overly large requests.
+                        * Keep doing so. */
+                       io->pfrio_size = pf_ioctl_maxcount;
                        break;
                }
-               io->pfrio_size = min(io->pfrio_size, n);
 
                totlen = io->pfrio_size * sizeof(struct pfr_table);
                pfrts = mallocarray(io->pfrio_size, sizeof(struct pfr_table),
                    M_TEMP, M_NOWAIT);
                if (pfrts == NULL) {
                        error = ENOMEM;
-                       PF_RULES_WUNLOCK();
                        break;
                }
                error = copyin(io->pfrio_buffer, pfrts, totlen);
                if (error) {
                        free(pfrts, M_TEMP);
-                       PF_RULES_WUNLOCK();
                        break;
                }
+
+               PF_RULES_WLOCK();
                error = pfr_clr_tstats(pfrts, io->pfrio_size,
                    &io->pfrio_nzero, io->pfrio_flags | PFR_FLAG_USERIOCTL);
                PF_RULES_WUNLOCK();
_______________________________________________
dev-commits-src-main@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/dev-commits-src-main
To unsubscribe, send any mail to "dev-commits-src-main-unsubscr...@freebsd.org"

Reply via email to