From owner-svn-src-head@FreeBSD.ORG Fri Sep 12 08:39:16 2014 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 1601869B; Fri, 12 Sep 2014 08:39:16 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id DC025D8C; Fri, 12 Sep 2014 08:39:15 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id s8C8dFUA082669; Fri, 12 Sep 2014 08:39:15 GMT (envelope-from glebius@FreeBSD.org) Received: (from glebius@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id s8C8dFOZ082668; Fri, 12 Sep 2014 08:39:15 GMT (envelope-from glebius@FreeBSD.org) Message-Id: <201409120839.s8C8dFOZ082668@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: glebius set sender to glebius@FreeBSD.org using -f From: Gleb Smirnoff Date: Fri, 12 Sep 2014 08:39:15 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r271458 - head/sys/netpfil/pf X-SVN-Group: head 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.18-1 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, 12 Sep 2014 08:39:16 -0000 Author: glebius Date: Fri Sep 12 08:39:15 2014 New Revision: 271458 URL: http://svnweb.freebsd.org/changeset/base/271458 Log: - Provide a sleepable lock to protect against ioctl() vs ioctl() races. - Use the new lock to protect against simultaneous DIOCSTART and/or DIOCSTOP ioctls. Reported & tested by: jmallett Sponsored by: Nginx, Inc. Modified: head/sys/netpfil/pf/pf_ioctl.c Modified: head/sys/netpfil/pf/pf_ioctl.c ============================================================================== --- head/sys/netpfil/pf/pf_ioctl.c Fri Sep 12 08:37:21 2014 (r271457) +++ head/sys/netpfil/pf/pf_ioctl.c Fri Sep 12 08:39:15 2014 (r271458) @@ -191,6 +191,7 @@ static volatile VNET_DEFINE(int, pf_pfil VNET_DEFINE(int, pf_end_threads); struct rwlock pf_rules_lock; +struct sx pf_ioctl_lock; /* pfsync */ pfsync_state_import_t *pfsync_state_import_ptr = NULL; @@ -1095,20 +1096,18 @@ pfioctl(struct cdev *dev, u_long cmd, ca switch (cmd) { case DIOCSTART: - PF_RULES_WLOCK(); + sx_xlock(&pf_ioctl_lock); if (V_pf_status.running) error = EEXIST; else { int cpu; - PF_RULES_WUNLOCK(); error = hook_pf(); if (error) { DPFPRINTF(PF_DEBUG_MISC, ("pf: pfil registration failed\n")); break; } - PF_RULES_WLOCK(); V_pf_status.running = 1; V_pf_status.since = time_second; @@ -1117,27 +1116,23 @@ pfioctl(struct cdev *dev, u_long cmd, ca DPFPRINTF(PF_DEBUG_MISC, ("pf: started\n")); } - PF_RULES_WUNLOCK(); break; case DIOCSTOP: - PF_RULES_WLOCK(); + sx_xlock(&pf_ioctl_lock); if (!V_pf_status.running) error = ENOENT; else { V_pf_status.running = 0; - PF_RULES_WUNLOCK(); error = dehook_pf(); if (error) { V_pf_status.running = 1; DPFPRINTF(PF_DEBUG_MISC, ("pf: pfil unregistration failed\n")); } - PF_RULES_WLOCK(); V_pf_status.since = time_second; DPFPRINTF(PF_DEBUG_MISC, ("pf: stopped\n")); } - PF_RULES_WUNLOCK(); break; case DIOCADDRULE: { @@ -3261,6 +3256,8 @@ DIOCCHANGEADDR_error: break; } fail: + if (sx_xlocked(&pf_ioctl_lock)) + sx_xunlock(&pf_ioctl_lock); CURVNET_RESTORE(); return (error); @@ -3734,6 +3731,7 @@ pf_load(void) VNET_LIST_RUNLOCK(); rw_init(&pf_rules_lock, "pf rulesets"); + sx_init(&pf_ioctl_lock, "pf ioctl"); pf_dev = make_dev(&pf_cdevsw, 0, 0, 0, 0600, PF_NAME); if ((error = pfattach()) != 0) @@ -3747,9 +3745,7 @@ pf_unload(void) { int error = 0; - PF_RULES_WLOCK(); V_pf_status.running = 0; - PF_RULES_WUNLOCK(); swi_remove(V_pf_swi_cookie); error = dehook_pf(); if (error) { @@ -3778,6 +3774,7 @@ pf_unload(void) PF_RULES_WUNLOCK(); destroy_dev(pf_dev); rw_destroy(&pf_rules_lock); + sx_destroy(&pf_ioctl_lock); return (error); }