From owner-svn-src-head@freebsd.org Fri Apr 6 15:01:46 2018 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 836D9F8C29B; Fri, 6 Apr 2018 15:01:46 +0000 (UTC) (envelope-from kp@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 320217F97A; Fri, 6 Apr 2018 15:01:46 +0000 (UTC) (envelope-from kp@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 2CE4D1357A; Fri, 6 Apr 2018 15:01:46 +0000 (UTC) (envelope-from kp@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w36F1kjs086081; Fri, 6 Apr 2018 15:01:46 GMT (envelope-from kp@FreeBSD.org) Received: (from kp@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w36F1kaq086080; Fri, 6 Apr 2018 15:01:46 GMT (envelope-from kp@FreeBSD.org) Message-Id: <201804061501.w36F1kaq086080@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: kp set sender to kp@FreeBSD.org using -f From: Kristof Provost Date: Fri, 6 Apr 2018 15:01:46 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r332101 - head/sys/netpfil/pf X-SVN-Group: head X-SVN-Commit-Author: kp X-SVN-Commit-Paths: head/sys/netpfil/pf X-SVN-Commit-Revision: 332101 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.25 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 06 Apr 2018 15:01:46 -0000 Author: kp Date: Fri Apr 6 15:01:45 2018 New Revision: 332101 URL: https://svnweb.freebsd.org/changeset/base/332101 Log: pf: Improve ioctl validation for DIOCRADDTABLES and DIOCRDELTABLES The DIOCRADDTABLES and DIOCRDELTABLES ioctls can process a number of tables at a time, and as such try to allocate * sizeof(struct pfr_table). This multiplication can overflow. Thanks to mallocarray() this is not exploitable, but an overflow does panic the system. Arbitrarily limit this to 65535 tables. pfctl only ever processes one table at a time, so it presents no issues there. MFC after: 1 week Modified: head/sys/netpfil/pf/pf_ioctl.c Modified: head/sys/netpfil/pf/pf_ioctl.c ============================================================================== --- head/sys/netpfil/pf/pf_ioctl.c Fri Apr 6 13:00:45 2018 (r332100) +++ head/sys/netpfil/pf/pf_ioctl.c Fri Apr 6 15:01:45 2018 (r332101) @@ -89,6 +89,8 @@ __FBSDID("$FreeBSD$"); #include #endif +#define PF_TABLES_MAX_REQUEST 65535 /* Maximum tables per request. */ + static struct pf_pool *pf_get_pool(char *, u_int32_t, u_int8_t, u_int32_t, u_int8_t, u_int8_t, u_int8_t); @@ -2530,13 +2532,15 @@ DIOCCHANGEADDR_error: error = ENODEV; break; } - totlen = io->pfrio_size * sizeof(struct pfr_table); - pfrts = mallocarray(io->pfrio_size, sizeof(struct pfr_table), - M_TEMP, M_WAITOK); - if (! pfrts) { + + if (io->pfrio_size < 0 || io->pfrio_size > PF_TABLES_MAX_REQUEST) { error = ENOMEM; break; } + + totlen = io->pfrio_size * sizeof(struct pfr_table); + pfrts = mallocarray(io->pfrio_size, sizeof(struct pfr_table), + M_TEMP, M_WAITOK); error = copyin(io->pfrio_buffer, pfrts, totlen); if (error) { free(pfrts, M_TEMP); @@ -2559,13 +2563,15 @@ DIOCCHANGEADDR_error: error = ENODEV; break; } - totlen = io->pfrio_size * sizeof(struct pfr_table); - pfrts = mallocarray(io->pfrio_size, sizeof(struct pfr_table), - M_TEMP, M_WAITOK); - if (! pfrts) { + + if (io->pfrio_size < 0 || io->pfrio_size > PF_TABLES_MAX_REQUEST) { error = ENOMEM; break; } + + totlen = io->pfrio_size * sizeof(struct pfr_table); + pfrts = mallocarray(io->pfrio_size, sizeof(struct pfr_table), + M_TEMP, M_WAITOK); error = copyin(io->pfrio_buffer, pfrts, totlen); if (error) { free(pfrts, M_TEMP);