close
Skip to content

Truncate can lead to data loss #382

@benrubson

Description

@benrubson

Hi,

I found a bug in truncate function, which leads to data loss.

You can easily reproduce it using the following tiny C++ example :

#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <cerrno>

int main() {

int error=0;

int fd = open("trunc.tmp", O_CREAT|O_TRUNC|O_WRONLY);
if(fd<0) {
	printf("open WR failed: %s\n",strerror(errno));
	error++;
}
if(pwrite(fd, "1\n2\n3\n4\n5\n", 10, 0)<=0) {
	printf("write failed: %s\n",strerror(errno));
	error++;
}
close(fd);

fd = open("trunc.tmp", O_RDONLY);
if(fd<0) {
	printf("open RD failed: %s\n",strerror(errno));
	error++;
}
if(ftruncate(fd, 6)>=0) {
	printf("ftruncate on the read-only fd succeeded, but should have failed !\n");
	error++;
}
if(truncate("trunc.tmp", 8)<0) {
	printf("truncate on the read-only opened path failed: %s\n",strerror(errno));
	error++;
}
close(fd);
if(truncate("trunc.tmp", 6)<0) {
	printf("truncate on the closed path failed: %s\n",strerror(errno));
	error++;
}

printf("Errors : %d\n",error);
return 0;
}

This will produce the following and corrupt trunc.tmp :

truncate on the read-only opened path failed: Input/output error
truncate on the closed path failed: Input/output error
Errors : 2

Encfs will log the following :

VERBOSE op: truncate : /tmp/encfs_test/ciphertext/qQD8mBQ1SItyykZ7MCh8xLle [encfs.cpp:150]
VERBOSE streamRead(data, 10, IV) [CipherFileIO.cpp:340]
VERBOSE Called streamWrite [CipherFileIO.cpp:407]
ERROR Assert failed: canWrite [RawFileIO.cpp:216]
ERROR withFileNode: error caught in truncate: canWrite [encfs.cpp:176]
VERBOSE created FileNode for /tmp/encfs_test/ciphertext/qQD8mBQ1SItyykZ7MCh8xLle [DirNode.cpp:675]
VERBOSE op: truncate : /tmp/encfs_test/ciphertext/qQD8mBQ1SItyykZ7MCh8xLle [encfs.cpp:150]
ERROR Assert failed: fd >= 0 [RawFileIO.cpp:202]
ERROR withFileNode: error caught in truncate: fd >= 0 [encfs.cpp:176]

In other words :

  • ftruncate should only truncate write-opened fds.
  • truncate should always truncate.

Ben

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions