NetBSD Problem Report #58886

From www@netbsd.org  Mon Dec  9 18:46:04 2024
Return-Path: <www@netbsd.org>
Received: from mail.netbsd.org (mail.netbsd.org [199.233.217.200])
	(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
	 key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256
	 client-signature RSA-PSS (2048 bits) client-digest SHA256)
	(Client CN "mail.NetBSD.org", Issuer "mail.NetBSD.org CA" (not verified))
	by mollari.NetBSD.org (Postfix) with ESMTPS id 0BABC1A923A
	for <gnats-bugs@gnats.NetBSD.org>; Mon,  9 Dec 2024 18:46:04 +0000 (UTC)
Message-Id: <20241209184602.3E1241A923B@mollari.NetBSD.org>
Date: Mon,  9 Dec 2024 18:46:02 +0000 (UTC)
From: jlduran@gmail.com
Reply-To: jlduran@gmail.com
To: gnats-bugs@NetBSD.org
Subject: mtree: Exit with status 2 on a non-matching spec
X-Send-Pr-Version: www-1.0

>Number:         58886
>Category:       bin
>Synopsis:       mtree: Exit with status 2 on a non-matching spec
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    bin-bug-people
>State:          closed
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Dec 09 18:50:00 +0000 2024
>Closed-Date:    Sat Dec 20 00:01:21 +0000 2025
>Last-Modified:  Sat Dec 20 00:01:21 +0000 2025
>Originator:     Jose Luis Duran
>Release:        trunk
>Organization:
FreeBSD
>Environment:
>Description:
A FreeBSD user reports[^1] that the mtree utility should exit with status 2 if the file hierarchy did
not match the specification.

[^1]: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=28424
>How-To-Repeat:
:It it important to remove the time stamp from the specification, otherwise it will behave correctly, because it will take a different code path:

# mkdir -p testdir/bar
# mtree -cd -R time -p testdir >output
# rm -fr testdir/bar
# mtree -d -f output -p testdir && echo 'hierarchy matches spec'
./bar missing
hierarchy matches spec
>Fix:
A simple (naive) patch is proposed, as usual, feel free to change as you see fit.

The patch:
1. Promotes rval (the return value) to an exten (this step is not mandatory).
2. Sets the rval to 2 (MISMATCHEXIT), after printing the message that something is missing from the specification. (This matches the behavior described in the man page).
3. Add a test. The test is not really relevant, it is added here just for convenience.

Subject: [PATCH 2/2] mtree: Exit with status 2 on a non-matching spec

The mtree utility should exit with status 2 if the file hierarchy did
not match the specification.

FreeBSD PR:	28424
---
 tests/usr.sbin/mtree/t_mtree.sh | 36 +++++++++++++++++++++++++++++++++
 usr.sbin/mtree/extern.h         |  1 +
 usr.sbin/mtree/getid.c          |  8 --------
 usr.sbin/mtree/mtree.c          |  1 +
 usr.sbin/mtree/specspec.c       |  1 -
 usr.sbin/mtree/verify.c         |  8 ++++----
 6 files changed, 42 insertions(+), 13 deletions(-)

diff --git a/tests/usr.sbin/mtree/t_mtree.sh b/tests/usr.sbin/mtree/t_mtree.sh
index 5e4177c792a5..fa1aba7c9d4a 100644
--- a/tests/usr.sbin/mtree/t_mtree.sh
+++ b/tests/usr.sbin/mtree/t_mtree.sh
@@ -482,6 +482,40 @@ netbsd6_onlyfile_body()
 	FLAVOR=netbsd6 onlyfile_body
 }

+atf_test_case mtree_verify
+atf_test_case netbsd6_verify
+verify_head()
+{
+	atf_set "descr" "Verify exit code of mismatched spec"
+}
+
+verify_body()
+{
+	mkdir -p testdir/bar
+	mtree -F ${FLAVOR} -cd -R time -p testdir >output
+	rm -fr testdir/bar
+
+	atf_check -s exit:2 -o ignore -x "mtree -F ${FLAVOR} -d -f output -p testdir"
+}
+
+mtree_verify_head()
+{
+	FLAVOR=mtree verify_head
+}
+netbsd6_verify_head()
+{
+	FLAVOR=netbsd6 verify_head
+}
+
+mtree_verify_body()
+{
+	FLAVOR=mtree verify_body
+}
+netbsd6_verify_body()
+{
+	FLAVOR=netbsd6 verify_body
+}
+

 atf_init_test_cases()
 {
@@ -496,6 +530,7 @@ atf_init_test_cases()
 	atf_add_test_case mtree_nonemptydir
 	atf_add_test_case mtree_specspec_type
 	atf_add_test_case mtree_onlyfile
+	atf_add_test_case mtree_verify

 	atf_add_test_case netbsd6_create
 	atf_add_test_case netbsd6_check
@@ -507,4 +542,5 @@ atf_init_test_cases()
 	atf_add_test_case netbsd6_merge
 	atf_add_test_case netbsd6_nonemptydir
 	atf_add_test_case netbsd6_onlyfile
+	atf_add_test_case netbsd6_verify
 }
diff --git a/usr.sbin/mtree/extern.h b/usr.sbin/mtree/extern.h
index 7b58dd4a4d20..f311d23a77d5 100644
--- a/usr.sbin/mtree/extern.h
+++ b/usr.sbin/mtree/extern.h
@@ -92,6 +92,7 @@ extern size_t	mtree_lineno;
 extern enum flavor	flavor;
 extern uint32_t crc_total;
 extern int	ftsoptions, keys;
+extern int	rval;
 extern char	fullpath[];
 extern slist_t	includetags, excludetags;

diff --git a/usr.sbin/mtree/getid.c b/usr.sbin/mtree/getid.c
index 2c9e641500ec..86d7d21189b5 100644
--- a/usr.sbin/mtree/getid.c
+++ b/usr.sbin/mtree/getid.c
@@ -151,8 +151,6 @@ setup_getid(const char *dir)
 static struct group *
 gi_getgrnam(const char *name)
 {
-	int rval;
-
 	if (!grstart())
 		return NULL;
 	rval = grscan(1, 0, name);
@@ -164,8 +162,6 @@ gi_getgrnam(const char *name)
 static struct group *
 gi_getgrgid(gid_t gid)
 {
-	int rval;
-
 	if (!grstart())
 		return NULL;
 	rval = grscan(1, gid, NULL);
@@ -300,8 +296,6 @@ grmatchline(int search, gid_t gid, const char *name)
 static struct passwd *
 gi_getpwnam(const char *name)
 {
-	int rval;
-
 	if (!pwstart())
 		return NULL;
 	rval = pwscan(1, 0, name);
@@ -313,8 +307,6 @@ gi_getpwnam(const char *name)
 static struct passwd *
 gi_getpwuid(uid_t uid)
 {
-	int rval;
-
 	if (!pwstart())
 		return NULL;
 	rval = pwscan(1, uid, NULL);
diff --git a/usr.sbin/mtree/mtree.c b/usr.sbin/mtree/mtree.c
index 28f09fa32210..9c289a1c0ee0 100644
--- a/usr.sbin/mtree/mtree.c
+++ b/usr.sbin/mtree/mtree.c
@@ -61,6 +61,7 @@ __RCSID("$NetBSD: mtree.c,v 1.51 2024/12/05 17:17:15 christos Exp $");
 int	ftsoptions = FTS_PHYSICAL;
 int	bflag, dflag, eflag, iflag, jflag, lflag, mflag, nflag, qflag, rflag,
 	sflag, tflag, uflag;
+int	rval = 0;
 char	fullpath[MAXPATHLEN];

 static struct {
diff --git a/usr.sbin/mtree/specspec.c b/usr.sbin/mtree/specspec.c
index 8e1187b4c0a8..9906a058878a 100644
--- a/usr.sbin/mtree/specspec.c
+++ b/usr.sbin/mtree/specspec.c
@@ -260,7 +260,6 @@ walk_in_the_forest(NODE *t1, NODE *t2, char const *path)
 int
 mtree_specspec(FILE *fi, FILE *fj)
 {
-	int rval;
 	NODE *root1, *root2;

 	root1 = spec(fi);
diff --git a/usr.sbin/mtree/verify.c b/usr.sbin/mtree/verify.c
index be11002cef85..b58f8ce46604 100644
--- a/usr.sbin/mtree/verify.c
+++ b/usr.sbin/mtree/verify.c
@@ -66,8 +66,6 @@ static int	vwalk(void);
 int
 verify(FILE *fi)
 {
-	int rval;
-
 	root = spec(fi);
 	rval = vwalk();
 	miss(root, path);
@@ -80,7 +78,7 @@ vwalk(void)
 	FTS *t;
 	FTSENT *p;
 	NODE *ep, *level;
-	int specdepth, rval;
+	int specdepth;
 	char *argv[2];
 	char  dot[] = ".";
 	argv[0] = dot;
@@ -199,8 +197,10 @@ miss(NODE *p, char *tail)
 			if (qflag && stat(path, &statbuf) == 0 &&
 			    S_ISDIR(statbuf.st_mode))
 				p->flags |= F_VISIT;
-			else
+			else {
 				(void)printf("%s missing", path);
+				rval = MISMATCHEXIT;
+			}
 		}
 		switch (p->type) {
 		case F_BLOCK:
--
Jose Luis Duran

>Release-Note:

>Audit-Trail:
From: Jose Luis Duran <jlduran@gmail.com>
To: gnats-bugs@netbsd.org
Cc: 
Subject: Re: bin/58886: mtree: Exit with status 2 on a non-matching spec
Date: Wed, 17 Dec 2025 14:39:12 -0300

 Please close this problem report.
 It is not a bug, this is the documented behavior.

From: "Christos Zoulas" <christos@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/58886 CVS commit: src/usr.sbin/mtree
Date: Thu, 18 Dec 2025 09:05:41 -0500

 Module Name:	src
 Committed By:	christos
 Date:		Thu Dec 18 14:05:41 UTC 2025

 Modified Files:
 	src/usr.sbin/mtree: spec.c

 Log Message:
 PR/58886: Jose Louis Duran: Fix freed memory access leading to SEGV,
 given the following spec file (mt -f <specfile>):
 ------
 /set type=dir
   .
     dup
     ..
     dup
       child_entry type=file
 ------
 This happens because when calling:
 	  addchild(last, centry);
 if it is the same entry, centry will be freed and then
 	  last = centry;
 will point to freed memory. Make addchild return the entry that is supposed
 to be used instead.


 To generate a diff of this commit:
 cvs rdiff -u -r1.93 -r1.94 src/usr.sbin/mtree/spec.c

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

State-Changed-From-To: open->closed
State-Changed-By: kre@NetBSD.org
State-Changed-When: Sat, 20 Dec 2025 00:01:21 +0000
State-Changed-Why:
Withdrawn by submitter


>Unformatted:

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.47 2022/09/11 19:34:41 kim Exp $
$NetBSD: gnats_config.sh,v 1.9 2014/08/02 14:16:04 spz Exp $
Copyright © 1994-2025 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.