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/


