This patch modifies both ext4 and jbd2 such that the journal
blocks which may contain file data, are securely deleted
after the files data blocks are deleted.
Because old journal blocks may contain file data, we need
a way to find those blocks again when it comes time to secure
delete the file. This patch adds a new list to the journal
structure to keep track of which vfs blocks the journal blocks
contain.
After a truncate or a punch hole operation has completed, a
new function ext4_secure_delete_jblks is called that flushes
the journal, and then searches the list for any journal blocks
that were used to journal the blocks that were just removed.
The found journal blocks are then secure deleted.
Signed-off-by: Allison Henderson<achender@xxxxxxxxxxxxxxxxxx>
---
:100644 100644 0cba63b... fdf73b5... M fs/ext4/ext4.h
:100644 100644 984fac2... 81df943... M fs/ext4/extents.c
:100644 100644 bd1facd... 083c516... M fs/ext4/inode.c
:100644 100644 eef6979... 2734e7b... M fs/jbd2/commit.c
:100644 100644 f24df13... 6dd8af7... M fs/jbd2/journal.c
:100644 100644 38f307b... 8b84b43... M include/linux/jbd2.h
fs/ext4/ext4.h | 3 +
fs/ext4/extents.c | 12 +++++
fs/ext4/inode.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++++
fs/jbd2/commit.c | 6 +++
fs/jbd2/journal.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++
include/linux/jbd2.h | 21 +++++++++
6 files changed, 264 insertions(+), 0 deletions(-)
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 0cba63b..fdf73b5 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -2230,6 +2230,9 @@ extern int ext4_secure_delete_lblks(struct inode *inode,
ext4_lblk_t first_block, unsigned long count);
extern int ext4_secure_delete_pblks(struct inode *inode,
ext4_fsblk_t block, unsigned long count);
+extern int ext4_secure_delete_jblks(struct inode *inode,
+ ext4_lblk_t first_block, unsigned long count);
+
/* move_extent.c */
extern int ext4_move_extents(struct file *o_filp, struct file *d_filp,
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 984fac2..81df943 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -4159,6 +4159,7 @@ int ext4_ext_punch_hole(struct file *file, loff_t offset, loff_t length)
struct super_block *sb = inode->i_sb;
struct ext4_ext_cache cache_ex;
ext4_lblk_t first_block, last_block, num_blocks, iblock, max_blocks;
+ ext4_lblk_t first_secrm_blk, last_secrm_blk, secrm_blk_count;
struct address_space *mapping = inode->i_mapping;
struct ext4_map_blocks map;
handle_t *handle;
@@ -4317,6 +4318,17 @@ out:
inode->i_mtime = inode->i_ctime = ext4_current_time(inode);
ext4_mark_inode_dirty(handle, inode);
ext4_journal_stop(handle);
+
+ if (!err&& EXT4_I(inode)->i_flags& EXT4_SECRM_FL) {
+ first_secrm_blk = offset>> EXT4_BLOCK_SIZE_BITS(sb);
+ last_secrm_blk = (offset + length + sb->s_blocksize - 1)>>
+ EXT4_BLOCK_SIZE_BITS(sb);
+ secrm_blk_count = last_secrm_blk - first_secrm_blk;
+
+ err = ext4_secure_delete_jblks(inode,
+ first_secrm_blk, secrm_blk_count);
+ }
+
return err;
}
int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index bd1facd..083c516 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -909,6 +909,110 @@ int ext4_secure_delete_lblks(struct inode *inode, ext4_lblk_t first_block,
return err;
}
+/*
+ * ext4_secure_delete_jblks()
+ *
+ * Secure deletes the journal blocks that contain
+ * the specified logical blocks
+ *
+ * @inode: The files inode
+ * @first_block: Starting logical block
+ * @count: The number of blocks to secure delete
+ * from the journal
+ *
+ * Returns 0 on sucess or negative on error
+ */
+int ext4_secure_delete_jblks(struct inode *inode,
+ ext4_lblk_t first_block, unsigned long count){
+
+ unsigned long long jbd2_pblk_start = 0;
+ unsigned long long jbd2_pblk_count = 0;
+ ext4_lblk_t last_block = 0;
+ struct list_head *tmp = NULL;
+ struct list_head *cur = NULL;
+ struct jbd2_blk_pair *b_pair = NULL;
+ int err = 0;
+ journal_t *journal = EXT4_JOURNAL(inode);
+
+ /* Do not allow last_block to wrap */
+ last_block = first_block + count;
+ if (last_block< first_block)
+ last_block = EXT_MAX_BLOCKS;
+
+ /*
+ * Force the journal to finnish up any pending transactions
+ * before we start secure deleteing journal blocks
+ */
+ err = ext4_force_commit((inode)->i_sb);
+ if (err)
+ return err;
+
+ spin_lock(&journal->j_pair_lock);
+
+ /* Loop over the journals blocks looking for our logical blocks */
+ list_for_each_safe(cur, tmp,&journal->blk_pairs) {
+ b_pair = list_entry(cur, struct jbd2_blk_pair, list);