Skip to content

mappinisbu/AntiMalwareFileSystem

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 

Repository files navigation

***********************************************
Stackable Anti Malware File System
***********************************************
--------------
Functionality
--------------

AMFS is a anti-malware file system that detects malware patterns in the filesystem on top of which AMFS is mounted.
It prevents read/write/rename to the bad files( files that contain malware pattern) in the underlying file system
 and hides them in the directory in which they are listed. However, bad files can be deleted through AMFS.

-----------------
Checked in Files
-----------------
amfsctl.c : The user program to manage the ioctl
installamfs.sh : The shell script that installs the module 
 The module gets generated when making the kernel. This is additional script to unmount amfs if already mounted)
fs/amfs/MakeFile : Please run make inside fs/amfs folder to build the amfsctl.c ( user ioctl) program.
Note: ccflags-y := -std=gnu99 -Wno-declaration-after-statement has been added while compiling. This is just to reduce the scope of
variables declared. If this option is added, it compiles without any warnings.
-------------------------
Error conditions checked 
-------------------------

1. More than one mount option passed
   - EINVAL is returned
2. Mount option of pattdb not given
   - EINVAL is returned
3. Pattern file does not exist
   - EPERM ( operation not permitted on an non existent file)
4. Pattern file is a directory
   - EISDIR is returned
5. Pattern file does not have read permission
   - EPERM is returned
6. Pattern file size is zero
   - EINVAL is returned
7. Invalid ioctl number called
   - EINVAL is returned
8. Removal of a pattern that does not exist ( adding of pattern that is already present is not considered error. However while removing
we remove both of the duplicate entries)
   - EINVAL is returned
   Rationale for not considering addition of duplicate pattern an error:
   The file is marked bad even when one malware pattern is found. Even if a duplicate might be added, 
   that doesnt affect the functionality.Moreover , checking that a duplicate pattern is added among a huge list is 
   impractical as addition of malware patterns happen quite frequently.Deletion of the malware pattern happens
   rarely in real world scenario. Hence it is best to remove the duplicates during deletion than prevent duplicate addition.
   
9. ioctl argument is NULL
   - EINVAL is returned
10. Unable to write to pattern file after adding or removing a pattern
   - No error is returned if we know that the pattern is successfully added in memory. A retry is made later.
11. Reading of a malware file
   - ENOENT is returned
12. Writing data to a file that is malware.
   - EACCES is returned
13. Opening a file that is bad.
   - ENOENT is returned
14. Trying to rename a bad file.
    - EACCES is returned
15. Trying to remove the malware xattr on the bad file
    - EACCES is returned
16. Trying to set an attribute on bad file.
    - EACCES is returned

--------------------------------
Design Considerations and logic
--------------------------------

------------------
Pattern structure
------------------

* Every pattern is stored as a linked list. It consists of 2 components. 
The pattern itself and the length of the pattern.
The length of the pattern is required because we might want to scan past the NULL character until \n as NULL can be a valid malware character.
This prevents incorrect result that we might get when we do strlen.
struct my_pattern_list
{
    struct list_head list;
    char* pattern;
    int pattLen;
};

------------------------
super block private data
------------------------
* The private data in super block:
The pattern list head and the pattern file name is stored.
The pattern file name is stored as we may need to write to the file later when the patterns are added or removed.
struct amfs_sb_info {
    struct super_block *lower_sb;
    struct my_pattern_list* pattern_head; // the head of the pattern list
    char* patternFileName; // the pattern file name
};

-------------
* IOCTL's
-------------

Four operations are defined as part of ioctl:

#define AMFS_IOCADD _IOW(AMFS_MAGIC, 2 , char *) : To add a pattern pointed to by char* argument
#define AMFS_IOCREM _IOW(AMFS_MAGIC, 3 , char *) : To remove a pattern pointed to by char* argument
#define AMFS_IOCLISTLEN _IOR(AMFS_MAGIC, 4 , int*) : The buffer length to be allocated by the user to 
                                                     read all patterns is copied to a integer to user space
#define AMFS_IOCLIST _IOR(AMFS_MAGIC, 5 , char*) : The concatenation of all buffers followed by "\n" is written to user space.

For simplicity and according to the specification of the assignment the patterns in ioctls are considered to be strings.

-----------------------
The Extended attribute 
-----------------------
Whenever a malware pattern is detected in a file when performing read or write operations, the 
following attribute is set:

Extended Attribute Name: user.malfile
Extended Attribute Value: 1

-----------------------------------
silent attribute updation for write
-----------------------------------

If there is a malware pattern in the buffer during write, the attribute is set, but error is not returned
to the user. The subsequent operations on the file (read/write) fail.

-----------------------------------------
Hiding bad files while directory reading
-----------------------------------------

Most of the code here is inspired from ecryptfs/readdir. 
The gent dents super block is replaced by the dentry of the directory we are listing.
When the filldir is called, we get the directory dentry and use:
lookup_one_len to get the dentry corresponding to that name in that directory.
We check the attribute of the bad file and make the  filename null and the size as 0 while emitting.

struct amfs_getdents_callback {
    struct dir_context ctx;
    struct dir_context *caller;
    struct dentry *lower_dentry;//lower dentry helps to get the dir dentry we are in
    int filldir_called;
    int entries_written;
 };

-------------------------------------
Caching, Revalidation
-------------------------------------
The cached dentry value for a bad file during revalidation always returns 0, and hence it always gets the inode by lookup 
and not from the cache.

---------------------
lookup of a bad file
---------------------

The lookup of a bad file does not return an error. Though this can be done by modifying code during lookup/getattribute,
it was preventing the deletion of the file. The "rm <badfile>" was returning -ENOENT. Hence the lookup has not been modified.
The deletion of a bad file takes higher precedence than the lookup of a bad file succeeding. However note that the 
directory ls does not list bad files. 

----------------------------------------
Preventing Extended Attribute Removal
----------------------------------------

If the attribute value is user.malfile, the attribute is never removed, even by root.

----------------------------------------------------------
Renaming of bad files/ setting up of additional attributes
----------------------------------------------------------
The rename operation on bad files is prevented and user cannnot set any attributes on these files.


**************************************
References
**************************************
http://lxr.free-electrons.com/source/fs/ecryptfs/file.c?v=3.8
http://stackoverflow.com/questions/19647356/linux-kernel-linked-list
http://stackoverflow.com/questions/15332381/linux-list-h-how-to-safely-remove-items-from-the-list
https://isis.poly.edu/kulesh/stuff/src/klist/
wrapfs and union fs sources


About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages