Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Data leak if crash during truncate #152

Open
iaoing opened this issue Jan 6, 2024 · 0 comments
Open

Data leak if crash during truncate #152

iaoing opened this issue Jan 6, 2024 · 0 comments

Comments

@iaoing
Copy link
Contributor

iaoing commented Jan 6, 2024

Issue

The data could leak if the system crashes during truncate.

Reproduce

The blow code snippet shows the operation to resize data blocks after appending an attribute log.

linux-nova/fs/nova/inode.c

Lines 1335 to 1342 in 976a4d1

/* Only after log entry is committed, we can truncate size */
if ((ia_valid & ATTR_SIZE) && (attr->ia_size != oldsize ||
pi->i_flags & cpu_to_le32(NOVA_EOFBLOCKS_FL))) {
// nova_set_blocksize_hint(sb, inode, pi, attr->ia_size);
/* now we can freely truncate the inode */
nova_setsize(inode, oldsize, attr->ia_size, epoch_id);
}

Modifying the code to simulate a crash before resizing.

	/* Only after log entry is committed, we can truncate size */
	if ((ia_valid & ATTR_SIZE) && (attr->ia_size != oldsize ||
			pi->i_flags & cpu_to_le32(NOVA_EOFBLOCKS_FL))) {
//		nova_set_blocksize_hint(sb, inode, pi, attr->ia_size);

		/* now we can freely truncate the inode */
                if (oldsize >= attr_ia_size)  // simulate a crash if we truncate the file to a smaller size
    		    nova_setsize(inode, oldsize, attr->ia_size, epoch_id);
	}
insmod nova.ko metadata_csum=1 data_csum=1 data_parity=1 dram_struct_csum=1
mount -t NOVA -o init,dbgmask=255 /dev/pmem0 /mnt/pmem0
touch /mnt/pmem0/foo
echo 123456789 > /mnt/pmem0/foo
# truncate the file to a smaller size
# since we modified the code, the `nova_setsize` function will not be invoked.
truncate -s 4 /mnt/pmem0/foo
# cat the image to represent the image in case of a crash
cat /dev/pmem0 > img
# remount the crash image
umount /mnt/pmem0
cat img > /dev/pmem0
mount -t NOVA -o dbgmask=255 /dev/pmem0 /mnt/pmem0
# the stat shows the size is 4 bytes and the cat shows '1234'
stat /mnt/pmem0/foo
cat /mnt/pmem0/foo
# truncate the file to a larger size
truncate -s 20 /mnt/pmem0/foo
# the cat shows '123456789', data leak.
cat /mnt/pmem0/foo

Reason

The truncate function (nova_notify_change) is not atomic.

Fix

Journaling the attribute change log and the zeroout of the last page tail, then committing them together. This fix might introduce a performance issue due to the logging of the data block in the undo-journal. We cannot solo log the attribute change log, since the resize (zeroout) could occur before the journal is committed, leading to data lost while the file is the old size.
Alternatively, declare a special log entry to indicate the completion of the resize. In recovery, if seeing the truncate log, redo the resize. It sounds like a redo log in an undo journal.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant