This time, in our OSDI lab, we are asked to implement a XOR Encryption/Decryption while someone is read/write the ramfs.
Setup the Flag (switch on/off the encryption/decryption feature)
Register a proc_dir_entry in fs/ramfs/inode.c to listen the external controls of the flag. A proc_read and a proc_write function is required. So...
Global Variables & Macros
#define MAX_PROC_SIZE 100 int ramfs_flag; static struct proc_dir_entry *proc_entry;
(register) Modify init_ramfs_fs
static int __init init_ramfs_fs(void) { // ODSI lab 10 proc_entry = create_proc_entry("flag", 0644, NULL); proc_entry->read_proc = my_read; proc_entry->write_proc = my_write; ramfs_flag = 0; // return register_filesystem(&ramfs_fs_type); }
(remove) Modifiy exit_ramfs_fs
static void __exit exit_ramfs_fs(void) { // ODSI lab 10 remove_proc_entry("flag", NULL); unregister_filesystem(&ramfs_fs_type); }
(read) Add proc_read Handler
static int my_read(char *buf, char **start, off_t offset, int count, int *eof, void *data) { int len=0; len = sprintf(buf,"%d\n", ramfs_flag); return len; }
(write) Add proc_write Handler
static int my_write(struct file *file, const char *buf, unsigned long count, void *data) { char t_data[MAX_PROC_SIZE]; if(copy_from_user(t_data, buf, count)) return -EFAULT; if(t_data[0] != '0' && t_data[0] != '1'){ printk("garbage ignored\n"); return count; // just ignore } printk("my_write get : %s\n", t_data); // success setup if(t_data[0] == '0') ramfs_flag = 0; else if(t_data[0] == '1') ramfs_flag = 1; printk("ramfs_flag = %d ramfs_addr = %p\n", ramfs_flag, &ramfs_flag); return count; }
Implement the Encryption/Decryption when the Flag is Up
Make our Flag Accessible by the MMU (fs/ramfs/internal.h)
extern const struct address_space_operations ramfs_aops; extern const struct inode_operations ramfs_file_inode_operations; extern int ramfs_flag;
Switch to Our Custom Handlers for MMU Read/Write (mm/file-mmu.c)
const struct file_operations ramfs_file_operations = { .read = do_sync_read, .aio_read = my_aio_read, // OSDI lab 10 .write = do_sync_write, .aio_write = my_aio_write, // OSDI lab 10 .mmap = generic_file_mmap, .fsync = simple_sync_file, .splice_read = generic_file_splice_read, .splice_write = generic_file_splice_write, .llseek = generic_file_llseek, };
Encryption (mm/file-mmu.c)
ssize_t my_aio_write(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, loff_t pos) { printk("OSDI: custom write\n"); if(ramfs_flag && iov!=NULL) { size_t i; char *ib = (char *)iov->iov_base; for( i=0 ; i < iov->iov_len ; i++ ) ib[i] ^= ENCODE_KEY; printk("ramfs_flag is up\n"); } return generic_file_aio_write(iocb, iov, nr_segs, pos); }
Decryption (mm/file-mmu.c)
ssize_t my_aio_read(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, loff_t pos) { ssize_t r; printk("OSDI: custom read\n"); r = generic_file_aio_read(iocb, iov, nr_segs, pos); if(ramfs_flag) { size_t i; char *ib = (char *)iov->iov_base; for( i=0 ; i < iov->iov_len ; i++ ) ib[i] ^= ENCODE_KEY; printk("ramfs_flag is up\n"); } return r; }
p.s. ENCODE_KEY can be any character size constant (ex. 0x25)
Run & Test
It should be something like this:
>> mount -t ramfs ramfs /mnt/ramfs/ >> cd /mnt/ramfs/ >> cat /proc/flag 0 >> echo 1 > /proc/flag >> cat /proc/flag 1 >> echo hello > test >> cat test hello >> echo 0 > /proc/flag >> cat test M@IIJ/
No comments:
Post a Comment