Subject: pkg/28479: pkgsrc/security/cfs opens ciphertext for write on read of plaintext
To: None <pkg-manager@netbsd.org, gnats-admin@netbsd.org,>
From: None <gdt@ir.bbn.com>
List: pkgsrc-bugs
Date: 11/30/2004 17:21:01
>Number:         28479
>Category:       pkg
>Synopsis:       pkgsrc/security/cfs opens ciphertext for write on read of plaintext
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    pkg-manager
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Tue Nov 30 17:21:00 +0000 2004
>Originator:     Greg Troxel
>Release:        NetBSD 2.0_RC4
>Organization:
        Greg Troxel <gdt@ir.bbn.com>
>Environment:
	
	
System: NetBSD fnord.ir.bbn.com 2.0_RC4 NetBSD 2.0_RC4 (SINEW) #33: Wed Oct 20 08:09:03 EDT 2004 root@poblano.ir.bbn.com:/n0/obj/sinew/gdt/i386/sys/arch/i386/compile/SINEW i386
Architecture: i386
Machine: i386
>Description:

[CFS (pkgsrc/security/cfs) keeps ciphertext in the filesystem and
provides a plaintext interface via NFS.  Each file operation is
translated to the underlying ciphertext filesystem.]

When reading the plaintext file, CFS opens the ciphertext read-write.
This is probably a workaround for some ancient system.  With ffs, the
sequence [open-for-write, read*, close] does not result in the file
being modified.

When using Coda to store ciphertext, this sequence results in a
"Store" operation when the file is closed.  This combination of
behaviors is dysfunctional, since reading files while disconnected is
normal with Coda.  Writing files is also normal, but the read->write
conversion means that reading the same file on multiple disconnected
systems will result in an eventual write-write conflict when the
disconnected sessions are reintegrated, rather than read-read, which
isn't a conflict at all.

Even when connected, this results in extra store traffic, and the
open-for-write gets an exclusive lock, requiring calling in all the
read (shared) locks on the file.

I reported this to the Coda folks, but it isn't likely to be fixed
soon, since "well, the file was opened for write", and fixing this
would be hard - the lock would have to be upgraded on the first actual
write, and there would perhaps have to be a new "abandon write of file
w/o writing" operation.

CFS is highly useful for privacy on coda, and coda is useful for
disconnected/thin pipe operation.  Without the change below, cfs on
coda is almost unusable unless one is never disconncted and always has
~1 Mb/s or more to the server.

>How-To-Repeat:

Create a cfs ciphertext directory in Coda.
Create a few files in cfs.
(or
  (begin
     Go disconnected.
     Read a file in coda (or two - cfs also has a cache).
     Checkpoint coda's modification log, and examine it.)
  (begin
     Ensure coda is connected.
     Run 'codacon'.
     Read a file or two.
     Observe the Store operations.))

>Fix:

Apply attached patch to pkgsrc.  This removes the logic that says
"even if opening plaintext for read, open ciphertext for write
anyway".

I have been using this patch for several years, with cfs ciphertext
both in ffs and in Coda.  There are some residual issues (the caches
in cfs are not invalidated properly; this hurts more on coda, and with
emacs' clash-detection symlinks), but this patch has not caused me any
problems.

Index: Makefile
===================================================================
RCS file: /NETBSD-CVS/pkgsrc/security/cfs/Makefile,v
retrieving revision 1.19
diff -u -r1.19 Makefile
--- Makefile	3 Aug 2004 04:35:42 -0000	1.19
+++ Makefile	30 Nov 2004 16:22:26 -0000
@@ -1,7 +1,7 @@
 # $NetBSD: Makefile,v 1.19 2004/08/03 04:35:42 tv Exp $
 
 DISTNAME=		cfs-1.4.1
-PKGREVISION=		3
+PKGREVISION=		4
 CATEGORIES=		security
 MASTER_SITES=		http://www.crypto.com/software/
 
Index: distinfo
===================================================================
RCS file: /NETBSD-CVS/pkgsrc/security/cfs/distinfo,v
retrieving revision 1.7
diff -u -r1.7 distinfo
--- distinfo	2 Aug 2004 17:09:06 -0000	1.7
+++ distinfo	30 Nov 2004 16:22:26 -0000
@@ -9,3 +9,4 @@
 SHA1 (patch-ae) = 68b440cda27353d1035bae3002a83d8131087a24
 SHA1 (patch-af) = 19bbedcf0c37356dab747087c64617608ff91838
 SHA1 (patch-ag) = b9563e2bbade9008d044b9b869822013317f118d
+SHA1 (patch-ah) = 6426888cf462fcd4c0245cb32ae78b7520aaf2d5
Index: patches/patch-ah
===================================================================
RCS file: patches/patch-ah
diff -N patches/patch-ah
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ patches/patch-ah	30 Nov 2004 16:22:26 -0000
@@ -0,0 +1,14 @@
+$NetBSD$
+
+--- cfs_fh.c.orig	2004-11-30 11:19:25.000000000 -0500
++++ cfs_fh.c
+@@ -547,7 +547,9 @@ fhtofd(f,mode)
+ 		openfd=NULL;
+ 	}
+ 
++#if 0
+ 	if (mode==0) { mode=CFS_WRITE; }
++#endif
+ 	/* Phil Karn's hack for R/O file systems */
+ 	if ((fd=open(f->name,mode,0))<0 && errno == EROFS) {
+ 		mode = CFS_READ;        /* Force read and try again */

>Unformatted: