mirror of
https://github.com/vgough/encfs.git
synced 2025-06-24 05:51:51 +02:00
Implement --nocache
Disable block cache (in EncFS) and stat cache (in kernel). This is needed if the backing files may be modified behind the back of EncFS (for example, when you mount an encrypted filesystem exported by encfs --reverse). The reverse grow tests fail when this option is not passed to the decrypting mount.
This commit is contained in:
parent
9f9e30a73f
commit
dee3f628e3
@ -27,6 +27,8 @@
|
|||||||
|
|
||||||
#include "i18n.h"
|
#include "i18n.h"
|
||||||
|
|
||||||
|
#include "FileUtils.h"
|
||||||
|
|
||||||
template <typename Type>
|
template <typename Type>
|
||||||
inline Type min(Type A, Type B) {
|
inline Type min(Type A, Type B) {
|
||||||
return (B < A) ? B : A;
|
return (B < A) ? B : A;
|
||||||
@ -41,6 +43,7 @@ BlockFileIO::BlockFileIO(int blockSize, const FSConfigPtr &cfg)
|
|||||||
: _blockSize(blockSize), _allowHoles(cfg->config->allowHoles) {
|
: _blockSize(blockSize), _allowHoles(cfg->config->allowHoles) {
|
||||||
rAssert(_blockSize > 1);
|
rAssert(_blockSize > 1);
|
||||||
_cache.data = new unsigned char[_blockSize];
|
_cache.data = new unsigned char[_blockSize];
|
||||||
|
_noCache = cfg->opts->noCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockFileIO::~BlockFileIO() {
|
BlockFileIO::~BlockFileIO() {
|
||||||
@ -61,8 +64,11 @@ ssize_t BlockFileIO::cacheReadOneBlock(const IORequest &req) const {
|
|||||||
|
|
||||||
/* we can satisfy the request even if _cache.dataLen is too short, because
|
/* we can satisfy the request even if _cache.dataLen is too short, because
|
||||||
* we always request a full block during reads. This just means we are
|
* we always request a full block during reads. This just means we are
|
||||||
* in the last block of a file, which may be smaller than the blocksize. */
|
* in the last block of a file, which may be smaller than the blocksize.
|
||||||
if ((req.offset == _cache.offset) && (_cache.dataLen != 0)) {
|
* For reverse encryption, the cache must not be used at all, because
|
||||||
|
* the lower file may have changed behind our back. */
|
||||||
|
if ( (_noCache == false) && (req.offset == _cache.offset) &&
|
||||||
|
(_cache.dataLen != 0)) {
|
||||||
// satisfy request from cache
|
// satisfy request from cache
|
||||||
int len = req.dataLen;
|
int len = req.dataLen;
|
||||||
if (_cache.dataLen < len) len = _cache.dataLen; // Don't read past EOF
|
if (_cache.dataLen < len) len = _cache.dataLen; // Don't read past EOF
|
||||||
|
@ -57,6 +57,7 @@ class BlockFileIO : public FileIO {
|
|||||||
|
|
||||||
int _blockSize;
|
int _blockSize;
|
||||||
bool _allowHoles;
|
bool _allowHoles;
|
||||||
|
bool _noCache;
|
||||||
|
|
||||||
// cache last block for speed...
|
// cache last block for speed...
|
||||||
mutable IORequest _cache;
|
mutable IORequest _cache;
|
||||||
|
@ -76,6 +76,11 @@ struct EncFS_Opts {
|
|||||||
|
|
||||||
bool reverseEncryption; // Reverse encryption
|
bool reverseEncryption; // Reverse encryption
|
||||||
|
|
||||||
|
bool noCache; /* Disable block cache (in EncFS) and stat cache (in kernel).
|
||||||
|
* This is needed if the backing files may be modified
|
||||||
|
* behind the back of EncFS (for example, in reverse mode).
|
||||||
|
* See main.cpp for a longer explaination. */
|
||||||
|
|
||||||
ConfigMode configMode;
|
ConfigMode configMode;
|
||||||
|
|
||||||
EncFS_Opts() {
|
EncFS_Opts() {
|
||||||
@ -90,6 +95,7 @@ struct EncFS_Opts {
|
|||||||
ownerCreate = false;
|
ownerCreate = false;
|
||||||
reverseEncryption = false;
|
reverseEncryption = false;
|
||||||
configMode = Config_Prompt;
|
configMode = Config_Prompt;
|
||||||
|
noCache = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -212,6 +212,7 @@ static bool processArgs(int argc, char *argv[],
|
|||||||
// {"single-thread", 0, 0, 's'}, // single-threaded mode
|
// {"single-thread", 0, 0, 's'}, // single-threaded mode
|
||||||
{"stdinpass", 0, 0, 'S'}, // read password from stdin
|
{"stdinpass", 0, 0, 'S'}, // read password from stdin
|
||||||
{"annotate", 0, 0, 513}, // Print annotation lines to stderr
|
{"annotate", 0, 0, 513}, // Print annotation lines to stderr
|
||||||
|
{"nocache", 0, 0, 514}, // disable caching
|
||||||
{"verbose", 0, 0, 'v'}, // verbose mode
|
{"verbose", 0, 0, 'v'}, // verbose mode
|
||||||
{"version", 0, 0, 'V'}, // version
|
{"version", 0, 0, 'V'}, // version
|
||||||
{"reverse", 0, 0, 'r'}, // reverse encryption
|
{"reverse", 0, 0, 'r'}, // reverse encryption
|
||||||
@ -272,24 +273,32 @@ static bool processArgs(int argc, char *argv[],
|
|||||||
case 'D':
|
case 'D':
|
||||||
out->opts->forceDecode = true;
|
out->opts->forceDecode = true;
|
||||||
break;
|
break;
|
||||||
|
/* By default, the kernel caches file metadata for one second.
|
||||||
|
* This is fine for EncFS' normal mode, but for --reverse, this
|
||||||
|
* means that the encrypted view will be up to one second out of
|
||||||
|
* date.
|
||||||
|
* Quoting Goswin von Brederlow:
|
||||||
|
* "Caching only works correctly if you implement a disk based
|
||||||
|
* filesystem, one where only the fuse process can alter
|
||||||
|
* metadata and all access goes only through fuse. Any overlay
|
||||||
|
* filesystem where something can change the underlying
|
||||||
|
* filesystem without going through fuse can run into
|
||||||
|
* inconsistencies."
|
||||||
|
* Enabling reverse automatically enables noCache. */
|
||||||
case 'r':
|
case 'r':
|
||||||
out->opts->reverseEncryption = true;
|
out->opts->reverseEncryption = true;
|
||||||
/* By default, the kernel caches file metadata for one second.
|
case 514:
|
||||||
* This is fine for EncFS' normal mode, but for --reverse, this
|
/* Disable EncFS block cache
|
||||||
* means that the encrypted view will be up to one second out of
|
* Causes reverse grow tests to fail because short reads
|
||||||
* date.
|
* are returned */
|
||||||
* Quoting Goswin von Brederlow:
|
out->opts->noCache = true;
|
||||||
* "Caching only works correctly if you implement a disk based
|
/* Disable kernel stat() cache
|
||||||
* filesystem, one where only the fuse process can alter
|
* Causes reverse grow tests to fail because stale stat() data
|
||||||
* metadata and all access goes only through fuse. Any overlay
|
* is returned */
|
||||||
* filesystem where something can change the underlying
|
PUSHARG("-oattr_timeout=0");
|
||||||
* filesystem without going through fuse can run into
|
/* Disable kernel dentry cache
|
||||||
* inconsistencies."
|
* Fallout unknown, disabling for safety */
|
||||||
* Disable caching so the encrypted view stays consistent with
|
PUSHARG("-oentry_timeout=0");
|
||||||
* the backing files. */
|
|
||||||
PUSHARG("-oattr_timeout=0"); // Causes reverse grow tests to fail
|
|
||||||
// because stale stat() data is returned
|
|
||||||
PUSHARG("-oentry_timeout=0"); // Fallout unknown, disabling for safety
|
|
||||||
break;
|
break;
|
||||||
case 'm':
|
case 'm':
|
||||||
out->opts->mountOnDemand = true;
|
out->opts->mountOnDemand = true;
|
||||||
|
@ -48,7 +48,7 @@ sub mount
|
|||||||
ok(waitForFile("$plain/.encfs6.xml"), "plain .encfs6.xml exists") or BAIL_OUT("'$plain/.encfs6.xml'");
|
ok(waitForFile("$plain/.encfs6.xml"), "plain .encfs6.xml exists") or BAIL_OUT("'$plain/.encfs6.xml'");
|
||||||
my $e = encName(".encfs6.xml");
|
my $e = encName(".encfs6.xml");
|
||||||
ok(waitForFile("$ciphertext/$e"), "encrypted .encfs6.xml exists") or BAIL_OUT("'$ciphertext/$e'");
|
ok(waitForFile("$ciphertext/$e"), "encrypted .encfs6.xml exists") or BAIL_OUT("'$ciphertext/$e'");
|
||||||
system("ENCFS6_CONFIG=$plain/.encfs6.xml ./encfs/encfs -o attr_timeout=0 --extpass=\"echo test\" $ciphertext $decrypted");
|
system("ENCFS6_CONFIG=$plain/.encfs6.xml ./encfs/encfs --nocache --extpass=\"echo test\" $ciphertext $decrypted");
|
||||||
ok(waitForFile("$decrypted/.encfs6.xml"), "decrypted .encfs6.xml exists") or BAIL_OUT("'$decrypted/.encfs6.xml'");
|
ok(waitForFile("$decrypted/.encfs6.xml"), "decrypted .encfs6.xml exists") or BAIL_OUT("'$decrypted/.encfs6.xml'");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user