Skip to content

disdi/address-space-ops-in-wrapfs

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 

Repository files navigation

The source files present in this directory consists of source-code to add to support address_space operations instead of vm_ops operations and to add file data encryption to the wrapfs filesystem. 

 --------------
| Source files |
 -------------- 
Below files are modified version of original wrapfs
1) wrapfs/wrapfs.h - Added extra fields in wrapfs_sb_info struct to hold mount options and key to encrypt and decrypt. Created a structure which hold the mount options. This is done by keeping extensibility in mind. If in future some more mount options are added then the code can be modified and parsed easily without much hassle. Added wrapfs_parse_options function which parses the mount options. This function is implemented using the similar function in UDF file system source code. Added extra file_operations structure.
2) wrapfs/file.c - Added new file operations structure. Modified ->read, ->write, ->unlocked_ioctl to handle encryption-decryption. Modified ->mmap operation to assign address_operations according to the mount options provided.
3) wrapfs/lookup.c - Modified wrapfs_iget() function to make it point to the necessary file_operations and address_operations according to the mount options specified.
4) wrapfs/main.c - Modified wrapfs_read_super() function to store and initialize mount options and key in wrapfs_sb_info structure. Modified wrapfs_mount() function to parse for mount options. The parsing function can recognize the options mmap and debug. The debug mount option is not fully implemented but the parser is having the capability to parse it from the mount command. I did not remove this code as it doesnot affect other parts.
5) wrapfs/mmap.c - Added new address_operations structure and instantiated a dummy address_operations structure to point it according to the mount options. I have copied code from ecryptfs and old unionfs sources. I have used ->readpage, ->write_begin, ->write_end from ecryptfs and ->writepage from unionfs.
6) wrapfs/super.c - Added wrapfs_parse_options to parse mount options. Necessary structures needed for parsing are also added in this file.
7) wrapfs/Makefile - I have edited the Makefile to take one more flag to include conditional compiling. I have also added commands to compile and clean the user programs accordingly.

Newly added files
1) wrapfs/wrapfs_setkey.c - This is a user-level ioctl program which is used to set/reset the key required for encrypt/decrypt files. I am currently using 1 as ioctl number for setting or resetting key. If the key length is not restricted at the user program , however only 32 bytes will be copied at the kernel level in unlocked_ioctl() function. If the key is provided as 123 then I am using it as 12300000000000000000000000000000 making it length of 32 bytes. I am using 32 bytes of 0 to reset the key. I am not allowing to read or write data when the key is not set or the key is revoked. The user can give the key of any length of 0s to revoke, I am internally converting it to 32 bytes length and interpreting.
2) wrapfs/test/read_demo.c - This file tries to read data from /mnt/mpt_wrapfs/a.txt
3) wrapfs/test/write_demo.c - This file tries to write data to /mnt/mpt_wrapfs/a.txt, If the file doesnot exists it creates it and tries to write data.


The kernel sources can be downloaded from  http://www.kernel.org/pub/linux/kernel/v3.0/linux-3.2.2.tar.bz2
Once downloaded, copy the contents of wrapfs folder to fs/wrapfs/ in kernel sources.

 -------------
| Executables |
 -------------
1) wrapfs_setkey.o - This executable is the ioctl program. The usage of the program is self explanatory, however it is given below.
"Usage: %s {-k KEY} [-h HELP] mount_point"
"-k : Use to give key. Ex: -k "key""
"-h : Use to display this help message"
2) test/read_demo.o - As explained above in "Source Files" section.
3) test/write_demo.o - As explained above in "Source Files" section.

  -------------------------------------------------------------
| Steps to be followed for compiling and executing this project |
  -------------------------------------------------------------
Compiling: 
Go to fs/wrapfs
#make - To compile without Part 2 of the HW2
#make CRYPTO+=-DWRAPFS_CRYPTO - To compile both Part 1 and Part 2 of HW2

Insert module:
#insmod wrapfs.ko

Mounting:
#mount -t wrapfs -o mmap /tmp /mnt/mpt_wrapfs - It takes mmap option to specify whether address operations or not. The usage of this option depends on the type of "make". If "make" is performed using WRAPFS_CRYPTO, then the mount with -o mmap option results in using address operations as well as performing encryption and decryption if the key is set. 

Setting the key:
#./wrapfs_setkey.o -k 123 /mnt/mpt_wrapfs - Here 123 is the key encrypt or decrypt. If 0 is passed as key, then it revokes/resets the key. It will accept series of 0s as a command to set or revoke key. Without key, the read and write operations are not allowed.

Unmounting:
#umount /mnt/mpt_wrapfs

Removing module:
#rmmod wrapfs

 ---------------------------------
| Compiling the user-applications |
 ---------------------------------
Go to fs/wrapfs and do make (any of the make as specified above). This will automatically result in compiling the wrapfs as well as the user-ioctl program wrapfs_setkey and also the test programs in the test/ directory.

make clean will result in removing all the temporary object files.

 ----------------------
| Design Considerations |
 ----------------------
1) I havent implemented IOCTL by following guidelines from the linux documentation guidelines. But used an ioctl number as 1 for my file system.
2) If the user compiles the filesystem using WRAPFS_CRYPTO and mounts it using mmap option, then the user has to set the key before performing any read or write. The user has to invoke the ioctl() for the file system and pass in the key required for encrypting and decrypting. If the ioctl() is not invoked, read or write will return -ENOKEY error code. The only bug is the files will be created without writing data if the ioctl is not called and the key is not set. 
3) File descriptor has to be passed to the ioctl(). I assumed that the mount point will be known ahead of time before doing a read and write. So using the "wrapfs_setkey" utility program, I have opened the mount point directory as O_RDONLY, get the file descriptor, to invoke the ioctl.
 
 ---------
| Testing |
 ---------
I was not able to run LTP test suite on my project. Instead I have written a sample user applications which has read() and write() system calls which will inturn invoke file operations depending on the mounted wrapfs file system.

Create mpt_wrapfs directory in /mnt/. Before running every test case mentioned below, make sure that /tmp is cleared (delete all the existing files) and /mnt/mpt_wrapfs is cleared (delete all the existing files).

I have created below files for testing
wrapfs/read_demo.c - this file tries to read /mnt/mpt_wrapfs/a.txt
wrapfs/write_demo.c - this file tries to write /mnt/mpt_wrapfs/a.txt

Please see "Steps to be followed for compiling and executing this project" section mentioned above to use various conditional compiling useful for testing below test cases.

After compiling, goto fs/wrapfs and execute
# insmod wrapfs.ko

Testcase 1 - Compile using "make" in <downloaded_kernel_sources_path>/fs/wrapfs/
# mount -t wrapfs /tmp /mnt/mpt_wrapfs
# cd test
# ./write_demo.o
# ./read_demo.o
It should display "Writing th". In this test case, it will not use address operations. The original wrapfs code works fine as if it is unmodified.

Testcase 2 - Compile using "make" in <downloaded_kernel_sources_path>/fs/wrapfs/
# mount -t wrapfs -o mmap /tmp /mnt/mpt_wrapfs
# cd test
# ./write_demo.o
# ./read_demo.o
It should display "Writing th". In this test case, it will use address operations. Instead of using vfs_read() and vfs_write(), the address operations ->readpage and ->write_begin, ->write_end will be invoked.

Testcase 3 - Compile using "make CRYPTO=-DWRAPFS_CRYPTO" in <downloaded_kernel_sources_path>/fs/wrapfs/
# mount -t wrapfs /tmp /mnt/mpt_wrapfs
# cd test
# ./write_demo.o
# ./read_demo.o
It should display "Writing th". In this test case, it will not use address operations. The original wrapfs code works fine as if it is unmodified. The only difference between Testcase 1 and this testcase is that the conditional code inserted between #ifdef WRAPFS_CRYPTO and #endif will be compiled and burnt into wrapfs.ko 

Testcase 4 - Compile using "make CRYPTO=-DWRAPFS_CRYPTO" in <downloaded_kernel_sources_path>/fs/wrapfs/
# mount -t wrapfs -o mmap /tmp /mnt/mpt_wrapfs
# ./wrapfs_set.o -k 123 /mnt/mpt_wrapfs
# cd test
# ./write_demo.o
# ./read_demo.o
It should display "Writing th". In this test case, it will use address operations. Now the ->readpage and ->write_begin, ->write_end will encrypt and decrypt the data. 
Since we are mounting /tmp on /mnt/mpt_wrapfs we will get to see files while navigating from both /tmp/a.txt and /mnt/mpt_wrapfs/a.txt
However, reading file from /tmp/a.txt will result in encrypted data. Reading file from /mnt/mpt_wrapfs/a.txt will result in decrypted file.
Writing files from /mnt/mpt_wrapfs will encrypt the data using the key set using "./wrapfs_set.o -k 123 /mnt/mpt_wrapfs" and will write in /mnt/mpt_wrapfs and finally to /tmp. Of-course, writing a file through /tmp will not encrypt and write.

The key can be reset anytime by "# ./wrapfs_set.o -k 345 /mnt/mpt_wrapfs", if the key is changed in between and write or read is performed and again read/write are performed then they will be using newly provided key to encrypt and decrypt and possibly will result in providing the user with corrupted data. The key can be reset using any number of 0s in the key. Ex: "# ./wrapfs_set.o -k 0 /mnt/mpt_wrapfs".

Testcase 5 - Compile using "make CRYPTO=-DWRAPFS_CRYPTO" in <downloaded_kernel_sources_path>/fs/wrapfs/
# mount -t wrapfs -o mmap /tmp /mnt/mpt_wrapfs
# cd test
# ./write_demo.o
# ./read_demo.o

In this test case, we are not setting the key using ioctl() system call. So without setting the key, the file system doesnt allow us to read or write data. Ideally it should not allow to create the file itself in the first place, but in my implementation I could not resolve this. Instead, it would create a blank file and any following read()/write() will result in returning -ENOKEY to the user. The error message can be seen if we do 
/mnt/mpt_wrapfs# cat a.txt 
after executing the above program.

 ------------
| References |
 ------------ 
1) Instead of using HW1 encrypt and decrypt functions, I used the example from below link to invoke encrypt() and decrypt() functions.
http://stackoverflow.com/questions/9156076/aes-encryption-error-unknown-symbol-crypto-alloc-base
2) An in-depth look at file handling in the Linux kernel
http://kevinboone.net/linuxfile.html
3) I have copied code from ecryptfs and old unionfs sources. I have used ->readpage, ->write_begin, ->write_end from ecryptfs and ->writepage from unionfs.
4) I have used mmapdemo.c test program from http://beej.us/guide/bgipc/examples/mmapdemo.c to test my ->mmap file operation.

About

Modified wrapfs stackable file system to support address space operations and file data encryption and decryption for linux 3.2.2 kernel

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published