From owner-svn-src-stable@FreeBSD.ORG  Fri Aug 23 14:25:04 2013
Return-Path: <owner-svn-src-stable@FreeBSD.ORG>
Delivered-To: svn-src-stable@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 ESMTP id DF6F7C67;
 Fri, 23 Aug 2013 14:25:04 +0000 (UTC) (envelope-from avg@FreeBSD.org)
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))
 (No client certificate requested)
 by mx1.freebsd.org (Postfix) with ESMTPS id CC61E2B14;
 Fri, 23 Aug 2013 14:25:04 +0000 (UTC)
Received: from svn.freebsd.org ([127.0.1.70])
 by svn.freebsd.org (8.14.7/8.14.7) with ESMTP id r7NEP4h8087379;
 Fri, 23 Aug 2013 14:25:04 GMT (envelope-from avg@svn.freebsd.org)
Received: (from avg@localhost)
 by svn.freebsd.org (8.14.7/8.14.5/Submit) id r7NEP43F087377;
 Fri, 23 Aug 2013 14:25:04 GMT (envelope-from avg@svn.freebsd.org)
Message-Id: <201308231425.r7NEP43F087377@svn.freebsd.org>
From: Andriy Gapon <avg@FreeBSD.org>
Date: Fri, 23 Aug 2013 14:25:04 +0000 (UTC)
To: src-committers@freebsd.org, svn-src-all@freebsd.org,
 svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org
Subject: svn commit: r254708 - in stable/8: . sys/fs/devfs
X-SVN-Group: stable-8
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
X-BeenThere: svn-src-stable@freebsd.org
X-Mailman-Version: 2.1.14
Precedence: list
List-Id: SVN commit messages for all the -stable branches of the src tree
 <svn-src-stable.freebsd.org>
List-Unsubscribe: <http://lists.freebsd.org/mailman/options/svn-src-stable>,
 <mailto:svn-src-stable-request@freebsd.org?subject=unsubscribe>
List-Archive: <http://lists.freebsd.org/pipermail/svn-src-stable>
List-Post: <mailto:svn-src-stable@freebsd.org>
List-Help: <mailto:svn-src-stable-request@freebsd.org?subject=help>
List-Subscribe: <http://lists.freebsd.org/mailman/listinfo/svn-src-stable>,
 <mailto:svn-src-stable-request@freebsd.org?subject=subscribe>
X-List-Received-Date: Fri, 23 Aug 2013 14:25:05 -0000

Author: avg
Date: Fri Aug 23 14:25:04 2013
New Revision: 254708
URL: http://svnweb.freebsd.org/changeset/base/254708

Log:
  MFC r253677,253679: make path matching in devfs rules consistent and
  sane (and safer)

Modified:
  stable/8/UPDATING
  stable/8/sys/fs/devfs/devfs_rule.c
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/fs/   (props changed)

Modified: stable/8/UPDATING
==============================================================================
--- stable/8/UPDATING	Fri Aug 23 14:24:46 2013	(r254707)
+++ stable/8/UPDATING	Fri Aug 23 14:25:04 2013	(r254708)
@@ -15,6 +15,13 @@ NOTE TO PEOPLE WHO THINK THAT FreeBSD 8.
 	debugging tools present in HEAD were left in place because
 	sun4v support still needs work to become production ready.
 
+20130823:
+	Behavior of devfs rules path matching has been changed.
+	Pattern is now always matched against fully qualified devfs
+	path and slash characters must be explicitly matched by
+	slashes in pattern (FNM_PATHNAME). Rulesets involving devfs
+	subdirectories must be reviewed.
+
 20130705:
 	hastctl(8)'s `status' command output changed to terse one-liner format.
 	Scripts using this should switch to `list' command or be rewritten.

Modified: stable/8/sys/fs/devfs/devfs_rule.c
==============================================================================
--- stable/8/sys/fs/devfs/devfs_rule.c	Fri Aug 23 14:24:46 2013	(r254707)
+++ stable/8/sys/fs/devfs/devfs_rule.c	Fri Aug 23 14:25:04 2013	(r254708)
@@ -101,7 +101,7 @@ struct devfs_ruleset {
 static devfs_rid devfs_rid_input(devfs_rid rid, struct devfs_mount *dm);
 
 static void devfs_rule_applyde_recursive(struct devfs_krule *dk,
-		struct devfs_dirent *de);
+		struct devfs_mount *dm, struct devfs_dirent *de);
 static void devfs_rule_applydm(struct devfs_krule *dk, struct devfs_mount *dm);
 static int  devfs_rule_autonumber(struct devfs_ruleset *ds, devfs_rnum *rnp);
 static struct devfs_krule *devfs_rule_byid(devfs_rid rid);
@@ -109,13 +109,16 @@ static int  devfs_rule_delete(struct dev
 static struct cdev *devfs_rule_getdev(struct devfs_dirent *de);
 static int  devfs_rule_input(struct devfs_rule *dr, struct devfs_mount *dm);
 static int  devfs_rule_insert(struct devfs_rule *dr);
-static int  devfs_rule_match(struct devfs_krule *dk, struct devfs_dirent *de);
-static int  devfs_rule_matchpath(struct devfs_krule *dk,
+static int  devfs_rule_match(struct devfs_krule *dk, struct devfs_mount *dm,
+		struct devfs_dirent *de);
+static int  devfs_rule_matchpath(struct devfs_krule *dk, struct devfs_mount *dm,
 		struct devfs_dirent *de);
-static void devfs_rule_run(struct devfs_krule *dk, struct devfs_dirent *de, unsigned depth);
+static void devfs_rule_run(struct devfs_krule *dk, struct devfs_mount *dm,
+		struct devfs_dirent *de, unsigned depth);
 
 static void devfs_ruleset_applyde(struct devfs_ruleset *ds,
-		struct devfs_dirent *de, unsigned depth);
+		struct devfs_mount *dm, struct devfs_dirent *de,
+		unsigned depth);
 static void devfs_ruleset_applydm(struct devfs_ruleset *ds,
 		struct devfs_mount *dm);
 static struct devfs_ruleset *devfs_ruleset_bynum(devfs_rsnum rsnum);
@@ -146,7 +149,7 @@ devfs_rules_apply(struct devfs_mount *dm
 	sx_slock(&sx_rules);
 	ds = devfs_ruleset_bynum(dm->dm_ruleset);
 	KASSERT(ds != NULL, ("mount-point has NULL ruleset"));
-	devfs_ruleset_applyde(ds, de, devfs_rule_depth);
+	devfs_ruleset_applyde(ds, dm, de, devfs_rule_depth);
 	sx_sunlock(&sx_rules);
 }
 
@@ -337,13 +340,14 @@ devfs_rid_input(devfs_rid rid, struct de
  * XXX: a linear search could be done through the cdev list instead.
  */
 static void
-devfs_rule_applyde_recursive(struct devfs_krule *dk, struct devfs_dirent *de)
+devfs_rule_applyde_recursive(struct devfs_krule *dk, struct devfs_mount *dm,
+    struct devfs_dirent *de)
 {
 	struct devfs_dirent *de2;
 
 	TAILQ_FOREACH(de2, &de->de_dlist, de_list)
-		devfs_rule_applyde_recursive(dk, de2);
-	devfs_rule_run(dk, de, devfs_rule_depth);
+		devfs_rule_applyde_recursive(dk, dm, de2);
+	devfs_rule_run(dk, dm, de, devfs_rule_depth);
 }
 
 /*
@@ -353,7 +357,7 @@ static void
 devfs_rule_applydm(struct devfs_krule *dk, struct devfs_mount *dm)
 {
 
-	devfs_rule_applyde_recursive(dk, dm->dm_rootdir);
+	devfs_rule_applyde_recursive(dk, dm, dm->dm_rootdir);
 }
 
 /*
@@ -525,7 +529,8 @@ devfs_rule_insert(struct devfs_rule *dr)
  * de; 0, otherwise.
  */
 static int
-devfs_rule_match(struct devfs_krule *dk, struct devfs_dirent *de)
+devfs_rule_match(struct devfs_krule *dk, struct devfs_mount *dm,
+    struct devfs_dirent *de)
 {
 	struct devfs_rule *dr = &dk->dk_rule;
 	struct cdev *dev;
@@ -558,7 +563,7 @@ devfs_rule_match(struct devfs_krule *dk,
 		dev_relthread(dev, ref);
 	}
 	if (dr->dr_icond & DRC_PATHPTRN)
-		if (!devfs_rule_matchpath(dk, de))
+		if (!devfs_rule_matchpath(dk, dm, de))
 			return (0);
 
 	return (1);
@@ -568,35 +573,43 @@ devfs_rule_match(struct devfs_krule *dk,
  * Determine whether dk matches de on account of dr_pathptrn.
  */
 static int
-devfs_rule_matchpath(struct devfs_krule *dk, struct devfs_dirent *de)
+devfs_rule_matchpath(struct devfs_krule *dk, struct devfs_mount *dm,
+    struct devfs_dirent *de)
 {
 	struct devfs_rule *dr = &dk->dk_rule;
-	char *pname;
 	struct cdev *dev;
+	int match;
+	char *pname, *specname;
 
+	specname = NULL;
 	dev = devfs_rule_getdev(de);
 	if (dev != NULL)
 		pname = dev->si_name;
 	else if (de->de_dirent->d_type == DT_LNK ||
-	    de->de_dirent->d_type == DT_DIR)
-		pname = de->de_dirent->d_name;
-	else
+	    (de->de_dirent->d_type == DT_DIR && de != dm->dm_rootdir &&
+	    (de->de_flags & (DE_DOT | DE_DOTDOT)) == 0)) {
+		specname = malloc(SPECNAMELEN + 1, M_TEMP, M_WAITOK);
+		pname = devfs_fqpn(specname, dm, de, NULL);
+	} else
 		return (0);
-	KASSERT(pname != NULL, ("devfs_rule_matchpath: NULL pname"));
 
-	return (fnmatch(dr->dr_pathptrn, pname, 0) == 0);
+	KASSERT(pname != NULL, ("devfs_rule_matchpath: NULL pname"));
+	match = fnmatch(dr->dr_pathptrn, pname, FNM_PATHNAME) == 0;
+	free(specname, M_TEMP);
+	return (match);
 }
 
 /*
  * Run dk on de.
  */
 static void
-devfs_rule_run(struct devfs_krule *dk, struct devfs_dirent *de, unsigned depth)
+devfs_rule_run(struct devfs_krule *dk,  struct devfs_mount *dm,
+    struct devfs_dirent *de, unsigned depth)
 {
 	struct devfs_rule *dr = &dk->dk_rule;
 	struct devfs_ruleset *ds;
 
-	if (!devfs_rule_match(dk, de))
+	if (!devfs_rule_match(dk, dm, de))
 		return;
 	if (dr->dr_iacts & DRA_BACTS) {
 		if (dr->dr_bacts & DRB_HIDE)
@@ -623,7 +636,7 @@ devfs_rule_run(struct devfs_krule *dk, s
 		if (depth > 0) {
 			ds = devfs_ruleset_bynum(dk->dk_rule.dr_incset);
 			KASSERT(ds != NULL, ("DRA_INCSET but bad dr_incset"));
-			devfs_ruleset_applyde(ds, de, depth - 1);
+			devfs_ruleset_applyde(ds, dm, de, depth - 1);
 		}
 	}
 }
@@ -632,12 +645,13 @@ devfs_rule_run(struct devfs_krule *dk, s
  * Apply all the rules in ds to de.
  */
 static void
-devfs_ruleset_applyde(struct devfs_ruleset *ds, struct devfs_dirent *de, unsigned depth)
+devfs_ruleset_applyde(struct devfs_ruleset *ds, struct devfs_mount *dm,
+    struct devfs_dirent *de, unsigned depth)
 {
 	struct devfs_krule *dk;
 
 	TAILQ_FOREACH(dk, &ds->ds_rules, dk_list)
-		devfs_rule_run(dk, de, depth);
+		devfs_rule_run(dk, dm, de, depth);
 }
 
 /*