encfs with 10.0's FUSE doesn't work

Kevin Day toasty at dragondata.com
Mon Apr 21 15:07:22 UTC 2014

fusefs-encfs is in ports, and worked for me in older releases of FreeBSD with the “built from ports” version of fusefs-kmod. It builds okay in 10.0-RELEASE, lets you mount an encrypted filesystem, lets you create directories in it, but fails at actually creating any files. I traced the problem down to the fact that encfs doesn’t implement FUSE_CREATE, it relies on the older fuse behavior of creating a file being accomplished by FUSE_MKNOD + FUSE_OPEN.

To reproduce, install fusefs-encfs then create an encrypted filesystem:

root at media:~ # mkdir /mnt/encfs
root at media:~ # mkdir /tmp/encsource
root at media:~ # encfs /tmp/encsource /mnt/encfs
Creating new encrypted volume.
Please choose from one of the following options:
 enter "x" for expert configuration mode,
 enter "p" for pre-configured paranoia mode,
 anything else, or an empty line will select standard mode.

Standard configuration selected.

Configuration finished.  The filesystem to be created has
the following properties:
Filesystem cipher: "ssl/aes", version 3:0:2
Filename encoding: "nameio/block", version 3:0:1
Key Size: 192 bits
Block Size: 1024 bytes
Each file contains 8 byte header with unique IV data.
Filenames encoded using IV chaining mode.
File holes passed through to ciphertext.

Now you will need to enter a password for your filesystem.
You will need to remember this password, as there is absolutely
no recovery mechanism.  However, the password can be changed
later using encfsctl.

New Encfs Password:
Verify Encfs Password:

It’s mounted and seems to work:

root at media:~ # mount |grep encfs
/dev/fuse on /mnt/encfs (fusefs, local, synchronous)
root at media:~ # mkdir /mnt/encfs/test
root at media:~ # ls -l /mnt/encfs
total 9
drwxr-xr-x  2 root  wheel  2 Apr 21 07:13 test

But trying to create a file fails, and fails differently the first time compared to the second time:

root at media:~ # touch /mnt/encfs/xx
touch: /mnt/encfs/xx: Function not implemented
root at media:~ # touch /mnt/encfs/xx
touch: /mnt/encfs/xxx: Invalid argument

This matches the behavior of fuse_vnops.c if FUSE_CREATE isn’t recognized by the fuse program. The first time through if it sees ENOSYS back from the daemon it does this:

361	        if (err) {
362	                if (err == ENOSYS)
363	                        fsess_set_notimpl(mp, FUSE_CREATE);
364	                debug_printf("create: got err=%d from daemon\n", err);
365	                goto out;
366	        }

which is recognized the second time around:

345	        if (!fsess_isimpl(mp, FUSE_CREATE)) {
346	                debug_printf("eh, daemon doesn't implement create?\n");
347	                return (EINVAL);
348	        }

This is happening because encfs doesn’t define a create function. From encfs’s main.cpp:

    //encfs_oper.create = encfs_create;

It looks like this is supposed to be allowable, because the fuse documentation at http://fuse.sourceforge.net/doxygen/structfuse__operations.html says:

int(* fuse_operations::create)(const char *, mode_t, struct fuse_file_info *)
Create and open a file

If the file does not exist, first create it with the specified mode, and then open it.
If this method is not implemented or under Linux kernel versions earlier than 2.6.15, the mknod() and open() methods will be called instead.
Introduced in version 2.5

It looks like the linux kernel does this: https://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git/tree/fs/fuse/dir.c#n535  OpenBSD has a rather large patch to encfs that gives it an encfs_create() function, but it seems to be relying on behavior specific to OpenBSD’s implementation of fuse.

Is there a reason that the included fuse support is no longer allowing for this?

More information about the freebsd-fs mailing list