From peterjeremy@optushome.com.au  Sun Mar  9 01:27:51 2003
Return-Path: <peterjeremy@optushome.com.au>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id 54EDB37B404
	for <FreeBSD-gnats-submit@freebsd.org>; Sun,  9 Mar 2003 01:27:51 -0800 (PST)
Received: from cirb503493.alcatel.com.au (c18609.belrs1.nsw.optusnet.com.au [210.49.80.204])
	by mx1.FreeBSD.org (Postfix) with ESMTP id 44D5343FAF
	for <FreeBSD-gnats-submit@freebsd.org>; Sun,  9 Mar 2003 01:27:49 -0800 (PST)
	(envelope-from peterjeremy@optushome.com.au)
Received: from cirb503493.alcatel.com.au (localhost.alcatel.com.au [127.0.0.1])
	by cirb503493.alcatel.com.au (8.12.6/8.12.5) with ESMTP id h299RkiM001975;
	Sun, 9 Mar 2003 20:27:46 +1100 (EST)
	(envelope-from jeremyp@cirb503493.alcatel.com.au)
Received: (from jeremyp@localhost)
	by cirb503493.alcatel.com.au (8.12.6/8.12.5/Submit) id h299RjX0001974;
	Sun, 9 Mar 2003 20:27:45 +1100 (EST)
Message-Id: <200303090927.h299RjX0001974@cirb503493.alcatel.com.au>
Date: Sun, 9 Mar 2003 20:27:45 +1100 (EST)
From: Peter Jeremy <peterjeremy@optushome.com.au>
Reply-To:
To: FreeBSD-gnats-submit@freebsd.org
Cc: Peter Jeremy <jeremyp@cirb503493.alcatel.com.au>
Subject: [patch] ctm(1) does not check parent directory of objects
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         49048
>Category:       bin
>Synopsis:       [patch] ctm(1) does not check parent directory of objects
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sun Mar 09 01:30:10 PST 2003
>Closed-Date:    Tue Aug 30 10:15:00 GMT 2005
>Last-Modified:  Tue Aug 30 10:15:00 GMT 2005
>Originator:     Peter Jeremy
>Release:        FreeBSD 4.6-STABLE i386
>Organization:
n/a
>Environment:
System: FreeBSD cirb503493.alcatel.com.au 4.6-STABLE FreeBSD 4.6-STABLE #0: Mon Jul 22 21:45:58 EST 2002 root@cirb503493.alcatel.com.au:/usr/obj/usr/src/sys/pj1592 i386

>Description:
	When ctm(1) executes FM or DM operations, it verifies that the
	specified object doesn't exist but it fails to verify that the
	parent directory does exist during pass2.  If the parent directory
	doesn't exist then pass2 will succeed and ctm will die during pass3
	leaving the repository in an inconsistent state.

	Likewise ctm does not verify that the parent directory can be
	modified by the user running ctm.
>How-To-Repeat:
	Remove (or rename) the parent directory associated with a CTMFM
	or CTMDM operation in a ctm delta.  Run "ctm -c" on the delta
	and repository.  This will report "All checks out ok."  Actually
	running CTM will report "Fatal error: Assert failed." during
	pass3.  For further details or sample deltas, contact me.

>Fix:
	The following is against -CURRENT but will also apply to -STABLE.
Index: ctm_pass2.c
===================================================================
RCS file: /usr/ncvs/src/usr.sbin/ctm/ctm/ctm_pass2.c,v
retrieving revision 1.20
diff -u -r1.20 ctm_pass2.c
--- ctm_pass2.c	25 Mar 2002 13:53:29 -0000	1.20
+++ ctm_pass2.c	9 Mar 2003 08:57:50 -0000
@@ -21,6 +21,7 @@
 Pass2(FILE *fd)
 {
     u_char *p,*q,*md5=0;
+    const u_char *parent;
     MD5_CTX ctx;
     int i,j,sep,cnt,fdesc;
     u_char *trash=0,*name=0;
@@ -96,7 +97,41 @@
 		    if (CTM_FILTER_DISABLE == match)
 			    break;	/* should ignore this file */
 
-		    /* XXX Check DR DM rec's for parent-dir */
+		    /* Check parent directory exists */
+		    q = strrchr(name,'/');
+		    if(NULL != q) {
+			*q = '\0';
+			parent = name;
+		    } else
+			parent = ".";
+		    if(-1 == stat(parent,&st)) {
+			if (NULL != q)
+			    *q = '/';
+			fprintf(stderr,"  %s: %s parent doesn't exist.\n",
+			    sp->Key,name);
+			ret |= Exit_NotOK;
+			break;
+		    }
+		    /* Check we can write to parent */
+		    if (0 != access(parent, W_OK)) {
+			if (NULL != q)
+			    *q = '/';
+			fprintf(stderr, "  %s: %s can't alter parent.\n",
+			    sp->Key,name);
+			ret |= Exit_NotOK;
+			break;
+		    }
+		    if (NULL != q)
+			*q = '/';
+		    /* Check parent is directory */
+		    if((st.st_mode & S_IFMT) != S_IFDIR) {
+			fprintf(stderr,
+			    "  %s: %s parent exists, but isn't dir.\n",
+			    sp->Key,name);
+			ret |= Exit_NotOK;
+			break;
+		    }
+
 		    if(j & CTM_Q_Name_New) {
 			/* XXX Check DR FR rec's for item */
 			if(-1 != stat(name,&st)) {
>Release-Note:
>Audit-Trail:

From: Peter Jeremy <peterjeremy@optushome.com.au>
To: FreeBSD-gnats-submit@FreeBSD.org, freebsd-bugs@FreeBSD.org
Cc:  
Subject: Re: bin/49048: [patch] ctm(1) does not check parent directory of objects
Date: Mon, 10 Mar 2003 19:17:15 +1100

 Following further testing, I withdraw the patch included in the
 original PR.  It fails to take into account changes in the repository
 as a result of previous directives.  As a simple case (that should
 have been obvious to me before), given:
 	CTMDM foo
 	CTMFM foo/bar
 my original patch will fail because "foo" doesn't exist during pass2
 and therefore the CTMFM will be rejected.
 
 I shall consider the problem further and develop a new fix.
 
 Peter
State-Changed-From-To: open->feedback 
State-Changed-By: dwmalone 
State-Changed-When: Wed Mar 12 05:44:32 PST 2003 
State-Changed-Why:  
Put this PR into the feedback state, while Peter works on a new patch. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=49048 
State-Changed-From-To: feedback->closed 
State-Changed-By: matteo 
State-Changed-When: Tue Aug 30 10:14:41 GMT 2005 
State-Changed-Why:  
feedback timeout 

http://www.freebsd.org/cgi/query-pr.cgi?pr=49048 
>Unformatted:
