Secure Deletion under Linux kernel patch. If a regular file has set attribute "s" on ext2 filesystem, the file will be securely deleted after an "unlink" call by the "srm" program.
811368f0d49a265a31ec7d3e3cfb51a7diff -u -w -r /usr/src/linux-origin/fs/namei.c /usr/src/linux/fs/namei.c
--- /usr/src/linux-origin/fs/namei.c Sun Jan 30 17:03:48 2000
+++ /usr/src/linux/fs/namei.c Sat Feb 12 10:35:53 2000
@@ -12,11 +12,17 @@
* lookup logic.
*/
+#define __KERNEL_SYSCALLS__
+
#include <linux/mm.h>
#include <linux/proc_fs.h>
#include <linux/smp_lock.h>
#include <linux/quotaops.h>
+#include <linux/string.h>
+#include <linux/unistd.h>
+#include <linux/sched.h>
+
#include <asm/uaccess.h>
#include <asm/unaligned.h>
#include <asm/semaphore.h>
@@ -24,6 +30,8 @@
#include <asm/pgtable.h>
#include <asm/namei.h>
+#include <linux/ext2_fs.h> /* for EXT2_SECRM_FL */
+
/* This can be removed after the beta phase. */
#define CACHE_SUPERVISE /* debug the correctness of dcache entries */
@@ -1025,25 +1033,202 @@
return error;
}
-int vfs_unlink(struct inode *dir, struct dentry *dentry)
+
+
+
+
+
+/* call program secrm - security delete */
+static int vfs_unlink_exec_srm(void *file_name)
+{
+
+ static char * envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
+ char *argv[]={"/bin/secrm",(char *)file_name,NULL };
+
+
+
+ /* Prevent parent user process from sending signals to child.
+ Otherwise, if the secrm program does not exist, it might
+ be possible to get a user defined signal handler to execute
+ as the super user right after the execve fails if you time
+ the signal just right.
+ */
+ spin_lock_irq(¤t->sigmask_lock);
+ flush_signals(current);
+ flush_signal_handlers(current);
+ spin_unlock_irq(¤t->sigmask_lock);
+
+
+ /* Drop the "current user" thing */
+ free_uid(current);
+
+ /* Give secrm all privileges..
+ Waitpid reports error without it. */
+ current->uid = current->euid = current->fsuid = 0;
+ cap_set_full(current->cap_inheritable);
+ cap_set_full(current->cap_effective);
+
+
+
+
+
+ /* Allow execve args to be in kernel space. */
+
+
+
+/* printk("set_fs(KERNEL_DS)\n");*/
+
+ set_fs(KERNEL_DS);
+
+/* printk("Execve\n"); */
+
+ /* Go, go, go... */
+ if (execve("/bin/secrm", argv, envp) < 0) {
+
+ printk("vfs_unlink_exec_srm: can't exec /bin/secrm\n");
+ return -errno;
+ }
+
+ return 0;
+
+
+}
+
+
+int vfs_unlink(struct inode *dir, struct dentry *dentry, const char *name, struct dentry **dir2)
{
int error;
+ pid_t pid,waitpid_result;
+ int status;
+ sigset_t tmpsig;
+ mm_segment_t addr_limit;
+
error = may_delete(dir, dentry, 0);
if (!error) {
error = -EPERM;
if (dir->i_op && dir->i_op->unlink) {
+
+ /*dentry->d_inode->i_sb->s_type->name == ext2*/
+ /* filesystem type*/
+
+ if (!strcmp(dentry->d_inode->i_sb->s_type->name,"ext2"))
+ {
+
+
+ if (dentry->d_inode->u.ext2_i.i_flags & EXT2_SECRM_FL )
+ {
+
+
+ /* printk("Security flag set.\n"); */
+
+ if (S_ISREG(dentry->d_inode->i_mode)) {
+ /* printk("Regular file: %s\n",name); */
+
+ /* printk("Starting thread...\n"); */
+
+ unlock_dir(*dir2);
+ unlock_kernel();
+
+ *dir2=NULL; /* do_unlink - don't unlock*/
+ /* printk("vfs_unlink: unlock\n"); */
+
+ pid = kernel_thread(vfs_unlink_exec_srm, (void*) name, 0);
+
+
+
+ if (pid<0) {
+ printk("fork failed: vfs_unlink_exec_srm\n");
+ lock_kernel();
+ return -EIO;
+
+ }
+
+
+
+ /* Block everything but SIGKILL/SIGSTOP */
+ spin_lock_irq(¤t->sigmask_lock);
+ tmpsig = current->blocked;
+ siginitsetinv(¤t->blocked, sigmask(SIGKILL) | sigmask(SIGSTOP));
+ recalc_sigpending(current);
+ spin_unlock_irq(¤t->sigmask_lock);
+
+ /*printk("Waitpid...\n");*/
+
+ addr_limit=get_fs();
+
+ set_fs(KERNEL_DS);
+
+
+ waitpid_result = waitpid(pid, &status,__WCLONE);
+
+ set_fs(addr_limit);
+
+ /* Allow signals again.. */
+ spin_lock_irq(¤t->sigmask_lock);
+ current->blocked = tmpsig;
+ recalc_sigpending(current);
+ spin_unlock_irq(¤t->sigmask_lock);
+
+
+
+ /*printk("\npid:%i\nwaitpid:%i\nresult:%i\n\n",pid,waitpid_result,status);*/
+
+ lock_kernel();
+
+ if (waitpid_result != pid) {
+
+ printk("vfs_unlink: secrm error (waitpid)\n");
+ return -EIO;
+ }
+
+ if (!status) return 0; /* OK */
+
+ if (status<0x100) {
+
+
+ printk("vfs_unlink: secrm - signal %i caught.\n",status);
+
+ return -EINTR;
+
+
+ }
+
+
+ status=status>>8;
+
+ /* printk("vfs_unlink: secrm exit code:%i\n",status); */
+
+ return -status;
+
+
+ }
+
+ }
+
+
+ }
+
+
+
+
+
DQUOT_INIT(dir);
error = dir->i_op->unlink(dir, dentry);
+
}
+
}
+
return error;
}
+
+
static inline int do_unlink(const char * name)
{
int error;
- struct dentry *dir;
+ struct dentry *dir,*dir2;
struct dentry *dentry;
dentry = lookup_dentry(name, NULL, 0);
@@ -1051,12 +1236,15 @@
if (IS_ERR(dentry))
goto exit;
- dir = lock_parent(dentry);
+ dir=dir2= lock_parent(dentry);
error = -ENOENT;
if (check_parent(dir, dentry))
- error = vfs_unlink(dir->d_inode, dentry);
+ error = vfs_unlink(dir->d_inode, dentry,name,&dir2);
- unlock_dir(dir);
+ /* dir2 == NULL - dir unlocked */
+
+ if (dir2) unlock_dir(dir);
+/* else printk("do_unlock: don't unlock\n"); */
dput(dentry);
exit:
return error;
diff -u -w -r /usr/src/linux-origin/include/linux/fs.h /usr/src/linux/include/linux/fs.h
--- /usr/src/linux-origin/include/linux/fs.h Sun Jan 30 17:48:15 2000
+++ /usr/src/linux/include/linux/fs.h Wed Feb 9 23:49:16 2000
@@ -566,7 +566,7 @@
* VFS helper functions..
*/
extern int vfs_rmdir(struct inode *, struct dentry *);
-extern int vfs_unlink(struct inode *, struct dentry *);
+extern int vfs_unlink(struct inode *, struct dentry *, const char * name, struct dentry **) ;
extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
/*
Comments
No comments yet, be the first!