public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* PATCH - ext2fs privacy (i.e. secure deletion) patch
@ 2004-01-28 16:30 the grugq
  2004-02-03 22:20 ` Pavel Machek
  0 siblings, 1 reply; 45+ messages in thread
From: the grugq @ 2004-01-28 16:30 UTC (permalink / raw)
  To: linux-kernel

[-- Attachment #1: Type: text/plain, Size: 3453 bytes --]

Hi,

I've written a quick patch to the ext2fs which ensures that inodes, data 
  blocks, and directory entries are overwritten with null bytes when 
they are deleted. The patch adds a couple of inline functions to 
overwrite the appropriate data with zeroes. Its quite simple and 
self-explanitory. Both attached patches are to a vanilla 2.4.24 kernel.

inodes: ext2_delete_inode() now uses the inline function delete_inode() 
to mark the on-disk inode as 'deleted'. If the privacy option is not 
enabled, then the i_dtime is set as per usual operation, otherwise the 
meta-data are all set to 0. After the inode has been truncated, the 
i_data is set to 0 by delete_blocks() and the inode is written to disk 
again.

Splitting the delete_inode() and delete_blocks() functions is not ideal, 
I would prefer that one function remove the meta-data and the inode be 
written out just once. The problem is that ext2_truncate() needs the 
i_data information from the struct inode, and we want to remove this 
information from the inode on the disk. To ensure that the i_data is 0 
by the time it hits the disk, I write the inode to disk twice, which is 
not optimal.

directory entries: ext2_delete_entry() now uses the inline function 
mark_delete_dir() to indicate that the directory entry is no longer 
valid. If the privacy patch is not enabled, then the dir->inode is set 
to  0 as per normal operation, otherwise the entry is memset 0. Very 
straightforward.

blocks: ext2_free_blocks() now uses the inline function destroy_block() 
before it updates the group meta-data. The destroy_block() function 
overwrites the block with zeroes. I'm not sure that it is implemented 
correctly, I don't know anything about buffer_heads. The block is only 
overwritten with a single pass of zeroes. It is, of course, possible to 
have a full 37 pass overwriter with full bit toggling maps and all that, 
but I think it might make more sense to add a new option for that, 
something like: CONFIG_EXT2_FS_PRIVACY_EXTREME_PARANOIA. For preventing 
simple forensic analysis (that is, what the police, employers and even 
most government agencies do) a single pass with zeroes is sufficient. 
Users can use userland tools like wipe or srm for more thorough overwriting.

There is also a patch to ext3fs, which adds the same functionality (in 
the same way) as the ext2fs privacy patch. However, the main problem 
with privacy on the ext3fs is the journal. I am not familiar enough with 
how the journal transactions are handled to implement what seems to me 
the obvious solution: when a transaction is complete (i.e. doesn't need 
to be replayed by fsck) overwrite it with null bytes. If done correctly, 
it is possible to leave sufficient information for fsck to find the 
right transaction to begin replaying, without leaving any data which 
would be of use to a forensic analyst.

Given the existing global political climate, privacy control over a file 
system seems like a no-brainer to me. Full privacy options would include 
things like mounting disks with noatime, and possibly normalizing the 
mtime and ctime of all inodes (setting everthing to an arbitrary date, 
e.g. 0). Certainly this will break tools like make which require atime, 
but it would provide even less information to a forensic analyst 
examining the file system.



peace,

--gq

ps. apologies for posting to the kernel mailing list, but I'm not sure 
who is the maintainer for ext2/3.





[-- Attachment #2: privacy_patch_ext2 --]
[-- Type: text/plain, Size: 3509 bytes --]

--- linux-2.4.24/fs/Config.in	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.24/fs/Config.in-ext2-privacy	2004-01-27 21:56:58.000000000 +0000
@@ -92,6 +92,7 @@
 tristate 'ROM file system support' CONFIG_ROMFS_FS
 
 tristate 'Second extended fs support' CONFIG_EXT2_FS
+dep_mbool '  ext2 privacy support' CONFIG_EXT2_FS_PRIVACY $CONFIG_EXT2_FS
 
 tristate 'System V/Xenix/V7/Coherent file system support' CONFIG_SYSV_FS
 
--- linux-2.4.24/fs/ext2/balloc.c	2003-06-13 15:51:37.000000000 +0100
+++ linux-2.4.24/fs/ext2-privacy/balloc.c	2004-01-28 00:52:59.000000000 +0000
@@ -247,6 +247,23 @@
 	return slot;
 }
 
+static inline void destroy_block(struct inode *inode, unsigned long block)
+{
+#ifdef CONFIG_EXT2_FS_PRIVACY
+	struct buffer_head	* bh;
+
+	bh = sb_getblk(inode->i_sb, block);
+
+	memset(bh->b_data, 0x00, bh->b_size);
+
+	mark_buffer_dirty(bh);
+	wait_on_buffer(bh);
+	brelse(bh);
+
+	return;
+#endif
+}
+
 /* Free given blocks, update quota and i_blocks field */
 void ext2_free_blocks (struct inode * inode, unsigned long block,
 		       unsigned long count)
@@ -319,6 +336,8 @@
 				   "bit already cleared for block %lu", block);
 		else {
 			DQUOT_FREE_BLOCK(inode, 1);
+
+			destroy_block(sb, block);
 			gdp->bg_free_blocks_count =
 				cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count)+1);
 			es->s_free_blocks_count =
--- linux-2.4.24/fs/ext2/dir.c	2002-11-28 23:53:15.000000000 +0000
+++ linux-2.4.24/fs/ext2-privacy/dir.c	2004-01-25 17:15:27.000000000 +0000
@@ -468,6 +468,15 @@
 	return err;
 }
 
+static inline mark_deleted_dir(struct ext2_dir_entry_2 *dir)
+{
+#ifndef CONFIG_EXT2_FS_PRIVACY
+	dir->inode = 0;
+#else
+	memset(dir, 0, dir->rec_len);
+#endif
+}
+
 /*
  * ext2_delete_entry deletes a directory entry by merging it with the
  * previous entry. Page is up-to-date. Releases the page.
@@ -495,7 +504,7 @@
 		BUG();
 	if (pde)
 		pde->rec_len = cpu_to_le16(to-from);
-	dir->inode = 0;
+	mark_deleted_dir(dir);
 	err = ext2_commit_chunk(page, from, to);
 	UnlockPage(page);
 	ext2_put_page(page);
--- linux-2.4.24/fs/ext2/inode.c	2003-06-13 15:51:37.000000000 +0100
+++ linux-2.4.24/fs/ext2-privacy/inode.c	2004-01-27 21:33:59.000000000 +0000
@@ -46,6 +46,36 @@
 	ext2_discard_prealloc (inode);
 }
 
+static inline void delete_inode(struct inode *inode)
+{
+#ifndef CONFIG_EXT2_FS_PRIVACY
+	inode->u.ext2_i.i_dtime	= CURRENT_TIME;
+#else
+	inode->i_mode	= 0;
+	inode->i_uid	= 0;
+	inode->i_gid	= 0;
+	inode->i_nlink	= 0;
+	inode->i_atime	= 0;
+	inode->i_ctime	= 0;
+	inode->i_mtime	= 0;
+	inode->u.ext2_i.i_dtime	= 0;
+	inode->u.ext2_i.i_flags	= 0;
+	inode->u.ext2_i.i_faddr	= 0;
+	inode->u.ext2_i.i_frag_no	= 0;
+	inode->u.ext2_i.i_frag_size	= 0;
+	inode->u.ext2_i.i_file_acl	= 0;
+	inode->i_generation	= 0;
+#endif
+}
+
+static inline void delete_blocks(struct inode *inode)
+{
+#ifdef CONFIG_EXT2_FS_PRIVACY
+	inode->i_blocks	= 0;
+	memset(&inode->u.ext2_i.i_data, 0x00, sizeof(inode->u.ext2_i.i_data));
+#endif
+}
+
 /*
  * Called at the last iput() if i_nlink is zero.
  */
@@ -57,12 +87,18 @@
 	    inode->i_ino == EXT2_ACL_IDX_INO ||
 	    inode->i_ino == EXT2_ACL_DATA_INO)
 		goto no_delete;
-	inode->u.ext2_i.i_dtime	= CURRENT_TIME;
+
+	delete_inode(inode);
 	mark_inode_dirty(inode);
 	ext2_update_inode(inode, IS_SYNC(inode));
+
 	inode->i_size = 0;
 	if (inode->i_blocks)
 		ext2_truncate (inode);
+	delete_blocks(inode);
+       mark_inode_dirty(inode);
+       ext2_update_inode(inode, IS_SYNC(inode));
+
 	ext2_free_inode (inode);
 
 	unlock_kernel();

[-- Attachment #3: privacy_patch_ext3 --]
[-- Type: text/plain, Size: 2505 bytes --]

--- linux-2.4.24/fs/Config.in	2003-11-28 18:26:21.000000000 +0000
+++ linux-2.4.24/fs/Config.in-ext3-privacy	2004-01-27 21:57:22.000000000 +0000
@@ -34,6 +34,7 @@
 # dep_tristate '  Journal Block Device support (JBD for ext3)' CONFIG_JBD $CONFIG_EXT3_FS
 define_bool CONFIG_JBD $CONFIG_EXT3_FS
 dep_mbool '  JBD (ext3) debugging support' CONFIG_JBD_DEBUG $CONFIG_JBD
+dep_mbool '  ext3 privacy support' CONFIG_EXT3_FS_PRIVACY $CONFIG_EXT3_FS
 
 # msdos file systems
 tristate 'DOS FAT fs support' CONFIG_FAT_FS
--- linux-2.4.24/fs/ext3/balloc.c	2003-06-13 15:51:37.000000000 +0100
+++ linux-2.4.24/fs/ext3-privacy/balloc.c	2004-01-28 00:44:56.000000000 +0000
@@ -252,6 +252,23 @@
 	return slot;
 }
 
+static inline void destroy_block(struct inode *inode, unsigned long block)
+{
+#ifdef CONFIG_EXT3_FS_PRIVACY
+	struct buffer_head	* bh;
+
+	bh = sb_getblk(inode->i_sb, block);
+
+	memset(bh->b_data, 0x00, bh->b_size);
+
+	mark_buffer_dirty(bh);
+	wait_on_buffer(bh);
+	brelse(bh);
+
+	return;
+#endif
+}
+
 /* Free given blocks, update quota and i_blocks field */
 void ext3_free_blocks (handle_t *handle, struct inode * inode,
 			unsigned long block, unsigned long count)
@@ -370,6 +387,7 @@
 			BUFFER_TRACE(bitmap_bh, "bit already cleared");
 		} else {
 			dquot_freed_blocks++;
+			destroy_block(sb, block);
 			gdp->bg_free_blocks_count =
 			  cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count)+1);
 			es->s_free_blocks_count =
--- linux-2.4.24/fs/ext3/inode.c	2003-08-25 12:44:43.000000000 +0100
+++ linux-2.4.24/fs/ext3-privacy/inode.c	2004-01-27 21:48:54.000000000 +0000
@@ -172,6 +172,28 @@
 	ext3_discard_prealloc (inode);
 }
 
+static inline void delete_inode(struct inode *inode)
+{
+#ifndef CONFIG_EXT3_FS_PRIVACY
+	inode->u.ext3_i.i_dtime	= CURRENT_TIME;
+#else
+	inode->i_mode	= 0;
+	inode->i_uid	= 0;
+	inode->i_gid	= 0;
+	inode->i_nlink	= 0;
+	inode->i_size	= 0;
+	inode->i_blocks	= 0;
+	inode->i_atime	= 0;
+	inode->i_ctime	= 0;
+	inode->i_mtime	= 0;
+	inode->u.ext3_i.i_dtime	= 0;
+	inode->u.ext3_i.i_flags	= 0;
+	inode->u.ext3_i.i_file_acl	= 0;
+	inode->i_generation	= 0;
+	memset(&inode->u.ext3_i.i_data, 0x00, sizeof(inode->u.ext3_i.i_data));
+#endif
+}
+
 /*
  * Called at the last iput() if i_nlink is zero.
  */
@@ -211,7 +233,7 @@
 	 * (Well, we could do this if we need to, but heck - it works)
 	 */
 	ext3_orphan_del(handle, inode);
-	inode->u.ext3_i.i_dtime	= CURRENT_TIME;
+	delete_inode(inode);
 
 	/* 
 	 * One subtle ordering requirement: if anything has gone wrong

^ permalink raw reply	[flat|nested] 45+ messages in thread
* Re: PATCH - ext2fs privacy (i.e. secure deletion) patch
@ 2004-02-07  9:55 Albert Cahalan
  0 siblings, 0 replies; 45+ messages in thread
From: Albert Cahalan @ 2004-02-07  9:55 UTC (permalink / raw)
  To: linux-kernel mailing list; +Cc: reiser

Hans Reiser writes:

> There is an extensive literature on how you can recover
> deleted files from media that has been erased a dozen
> times,

I doubt this is true in any way that matters.

Unless you get REALLY lucky with bad sector
substitution and you know the secret
vendor-specific drive commands to fetch bad
sectors, you'll need the physical hardware.

   no hardware  --->  no data recovery

Given that you do have the physical hardware,
how are you going to read it? You'll need
some equipment that will cost you many millions
of dollars. So this isn't going to be anybody
but the CIA, NSA, or non-US equivelent. They
won't bother very often; even a "black" budget
is limited. Are you so sure you're worth it?

Does the "extensive literature" cover drives
made in the last year? (decade?) These days,
manufacturers are using extremely thin layers
of surface material over an inert substrate.
Magnetic domains flip in an all-or-nothing
fashion; the old recovery methods rely on
finding some buried domains that didn't flip.
With the layers getting damn thin, I doubt
any will exist. There just won't be any
residual signal from previous writes, and so
the recovery methods have nothing to work with.

> but breaking encryption is harder.  It is more
> secure to not put the data on disk unencrypted at all
> is my point.....

This leads to one method of implementing the
secure deletion flag. At boot, generate a
random key for the log file. At file creation,
generate a random key for the file body and
inode. (these are internal to the filesystem)
When you want to destroy something, wipe the key.
Remember to flush and regenerate the log file.



^ permalink raw reply	[flat|nested] 45+ messages in thread

end of thread, other threads:[~2004-02-18  9:49 UTC | newest]

Thread overview: 45+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-01-28 16:30 PATCH - ext2fs privacy (i.e. secure deletion) patch the grugq
2004-02-03 22:20 ` Pavel Machek
2004-02-04  0:33   ` the grugq
2004-02-04  0:43     ` Pavel Machek
2004-02-04  0:48       ` the grugq
2004-02-04  0:55         ` Pavel Machek
2004-02-04  0:58           ` the grugq
2004-02-04  1:10             ` Mike Fedyk
2004-02-04  6:29       ` Theodore Ts'o
2004-02-04 13:08         ` the grugq
2004-02-04 17:05           ` Bill Davidsen
2004-02-04 17:14             ` Valdis.Kletnieks
2004-02-04 23:47               ` Bill Davidsen
2004-02-04 23:51                 ` the grugq
2004-02-05  1:48                 ` the grugq
2004-02-05  4:38                 ` Valdis.Kletnieks
2004-02-07  3:30                   ` Bill Davidsen
2004-02-05  3:35               ` Theodore Ts'o
2004-02-06  0:00                 ` the grugq
2004-02-12 22:59         ` Robert White
2004-02-13  3:41           ` Jamie Lokier
2004-02-13 21:30             ` Robert White
2004-02-18  3:48             ` Bill Davidsen
2004-02-18  9:48               ` Jamie Lokier
2004-02-17 12:00           ` Pavel Machek
2004-02-04  3:20     ` Valdis.Kletnieks
2004-02-07  0:20       ` Jamie Lokier
2004-02-07  1:15         ` Hans Reiser
2004-02-07  1:29           ` the grugq
2004-02-07  5:40             ` Hans Reiser
2004-02-07  9:55               ` the grugq
2004-02-07 10:47                 ` Jamie Lokier
2004-02-07 11:02                   ` the grugq
2004-02-07 11:09                     ` Jamie Lokier
2004-02-07 11:46                       ` the grugq
2004-02-07 12:01                         ` Jamie Lokier
2004-02-07 16:52                           ` Hans Reiser
2004-02-07 17:22                           ` Pavel Machek
2004-02-08  0:04                             ` Jamie Lokier
2004-02-07 16:50                         ` Hans Reiser
2004-02-07 16:44                   ` Hans Reiser
2004-02-09 12:07                     ` Edward Shishkin
2004-02-10  7:18                       ` Hans Reiser
2004-02-07  2:17           ` Jamie Lokier
  -- strict thread matches above, loose matches on Subject: below --
2004-02-07  9:55 Albert Cahalan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox