2015MIS023
2015MIS023
2015MIS023
P. M. Wanigasinghe
University of Colombo School of Computing
2018
Declaration
The
thesis
is
my
original
work
and
has
not
been
submitted
previously
for
a
degree
at
this
or
any
other
university/institute.
To
the
best
of
my
knowledge
it
does
not
contain
any
material
published
or
written
by
another
person,
except
as
acknowledged
in
the
text.
Students Name:
_____________________
Signature: Date:
This is to certify that this thesis is based on the work of
Mr./Ms.
under
my
supervision.
The
thesis
has
been
prepared
according
to
the
format
stipulated
and
is
of
acceptable
standard.
Certified by:
Supervisor Name:
_____________________
Signature:
Date:
iv
Abstract
In Linux, traditional file system uses READ, WRITE and EXECUTE permissions
over individual users and groups in order to control the file access and file operations.
Although this has been the de-facto methodology, it has some disadvantages when it
comes to highly secure and sensitive environments like banks and military. There is no
straight forward way of defining permissions in operational aspect.
The goal of this project is to increase the granularity levels of defining permissions of
the Linux file system going beyond traditional read, write and execute permissions. It
consists of mainly two modules. In meta header module, authorized user can define what,
who and how things are accessible related to files. He can define on what operations needs
to restrict on what devices, locations and domains. The other module is responsible for
handling the file operations and restrict according to the defined permissions.
Evaluation carried out on security, performance and usability aspects. There may have
slight performance impact but it’s negligible compared to the requirements of security.
Further, this implementation can extends go beyond ext4 and apply into main kernel
development.
v
Acknowledgement
My special thank goes to UCSC for providing me with such an opportunity to improve
my academic knowledge and implementation skills and for all the lecturers in the panel
for sharing their invaluable time and knowledge to push us towards the degree. Also I
would like to thank the technical, non-academic staff in UCSC for all the help given to
us throughout the research period and prior.
I would also like to give my thanks to various researchers and online community
contributors which I referred and gathered knowledge throughout the project.
Last but not least words cannot express the gratitude I have for my parents, wife and
her parents for their support kindness and understanding throughout this whole time.
vi
Contents
Abstract iv
Acknowledgement v
List of Figures xi
Abbreviations xiv
1 Introduction 1
1.3 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2 Literature review 7
2.1.3 Ext4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.1.4 Inode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.4.1 State . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.4.2 Identifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.4.3 Links . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.5.1 Throughput . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.6.1 AD RMS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
3 Design 18
3.2.2 Inotify . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
4 Implementation 28
4.3.4 Validation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
4.3.5 Notification . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
5 Evaluation 40
5.3 Throughput . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
5.6 Usability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
6 Conclusion 53
6.1 Procedure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
Bibliography 55
Appendices 57
A.3 Configure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
C.2 module init() macro by init attribute - To load the kernel module . . . . 66
C.3 module exit() macro by exit attribute - To unload the kernel module . . . 66
C.6 Compilation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
List of Figures
3.4 Interceptor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
List of Tables
Abbreviations
CHAPTER 1
Introduction
One of the main weapons in modern economical warfare is information about competi-
tors, their offerings, finances, sales and marketing strategies. To fight in the market and
to grab the market share, competitive intelligence is used. That is legally gathered infor-
mation by closely monitoring all public channels, associated with competitors, networking
with industry insiders and analyzing latest trends.
However, since those are not enough. Many turn to much shadier tactics in order to
gain advantage over competition. Industrial espionage is much more common. [1]
The main goal of industrial espionage is to get a hold of protected confidential infor-
mation belonging to competitors. [2] Usual targets of such actions are:
Trade secrets Generally means protected information about existing products or prod-
ucts in development. This is one of the most popular targets of industrial espionage.
This information may help rival companies to increase competitiveness of their prod-
ucts or even bring a similar product to the market faster than original.
Client information Private data of clients, including their financial information, can be
used to steal business, or can be leaked to damage the reputation of the company.
Financial information Financial information of the company can be used to offer better
deals to clients and partners, win bids, or even make a better offer to valuable
employees.
Marketing information This will allow competitors to prepare a timely answer for your
marketing campaign, which, in turn, may render it completely ineffective.
Malicious insiders are one of the main key factors for industrial espionage. Competi-
tors frequently place their employees who will act as a regular employees, while secretly
gathering intelligence for their actual employer. They can approach trusted employees
with privileged access to trade secrets and other valuable information. [3]
2
So the insider threats has been considered as a main security threat in last year 2017.
Lots of data breaches, information disclosures, IP theft reported last few years. Its very
difficult to handle insider threats.
In order to deal with above situations, there is a need of defining security permissions
in to another level, especially on files. File systems in Linux, and all Unix like file systems,
supports file security based on RWE on top of users and groups. By it’s design, permissions
can define based on users aspect. But defining permissions on operational aspect, keeping
existing permission structure as it is, can drastically increase the granularity of defining
permissions.
Providing file system security in operational aspect in a more granular way is a lacking
feature in Linux. All most all file systems security features focusing on user perspective
rather than operational perspective. Implementing operational level permissions increase
the granularity of defining permissions and the file owner has more control over the file.
There are number of questions asked in Linux forums and other forums regarding increas-
ing granularity levels. But there’s no direct way of providing this. [4] [5] [6]
In NTFS file system in Windows, Microsoft Office 2007 system has granular permission
defining system called IRM (Information Rights Management) [7] using AD. It allows
individuals and administrators to specify access permissions to documents, and it helps to
prevent sensitive information being printed, forwarded or copied by unauthorized people.
Also there are third party applications like Safeguard PDF security by Locklizard, which
follows the same concept to protect PDF files. But similar feature is not available in
Linux , in OS level directly.
3
Standard Linux file system’s security provides permission levels, READ (R), WRITE
(W) and EXECUTE (E).
And each file (and directory) has three user based permission groups:
Owner Apply only to the owner of the file, they will not impact the actions of other
users.
Group Apply only to the group that has been assigned to the file or directory, they will
not effect the actions of other users.
Combination of file permission levels and permission groups became a standard and
provides control to the owner (or authorized user) to maintain a security of a file. Since
the design of Linux system focused primarily on providing generalized solution, go beyond
this combination is not supported by default.
Apart from the standard file permissions, a user can use ACL [9] or SELinux [10] like
approaches in order to increase security. But those are focuses on user perspective rather
than operations perspective which describes in section 3.1.
For example, if file owner wants to restrict a file being transferred/copied via USB
drive, either he wants to block USB drives for the entire system or he wants to restrict
write permission for a particular user or group. There’s no granularity level in between
4
to specify permissions such as, restrict copying file into USB drives for only a particular
user.
Another example would be, if user wants to restrict transferring file via SCP to certain
IP addresses, he needs to have another alternative solution to restrict those IP addresses.
Doing above approaches not only affect to that particular file only, but also it applies to
the entire file system.
1.3 Motivation
Motivation of this project is to increase the security of the Linux file system in OS
level itself rather than using third party software. This project extends the granularity
levels of defining permissions of a file. It goes beyond RWE permissions and users will be
able to specify what actions and what limitations will be provided with a file itself.
In this section objectives of this project is explained in detail. One of the most
important parts of this project is to do a comprehensive study of existing work done.
• Build a file system that provides more granularity, on which user can define permis-
sions on his own choice according to a pre-defined structure.
In current Linux, user will be able to provide permissions for file or directory using
existing READ, WRITE, EXECUTE and based on USER, GROUP and ALL, But
using this implementation, user will be able to define permissions in more granular
way in operations perspective. He will be able to control more by defining what
operations need to restrict based on what parameters.
• File will have extra security meta header which defines the parameters.
To achieve above, user will be able to define actions and related parameters in a
friendly manner. System will provide pre-defined structure of defining actions and
parameters.
• Build an interceptor module, which intercepts each operation and check against
permissions define in the header.
To validate defined actions and parameters, there will be an interceptor module,
where it centrally operates and check executing operations against them.
5
• This implementation applies only to files. But it can further extends to directory
level. Since Linux treats everything as a file, such expansion is not hard.
• Further this implementation can extends when the file is transferred, the security
meta header should transfer along with file with change of ownership. Since the meta
header associated with inode, it will automatically transfer when file get transferred.
But new namespace, which introduced in this project needs to be in the new system
in order to handle the permissions.
• In order to prove the concept, cp, scp and lpr commands will use in this project.
As a future work, this implementation can extends easily in order to work all the
file related operations which uses ’open’ system call internally.
• This implementation only focuses on Linux kernel 4.4 and this will suggest to the
kernel development to bind this into a core kernel to avoid conflicts in system up-
grades.
• This only applicable for ext4 file system and this can be further extends to other
file systems as well.
• This implementation works on the kernel versions greater than 2.6 kernels and this
should be changed in order to apply it for older kernels. This is because mainly due
to the more restrictions introduced to the system table after kernel version 2.6.
• This implementation is limited to file operations which are called ’open’ system call
internally.
6
Chapter 2 provides a literature review on how Linux and Linux file systems works. It
also includes systems that tries to resolve the same issue and how and what level
they have achieved it.
Chapter 3 provides the design of the system. It describes about the two main modules,
Meta Header module and Interceptor module, and the design approach.
Chapter 5 provides a critical evaluation of the research by performing various tests and
obtaining and plotting those results in to graphs.
Chapter 6 provides a conclusion to this research by providing the motivation, what was
done in the research, challenges faced, future work and status of the final outcome
7
CHAPTER 2
Literature review
This chapter will discuss about the current Linux file system, underline structures,
security and related OS features. Further this will discuss about similar approaches.
Without a file system, information gathered and stored in a storage medium like hard
drive, would be a one large block of data. So there is no way to tell where and how one
piece of information start and stop. Therefore in computers, a file system is used to define
and control how data is stored and retrieved. Each group of data is called ’file’ and it
has attributes like name, id to identify and isolate that particular group of information
separately from others. File system’s responsibility is to manage the structure and logic
rules used by the file. [11]
A file system is used to control how data is stored and retrieved. Without a file system,
information placed in a storage medium would be meaningless. By separating the data
into pieces and giving each piece a name, the information is easily isolated and identified.
[12]
Individual drive partitions can be setup using one of the many different available file
systems. Each has its own advantages, disadvantages. Some of the file systems supported
by Linux are, ext, ext2, ext3, ext4, hpfs, iso9660, JFS, minix, msdos, ncpfs nfs, ntfs, proc,
Reiserfs, smb, sysv, umsdos, vfat, XFS, xiafs. [13]
8
To switch or use one file system, you need to insert corresponding module or recompile
the kernel and mount it.
Below a short description of the available file systems in the Linux kernel.
ext is an elaborate extension of the minix file system. It has been completely superseded
by the second version of the extended file system (ext2) and has been removed from
the kernel (in 2.1.21).
ext2 is the high performance disk file system used by Linux for fixed disks as well as
removable media. The second extended file system was designed as an extension of
the extended file system (ext).
ext3 is a journaling version of the ext2 file system. It is easy to switch back and forth
between ext2 and ext3.
ext4 is a set of upgrades to ext3 including substantial performance and reliability en-
hancements, plus large increases in volume, file, and directory size limits.
hpfs is the High Performance File system, used in OS/2. This file system is read-only
under Linux due to the lack of available documentation.
iso9660 is a CD-ROM file system type conforming to the ISO 9660 standard.
High Sierra Linux supports High Sierra, the precursor to the ISO 9660 standard for
CD-ROM file systems. It is automatically recognized within the iso9660 file system
support under Linux.
Rock Ridge Linux also supports the System Use Sharing Protocol records specified by
the Rock Ridge Interchange Protocol.
9
JFS is a journaling file system, developed by IBM, that was integrated into Linux in
kernel 2.4.24.
For convenience, the Linux file system is usually thought of in a tree structure. On
a standard Linux system you will find the layout generally follows the scheme presented
below.
2.1.3 Ext4
Ext 4 has more improvements compared to Ext3 file system. It has improved design,
better performance, reliability, capacity and features. Most Linux distributions use Ext4.
Ext3 was mostly about adding journaling to Ext2, but Ext4 modifies important data
structures of the file system such as the ones destined to store the file data. [14]
Metadata and journal checksums were added to improve reliability. To meet various
mission-critical requirements, the filesystem timestamps were improved with the addition
of intervals down to nanoseconds.
In EXT4, data allocation was changed from fixed blocks to extents (described by
its starting and ending place on the hard drive). So it’s possible to describe very long,
physically contiguous files in a single inode pointer entry, which can significantly reduce
the number of pointers required to describe the location of all the data in larger files.
10
EXT4 reduces fragmentation by scattering newly created files across the disk so that
they are not bunched up in one location at the beginning of the disk.
Aside from the actual location of the data on the disk, EXT4 uses functional strategies,
such as delayed allocation, to allow the filesystem to collect all the data being written to
the disk before allocating space to it. This can improve the likelihood that the data space
will be contiguous.
2.1.4 Inode
A data structure is a way of storing data so that it can be used efficiently. Different
types of data structures are suited to different types of applications, and some are highly
specialized for specific types of tasks.
The Linux security model is based on the one used on UNIX systems which is quite
robust. On a Linux system, every file is owned by a user and a group user. There is also
a third category of users, those that are not the user owner and don’t belong to the group
owning the file. For each category of users, read, write and execute permissions can be
granted or denied. [15]
ls -l displays file permissions for these three user categories; they are indicated by
the nine characters that follow the first character, which is the file type indicator at the
beginning of the file properties line. First three characters in this series of nine display
access rights for the actual user that owns the file. The next three are for the group owner
of the file, the last three for other users. The permissions are always in the same order:
read, write, execute for the user, the group and the others.
Extended attributes are additional meta data for a file, which are not interpreted by
the file system. In Linux, the ext2, ext3, ext4, JFS, Squashfs, Yaffs2, ReiserFS, XFS,
Btrfs, OrangeFS, etc file systems support extended attributes. It consists of name and
associated data. Name should be a null terminated string, prefixed by namespace. [16]
user
trusted
The Linux kernel allows extended attribute to have names of up to 255 bytes and
values of up to 64KiB, as do XFS and ReiserFS, but ext2/3/4 and btrfs impose much
smaller limits, requiring all the attributes (names and values) of one file to fit in one
”filesystem block” (usually 4 KiB). [17]
Extended attributes can be accessed and modified using the arrt, getfattr and setfattr
commands from the attr package on most distributions.
Processes carry out tasks within the operating system. It is a dynamic entity, con-
stantly changing as the machine code instructions are executed by the processor. As well
as the program’s instructions and data, the process also includes the program counter and
12
all of the CPU’s registers as well as the process stacks containing temporary data such as
routine parameters, return addresses and saved variables. [18]
The current executing program, or process, includes all of the current activity in the
microprocessor. Linux is a multiprocessing operating system. Processes are separate tasks
each with their own rights and responsibilities. If one process crashes it will not cause
another process in the system to crash. Each individual process runs in its own virtual
address space and is not capable of interacting with another process except through secure,
kernel managed mechanisms.
During the lifetime of a process it will use many system resources. It will use the CPUs
in the system to run its instructions and the system’s physical memory to hold it and
its data. It will open and use files within the file systems and may directly or indirectly
use the physical devices in the system. So that Linux can manage the processes in the
system, each process is represented by a task struct data structure. The task vector is an
array of pointers to every task struct data structure in the system. To make it easy to
find, the current, running, process is pointed to by the current pointer.
As well as the normal type of process, Linux supports real time processes. These
processes have to react very quickly to external events and they are treated differently
from normal user processes by the scheduler. Although the task struct data structure is
quite large and complex, but its fields can be divided into a number of functional areas.
2.4.1 State
Running The process is either running (it is the current process in the system) or it is
ready to run (it is waiting to be assigned to one of the system’s CPUs).
Waiting The process is waiting for an event or for a resource. Linux differentiates be-
tween two types of waiting process; interruptible and uninterruptible. Interruptible
waiting processes can be interrupted by signals whereas uninterruptible waiting pro-
cesses are waiting directly on hardware conditions and cannot be interrupted under
any circumstances.
Stopped The process has been stopped, usually by receiving a signal. A process that is
being debugged can be in a stopped state.
Zombie This is a halted process which, for some reason, still has a task struct data
structure in the task vector. It is what it sounds like, a dead process.
2.4.2 Identifiers
Every process in the system has a process identifier. The process identifier is not an
index into the task vector, it is simply a number. Each process also has User and group
13
identifiers, these are used to control this processes access to the files and devices in the
system,
2.4.3 Links
Processes can open and close files as they wish and the processes task struct contains
pointers to descriptors for each open file as well as pointers to two VFS inodes. Each
VFS inode uniquely describes a file or directory within a file system and also provides a
uniform interface to the underlying file systems.
2.5.1 Throughput
Linux has also got set of utilities to monitor CPU utilization. With these commands
you can find out total CPU utilization, individual CPU utilization, your system’s average
CPU utilization since the last reboot, determine which process is eating up your CPU(s)
etc.
14
2.6.1 AD RMS
At high level, you can use organization’s security strategy and persistent usage policies
to protect information, no matter where it is moved by using Active Directory Rights
Management Services (AD RMS) and the AD RMS client.
• Windows Server 2008 running the Active Directory Rights Management Services
• (AD RMS) server role that handles certificates and licensing a database server
• AD RMS client. (included as part of the Windows 7 and Windows Vista operating
systems)
Safeguard sensitive information Users can define who can open, modify, print, for-
ward, or take other actions with the information. Applications such as word pro-
cessors, e-mail clients, and line-of-business applications can be AD RMS-enabled to
help safeguard sensitive information. Organizations can create custom usage pol-
icy templates such as ”confidential - read only” that can be applied directly to the
information.
Flexible and customize technology Independent software vendors (ISVs) and devel-
opers can AD RMS-enable any application or enable other servers, such as content
management systems or portal servers running on Windows or other operating sys-
tems, to work with AD RMS to help safeguard sensitive information. ISVs are
enabled to integrate information protection into server-based solutions such as doc-
ument and records management, e-mail gateways and archival systems, automated
workflows, and content inspection.
15
• individual users
• a group of users
• specific devices
Safeguard PDF Security can be used to protect PDF files to individual users, all the
users or group of users (for example, only the Sales department given access to sales
reports). As their documents says,
All users Selecting this option grants document access to all users you have added to
your Safeguard administration system.
Selected users Selecting this option grants document access to selected users. You select
the users you want to grant document access to in the Safeguard administration
system.
Users who have been given access to a publication (group of protected documents)
Selecting this option grants document access to all users who have been granted
access to a specific publication. Users are granted access to publications in the
Safeguard administration system.
Examples for restricting for domains are place of work or third party site etc. Re-
stricting document access to a specific location ensures documents cannot be used outside
that location and therefore minimizes confidential documents being compromised. This is
especially useful if your workforce uses laptops or other mobile devices to access protected
documents.
16
In the Settings Tab in the Safeguard Admin system and select the ’Restrict IP’ link.
Enter an IP address or range of IP addresses you want to restrict document access to.
On each user’s account you can enter an IP address or a range of addresses from which a
user can register their license from and also use a secure PDF document.
If a user tries registering their license from an IP address outside this range then then
they will not be able to register.
If a user registers their license on say a laptop from an approved IP address range (for
example an office location) and then takes their laptop home, they will not be able to
view your secure documents as long as the document controls are set to check with the
administration server (verify document access = each time the document is opened).
Safeguard PDF security can use to restrict access on some devices, such as devices
with Windows OS or mobile devices. You can also restrict printing to just Windows or
Macintosh devices. You can also stop documents from being accessed in thin client and
virtual environments. This prevents multiple users accessing documents from a single
system all at the same time.
Protected PDF files are locked to specific devices and cannot be moved to non-
authorized devices – if a user copies or sends a protected document to a non-authorized
device then the document will not open.
17
Locklizard’s Safeguard PDF security is a application level system and designed specif-
ically for PDF files. But this implementation works directly in a OS system kernel space
providing more security by the design itself.
Also this implementation not limited to PDF files, Since it directly deals with inode,
this applies to all kind of files and easily enhance to directories as well.
CHAPTER 3
Design
In this chapter, first two sections will discussed the design about main modules, meta
header module and interceptor module in this project. Then the subsequent sections some
approaches and design concerns will be discussed.
Traditional Linux file permissions, by design, are based on user perspective. User can
define file permissions (Read, Write and Execute) on top of owner, user group and all
users. So the defined permissions acts on user or group of users, allowing or restricting on
users point of view. For an example, file owner has Read, Write and Execute permissions
while restricting some group only to Read.
Function call hooking refers to a range of techniques used to intercept calls to pre-
existing functions and wrap around them to modify the function’s behavior at runtime.
[19]
function hooking in linux using the dynamic loader API, which allows us to dynam-
ically load and execute calls from shared libraries on the system at runtime, and allows
us to wrap around existing functions by making use of the LD PRELOAD environment
variable.
3.2.2 Inotify
The inotify API provides a mechanism for monitoring file system events. Inotify can be
used to monitor individual files, or to monitor directories. When a directory is monitored,
inotify will return events for the directory itself, and for files inside the directory. [[20]
Inotify was created by John McCutchan, and it was merged into the Linux kernel in
kernel version 2.6.13, released on August 29, 2005. later kernel versions included further
improvements. The required library interfaces were added into the GNU C library (glibc)
in its version 2.4, released in March 2006, while the support for inotify was completed in
glibc version 2.5, released in September 2006.
One major use is to permits re indexing of changed files without scanning the filesystem
for changes every few minutes, which would be very inefficient. Inotify can also be used
to automatically update directory views, reload configuration files, log changes, backup,
synchronize, and upload.
If we want to intercept a system call, we have to write our own fake system call, then
make the kernel call our fake function instead of the original call. At the end of our fake
call, we can invoke the original call. In order to do this, we must manipulate the system call
20
The Linux kernel maintains a table of pointers that reference various functions made
available to user space as a way of invoking privileged kernel functionality from unpriv-
ileged user space applications. These functions are collectively known as system calls.
[21]
Any legitimate software looking to hook kernel space functions should first consider
using existing infrastructure designed for such uses like the Linux kernel tracepoints frame-
work or the Linux security module framework.
Kernel modules are pieces of code that can be loaded and unloaded into the kernel
upon demand. They extend the functionality of the kernel without the need to reboot
the system. A module can be configured as built-in or loadable. To dynamically load or
remove a module, it has to be configured as a loadable module in the kernel configuration.
21
This system designed to have mainly two modules. Both of the modules designed to
run within the Linux kernel in kernel space.
Meta header module defines the permissions. When file owner creates a file, along
with the file, system will creates a separate security meta header, in which file owner can
specify the permissions in a defined way.
In this way, file owner has more control over defining file permissions in operational
aspect. He can specify the operation foremost and then followed by defining to whoem
this applies, what is the type and related value. More description and examples available
in implementation chapter
22
The primary objective of the interceptor module is to intercept the current running
process and validate against defined permissions. This module will implement as a cen-
tralized module where every file system operation go through it.
It will check whether the current running process is matched against the defined oper-
ations in the security meta header’s access controllers. If it does, then it checks whether
the performed action is allowed or not. If it’s not allowed, the module will generate a
error message and notify the user.
This module will implement as kernel module. LD PRELOAD has not used because
it will run in user space and has security issues. Also this module cannot implement as
inotify since, inotify works after inode get changed. So the pre-valiadtion cannot be done.
23
Interceptor module contains five sub modules. Process interceptor sub module inter-
cepts the file system operations (open(), read(), write()) and though that it will take the
current running process. After obtaining current process, file reader sub module will ex-
tract files attached to the current running process. Then the format validator sub module
validates the permission format defined by the user using meta header module. If the for-
mat and values are correct, Permission validator sub module will take care of validating
permissions against user entered command. Notification sub module is responsible for
format the output according the required output. (whether it’s terminal or GUI).
24
Full activity flow of the design shows below. When file owner creates a file, meta header
module will automatically creates a meta header. Then file owner can define standard
permissions and extended permissions as per the requirement. Meta header module will
save defined permissions in file’s inode.
When user tries to access the file (execute operation against that file), interceptor
module will intercept the process and read defined permissions on that file. Then it
validates permissions and decide whether to allow or notify restricting the operation.
One of the limitation of this design is, this will combine OS layers. For example,
defined parameters can contain IP addresses, devices which will be used to restrict file
operations. But defining network related features in a file (application level) can be
considered as a design concern.
There are some application level programs who allowed to define such configurations
in application level. For example, application server like Apache Tomcat allows to de-
fine/restrict certain IP addresses to access the server.
To overcome this kind of design limitations, there can be a separate policy module,
which resides outside the system, can contain permissions defined as policies. This is a
enhancement to this implementation and it will not cover in this scope.
CHAPTER 4
Implementation
As described in the previous chapter, under design of the meta header module, this
module is responsible of defining the file related permissions in a more granular way.
Extended attributes feature has been used to define these permissions and a new extended
attribute called FGP has been introduced.
To implement file system meta header, extended version of extended attributes has
been used. Currently there are four namespaces available in standard extended attributes
in Linux.
• user
• trusted
• security
• system
New namespace have introduced (fgp) in order to define permissions in this module.
Therefore user can specify permissions in a simplified text based manner. Namespace is
fgp (abbreviate for fine grained permissions ). user can define as
fgp is the namespace. This should followed by the string, which describes the permis-
sion.
<U/G: value> Specify the user or group needs to restricts from. U- User, G- Group
followed by value. (* for all)
User can use standard extended attributes set and get functions, setfattrt() and get-
fattr(). And user can define any number of records for a file within the file block size.
(for ext4, must fit in a single filesystem block (1024, 2048 or 4096 bytes). If them are
overridden, last defined entry has taken as a valid one.
30
As described in design, there are five sub modules in the interceptor module. Among
those, process interceptor module is the main sub module and intercepting the current
running file operation is the responsibility of it.
As described in the literature survey, three intercepting methods were analyzed and
due to the applicability, process interception via system call interception has been selected.
Intercept system call described in detail in Appendix D. Since Linux 2.6 > kernels not
exposed system table, there are couple of ways to implement this.
To start brute forcing, system utsname is selected as a staring address since it’s known
that system utsname structure exists before the system call table. Therefore, iteration
starts for system ustname location and iterates advancing byte each time. On the itera-
tion, function checks whether the current location is equal to sys read, since the sys read
is available to LKM. So, if it is equal to sys read, current location contains the system
table.
while ( i )
{
i f ( s y s t a b l e [ NR read ] == ( u n s i g n e d l o n g )
sys read )
{
s y s c a l l t a b l e=s y s t a b l e ;
f l a g =1;
break ;
}
i −−;
s y s t a b l e ++;
If the kernel’s System.map file is available, you can use it to obtain the location of
sys call table, and this location can be hard coded into the LKM
The module’s source code can hardcodes the address to obtain sys call table:
∗ ( l o n g ∗ )&s y s c a l l t a b l e =0x c 0 4 4 f d 0 0 ;
To find and load system table address dynamically, following approach has been used.
To get the kernel version, first store the user space perspective of the file system and
read into kernel space.
mm segment t o l d f s ;
oldfs = get fs () ;
s e t f s (KERNEL DS) ;
Open, read and extract the version file in the /proc virtual file system
p r o c v e r s i o n = f i l p o p e n (PROC V, O RDONLY, 0 ) ;
i f ( IS ERR ( p r o c v e r s i o n ) | | ( p r o c v e r s i o n == NULL) ) {
r e t u r n NULL;
}
k e r n e l v e r s i o n = s t r s e p (&buf , ” ” ) ;
Using the kernel version found above, here we have define the file path for /boot/sys-
tem.map
/∗
∗ C o n s t r u c t our / boot / System . map−<v e r s i o n > f i l e name
∗/
s t r n c p y ( f i l e n a m e , BOOT PATH, s t r l e n (BOOT PATH) ) ;
strncat ( filename , kern ver , s t r l e n ( kern ver ) ) ;
33
/∗
∗ Open t h e System . map f i l e f o r r e a d i n g
∗/
f = f i l p o p e n ( f i l e n a m e , O RDONLY, 0 ) ;
i f ( IS ERR ( f ) | | ( f == NULL) ) {
p r i n t k (KERN EMERG ” E r r o r opening System . map−<v e r s i o n >
f i l e : %s \n” , f i l e n a m e ) ;
r e t u r n −1;
}
/∗
∗ Read one byte a t a time from t h e f i l e u n t i l we e i t h e r
max out
∗ out our b u f f e r o r r ead an e n t i r e l i n e .
∗/
w h i l e ( v f s r e a d ( f , system map entry + i , 1 , &f −>f p o s ) ==
1) {
/∗
∗ I f we ’ ve read an e n t i r e l i n e o r maxed out our b u f f e r
,
∗ check t o s e e i f we ’ ve j u s t read th e s y s c a l l t a b l e
entry .
∗/
i f ( system map entry [ i ] == ’ \n ’ | | i ==
MAX VERSION LEN ) {
// Reset th e ” column ”/” c h a r a c t e r ” c o u n t e r f o r th e
row
i = 0;
34
kfree ( filename ) ;
r e t u r n −1;
}
s t r n c p y ( s y s s t r i n g , s t r s e p (&
s y s t e m m a p e n t r y p t r , ” ” ) , MAX VERSION LEN)
;
// s y s c a l l t a b l e = ( u n s i g n e d l o n g l o n g ∗ )
k s t r t o l l ( s y s s t r i n g , NULL, 1 6) ;
// s y s c a l l t a b l e = k m a l l o c ( s i z e o f ( u n s i g n e d l o n g
∗ ) , GFP KERNEL) ;
// s y s c a l l t a b l e = k m a l l o c ( s i z e o f ( s y s c a l l t a b l e )
, GFP KERNEL) ;
k s t r t o u l ( s y s s t r i n g , 1 6 , &s y s c a l l t a b l e ) ;
p r i n t k (KERN EMERG ” s y s c a l l t a b l e r e t r i e v e d \n” ) ;
break ;
}
i ++;
}
35
Then ”nameidata”, which is a data structure used in Linux kernels, has been used
access the reference to a given file.
The nameidata keeps track of the last resolved path component with dentry and mnt
fields. Initially, they are assigned with starting directory. The core lookup operation is
performed by link path walk(name, nd), where name is the path name, nd is the address
of the nameidata structure.
1. Consider next component to be resolved; from its name, compute 32-bit hash value
to be used when looking in the dentry cache hash table.
2. Set LOOKUP CONTINUE flags in nd-¿flags to denote that there are more com-
ponents to be analyzed.
3. Invoke do lookup() to search dentry object for the path component. If found
(skip revalidation), then this path component has been resolved, and move on. If not
found, then invoke real lookup(). At the end of the cycle, the dentry and mnt field of
local dentry variable next will point to, respectively, the dentry object and the mounted
filesystem object of the path component we attempt to resolve.
4. If the above do lookup() reaches the last component of the pathname, and assuming
that it is not a symbolic link as assumed at the beginning, then this is our destination.
All we need to do is to store the dentry object and mnt info in the passed nameidata nd
and return without error:
36
a s m l i n k a g e i n t n e w o p e n f u n c t i o n ( c o n s t char u s e r ∗ filename ,
int
f l a g s , i n t mode )
{
int error ;
s t r u c t nameidata nd , n d t ;
s t r u c t i n o d e ∗ inode , ∗ i n o d e t ;
mm segment t f s ;
e r r o r=u s e r p a t h w a l k ( f i l e n a m e ,&nd ) ;
i f (! error )
{
i n o d e=nd . dentry−>d i n o d e ;
/∗ Have t o do t h i s b e f o r e c a l l i n g u s e r p a t h w a l k
( )
from k e r n e l s p a c e : ∗/
f s=g e t f s ( ) ;
s e t f s ( get ds ( ) ) ;
set fs ( fs ) ;
i f (! error )
{
i n o d e t=n d t . dentry−>d i n o d e ;
i f ( i n o d e==i n o d e t )
r e t u r n −EACCES;
}
}
r e t u r n o r i g i n a l s y s o p e n ( f i l e n a m e , f l a g s , mode ) ;
}
When you try to do the sys open() call usually returns the error -EFAULT. Kernel
expects the pointer passed to the sys open() function call to be coming from user space.
So, it makes a check of the pointer to verify it is in the proper address space in order to
try to convert it to a kernel pointer that the rest of the kernel can use. So, when we are
trying to pass a kernel pointer to the function, the error -EFAULT occurs. To handle this
address space mismatch, uses the functions get fs() and set fs(). These functions modify
the current process address.
37
s e t f s (KERNEL DS) ;
The only two valid options for the set fs() function are KERNEL DS and USER DS,
roughly standing for kernel data segment and user data segment, respectively.
To determine what the current address limits are before modifying them, call the
get fs() function. Then, when the kernel module is done abusing the kernel API, it can
restore the proper address limits.
f s=g e t f s ( ) ;
s e t f s ( get ds ( ) ) ;
Extended attributes are name:value pairs associated with inodes. They are extensions
to the normal attributes which are associated with all inodes in the system. A complete
overview of extended attributes concepts can be found in literature review.
getxattr() retrieves the value of the extended attribute identified by name and asso-
ciated with the given path in the filesystem. The attribute value is placed in the buffer
pointed to by value; size specifies the size of that buffer. The return value of the call is
the number of bytes placed in value.
lgetxattr() is identical to getxattr(), except in the case of a symbolic link, where the
link itself is interrogated, not the file that it refers to.
fgetxattr() is identical to getxattr(), only the open file referred to by fd (as returned
by open(2)) is interrogated in place of path.
r e t = inode−>i o p −>g e t x a t t r ( g e t d e n t r y ( f i l e ) ,
#i f LINUX VERSION CODE >= KERNEL VERSION( 4 , 6 , 0 )
inode ,
#e n d i f
” s e c u r i t y . t pe ” , c o n t e x t , MAX FILE LEN) ;
#e n d i f
38
4.3.4 Validation
After retrieving the meta header parameters, the validation module uses regular ex-
pression to break and divide the parameters. Then it validate parameter values against
executed operation, to check whether it’s allowed or not.
As per the current implementation, authorized person can define any number of per-
missions for a operation. If there are more than one definitions, this module validate
combning all the permissions defined.
When executing copy operation against this file, first, second and forth permissions
will filter out first and considered combining all these three to restrict file copy for perera
to sdb1 and to directory /home/desktop while restricting sunil to copy also into sda1.
struct t a s k s t r u c t ∗ task ;
f o r e a c h p r o c e s s ( task )
p r i n f o ( ”%s [%d ] \ n” , task −>comm, task −>p id ) ;
To get a list of processes within the kernel (or within a module), the processes
are kept internally as a doubly linked list that starts with the init process (symbol
initt askinthekernel).M acrosdef inedininclude/linux/sched.hcanusetogetprocesses.
39
4.3.5 Notification
printk() is a logging mechanism for the kernel, and is used to log information or
give warnings. Therefore, each printk() statement comes with a priority, which is the
<1> and KERN ALERT. There are 8 priorities and the kernel has macros for them,
so you don’t have to use cryptic numbers, and you can view them (and their mean-
ings) in linux/kernel.h. If you don’t specify a priority level, the default priority, DE-
FAULT MESSAGE LOGLEVEL, will be used.
If the priority is less than int console loglevel, the message is printed on your current
terminal. If both syslogd and klogd are running, then the message will also get appended
to /var/log/messages, whether it got printed to the console or not. We use a high priority,
like KERN ALERT, to make sure the printk() messages get printed to your console rather
than just logged to your logfile.
40
CHAPTER 5
Evaluation
This chapter will discuss about the evaluation methods and techniques used. Three
types of evaluation methods have been used, performance evaluation, usability evaluation
and security evaluation.
To evaluate this implementation, following are the main performance criteria consid-
ered.
• Total time taken for selected file operations after the implementation
• Total time to perform file operation compared to time taken for the same operation
before this implementation.
• CPU utilization when performing file operations compared to same operation done
in previous without this feature
Apart from the above performance criteria, following additional points were also
investigated.
• Identify ten different use cases where this implementation will be able to use and
carryout success and fail case analysis.
• Failures
For testing purposes a machine with a 2.50GHz Intel Dual Core CPU with 2 cores
and 4GB of memory, is used. HDD is SATA 1 with speed of 1.544 GB/s. Linux 4.06.0-
43-generic version with 64bit architecture operating system is used. In this experiment
evaluation, disk I/O considered to be constant and the main intention was to compare
performance before and after the implementation.
5.3 Throughput
This section discusses various throughput information gathered during the evaluation.
Static time capture methods has been used to capture the data and graphs prepared
manually according to the results.
In order to get the data to this test, following sample Shell script have been used.
Generally it takes time to complete the operation in average of ten times. Sample results
output included after the script.
42
#! / b i n / bash
# Throughput when increasing the meta header p a r a m e t e r s
START=0
STOP=0
DIFF=0
COUNT=0
f o r number i n { 1 . . 1 0 }
do
START=$ ( ( $ ( da te +%s%N) /1000000) )
cp 100MB. z i p c o p i e s /
STOP=$ ( ( $ ( d ate +%s%N) /1000000) )
DIFF=$ ( ( $STOP−$START) )
COUNT=$ ( ($COUNT+$DIFF ) )
done
This graph describes how the three operations (CP,SCP and LPR) works when in-
creasing the number of parameters defined in the meta header, when the file size in fixed
for 100MB. As graph shows, time increases gradually when increasing the parameters.
This is mainly because, here it concerns only taking the last defined parameter for that
particular operation. But it will be increase when this enhances to take and combine all
the parameters defined for a particular operation.
Above graph shows how much time it takes after implementing this feature compared
to the normal file copy, against number of files. As graph shows, there is a considerable
amount of time taken when intercepting the file operation. Here individual file size is
fixed to 100 MB and number of parameters defined is fixed to 1.
Above two graph shows how time has taken when file sizes increased in normal file
system and after this implementation.
45
Following graph displays the total execution times taken for various file operations
after implementing this feature. File size is fixed to 100MB for CP command, 1KB for
SCP and LPR commands. File size doesn’t make a difference since the same operation
performed against the same file.
According to the above graph, utilized CPU percentage was almost constant and was
around 25.1%.
47
According the graph, memory usage also same an remain constant for various file
operations.
To test the practical usage and the accuracy of the implementation, following use cases
has been identified and applied for both new and previous versions. Refer Appendix E
for detailed test case list.
5.6 Usability
Before:
Solution is to disable USB storage devices. Simply blacklist the kernel driver:
sudo update−i n i t r a m f s −u
After that, nobody can use a USB memory stick in that computer, but still allows the
administrator(s) to manually load the module and use it.
After:
cp U : ∗ DEVICE sdb1
Previous way of restricting USB drive applied to the entire machine. No one would be
able to copy any files. From the business point of view, it is a blocking issue to continue
the daily business. But in the latter way of defining permission, only need to specify in
that particular file.
One of the disadvantage of latter approach is, when user wants to restrict more files
being copied to USB. Then previous approach is usable. But in a practical scenario, it’s
highly unlikely to have a business requirement to block all.
Before:
Since SCP operated on top of SSH, restricting SSH would be the option. There are
several ways available to restrict/allow SSH only within the local network.
Router
SSH configuration
ListenAddress 192.168.0.10
AllowUsers prasad@192 . 1 6 8 . 0 . 0 / 1 6
TCP wrapper
sshd : 1 9 2 . 1 6 8 . 0 .
ALL : ALL
50
Firewall
iptables
ufw
After:
To test the impact on other areas, following methods has been used.
User with the root privileges still has access to the raw disk device, which determined
users can manipulate directly. Hardening the root level user is one way to overcome these
issues.
Simple attack possible under current state of the implementation is, copy file into
another machine. Since defined permission associated with particular file’s inode, per-
missions are transferred with the file. But if the interceptor module not available in that
particular machine, anything can be done to the file.
53
CHAPTER 6
Conclusion
Current file system in Linux allows file owner to restrict or allow file access using
READ, WRITE and EXECUTE permissions based on users and groups. This restriction
levels are not enough specially for the sensitive and highly secure environments. In order
to achieve better granularity in using files, companies tends to go for a third party systems
like AD RAMS, Locklizard’s PDF security, which is not implemented on top of OS.
Motivation for this project was to implement a granular way of defining permissions
for the Linux ext4 file system. Which is included into operating system’s file handlers.
Further the implementation focused on defining parameters in a operational aspect and
validating defined parameters intercepting the process.
6.1 Procedure
First of all, similar systems were identified. There, mainly two systems (AD RMS and
Safegaurd PDF Security) were analyzed.
To define security parameters, extended attributes have been used with implementing
new attribute called FGP.
Evaluation carried out based on security, performance and usability. There, use cases
identified and applied the implementation to check whether it works as expected.
This implementation can further extends to directory level. Since directory is also a
file in Linux, this extension can be a simple one.
Further this implementation can extends to GUI level, since now it operates in Stan-
dard output only.
One of the biggest improvement that can be done is, extending interception to all the
file related operations. Here it considered only three operations, CP, SCP and LPR.
55
Bibliography
[1] I. Tripwire. (2017, dec) Insider threats as the main security threat in
2017. [Online]. Available: https://www.tripwire.com/state-of-security/security-
data-protection/insider-threats-main-security-threat-2017/
[2] Learn.dtexsystems.com. (2017, dec) Learn.dtexsystems.com. [On-
line]. Available: https://learn.dtexsystems.com/rs/173-QMH-
211/images/201620Cos20of20Insider20Threats.pdf
[3] ekransystem.com. (2018, jan) How to prevent industrial espionage: Best practices —
ekran system. [Online]. Available: https://www.ekransystem.com/en/blog/prevent-
industrial-espionage
[4] LinuxQuestions.org. (2017, oct) prevent files from getting copied
even though they have read permission. [Online]. Available: Avail-
able: https://www.linuxquestions.org/questions/linux-security-4/prevent-files-from-
getting-copied-even-though-they-have-read-permission-101361
[5] U. F. RSS. (2017, oct) Thread: Prevent/disable copy of a file. [Online]. Available:
Available: https://ubuntuforums.org/showthread.php?t=1681920
[6] I. it possible to prevent SCP while still allowing SSH access? (2017, nov)
Is it possible to prevent scp while still allowing ssh access? [Online]. Avail-
able: https://serverfault.com/questions/28858/is-it-possible-to-prevent-scp-while-
still-allowing-ssh-access
[7] O. Support. (2017, oct) Information rights management in the 2007 microsoft
office system. [Online]. Available: Available: https://support.office.com/en-
us/article/Information-Rights-Management-in-the-2007-Microsoft-Office-system-
afd5c5a9-e6fb-4ce7-b24c-eadcc9ee3fe8?CorrelationId=dd8eab3f-dcef-4ca2-93bc-
326039966471&ui=en-US&rs=en-US&ad=US&ocmsassetID=HA010102918BM1
[8] C. Leat. (2017, nov) Help.ubuntu.com - filepermissions - community help wiki.
[Online]. Available: https://help.ubuntu.com/community/FilePermissions
[9] SuSETeam. (2017, oct) Access control lists in linux. [Online].
Available: https://www-uxsup.csx.cam.ac.uk/pub/doc/suse/suse9.0/adminguide-
9.0/node27.html
[10] Linux.com. (2017, oct) What is selinux and how does it work. [Online]. Available:
https://www.linux.com/answers/what-selinux-and-how-does-it-work
[11] S. S. Joanna Oja, Linux System Administrators Guide:, 3rd ed. GNU Free Docu-
mentation License, 2003.
56
[14] Kernelnewbies.org. (2018, jan) Ext4 - linux kernel newbies. [Online]. Available:
https://kernelnewbies.org/Ext4/
[16] J. B. Layton. (2017, oct) Extended file attributes rock - linux magazine. [Online].
Available: http://www.linux-mag.com/id/8741/
[17] W. Mauerer, Professional Linux Kernel Architecture, 3rd ed. Wiley Pub., oct 2008,
vol. 8.
[18] C. . Processes. (2017, sep) The linux documentation project. [Online]. Available:
http://www.tldp.org/LDP/tlk/kernel/processes.html
[21] M. T. Jones. (2018, jan) Kernel command using linux system calls - ibm.com.
[Online]. Available: https://www.ibm.com/developerworks/linux/library/l-system-
calls/
57
Appendices
58
APPENDIX A
Most of the time you don’t want to compile the kernel. But when you are going to
add new feature, device driver or bug fix, you should compile the kernel. Here in this
project, modifying extended attributes direclty done in the kernel level. Therefore, kernel
compilation is needed. Below are the steps in order to compile and run linux 4.6 kernel.
A.3 Configure
The kernel contains nearly 3000 configuration options. To make the kernel used by
most people on most hardware, the Linux distro like Ubuntu, Fedora, Debian, RedHat,
CentOS, etc, will generally include support for most common hardware. You can take
any one of configuration from the distro, and on top of that you can add your own
configuration, or you can configure the kernel from scratch, or you can use the default
config provided by the kernel.
cd l i n u x − 4 . 6 . 0
make menuconfig
The make menuconfig, will launch a text-based user interface with default configura-
tion options as shown in the figure. You should have installed “libncurses and libncurses-
devel” packages for this command to work.
The make install command will create the following files in the /boot directory.
60
APPENDIX B
Here we defined xattr fgp.o, which is a new file introduced, as an object file, along
with other attribute files.
61
xattr.c inside ext4 package is the main file to handle extended attribute in ext4 file
system. Here we have defined the handler for newly introduced fgp attribute.
Above we have included into the header file in same ext4 package.
This file handles the newly introduced fine grained permission attributes definitions.
This includes getter, setter and the list functions for this attribute.
/∗
∗ linux / f s / ext4 / x a t t r f g p . c
∗ Handler f o r extended f i n e g r a i n e d p e r m i s s i o n s a t t r i b u t e s .
∗
∗ Copyright (C) 2017 by Prasad Wanigasinghe
∗
∗/
#i n c l u d e
#i n c l u d e
#i n c l u d e
#i n c l u d e ” e x t 4 j b d 2 . h”
#i n c l u d e ” e x t 4 . h”
#i n c l u d e ” x a t t r . h”
static size t
e x t 4 x a t t r f g p l i s t ( s t r u c t i n o d e ∗ inode , char ∗ l i s t , s i z e t
list size ,
c o n s t cha r ∗name , s i z e t name len )
{
c o n s t s i z e t p r e f i x l e n = XATTR FGP PREFIX LEN ;
c o n s t s i z e t t o t a l l e n = p r e f i x l e n + name len + 1 ;
#i f FPM
i f ( ! t e s t o p t ( inode−>i s b , XATTR USER) )
return 0;
#e n d i f
63
i f ( l i s t && t o t a l l e n <= l i s t s i z e ) {
memcpy( l i s t , XATTR FGP PREFIX, p r e f i x l e n ) ;
memcpy( l i s t +p r e f i x l e n , name , name len ) ;
l i s t [ p r e f i x l e n + name len ] = ’ \0 ’ ;
}
return t o t a l l e n ;
}
static int
e x t 4 x a t t r f g p g e t ( s t r u c t i n o d e ∗ inode , c o n s t char ∗name ,
void ∗ buffer , s i z e t s i z e )
{
i f ( strcmp ( name , ”” ) == 0 )
r e t u r n −EINVAL ;
#i f FPM
i f ( ! t e s t o p t ( inode−>i s b , XATTR USER) )
r e t u r n −EOPNOTSUPP;
#e n d i f
r e t u r n e x t 4 x a t t r g e t ( inode , EXT4 XATTR INDEX SNIA , name
, buffer , size ) ;
}
static int
e x t 4 x a t t r f g p s e t ( s t r u c t i n o d e ∗ inode , c o n s t char ∗name ,
c o n s t v o i d ∗ value , s i z e t s i z e , i n t f l a g s )
{
i f ( strcmp ( name , ”” ) == 0 )
r e t u r n −EINVAL ;
#i f FPM
i f ( ! t e s t o p t ( inode−>i s b , XATTR USER) )
r e t u r n −EOPNOTSUPP;
#e n d i f
64
xattr.c in fs package is the main C file, that contains extended attribute details re-
gardless of specific file system.
APPENDIX C
Below are the steps to add Loadable Kernel Module in to the Linux.
s t a t i c void e x i t c le an up mo du l e ( v o i d )
{
p r i n t k (KERN INFO ” E x i t from t he module \n” ) ;
return ;
}
67
C.6 Compilation
make m o d u l e s p r e p a r e
obj−m := lkm . o
KDIR := / l i b / modules / ‘ uname −r ‘ / b u i l d
PWD := ‘pwd ‘
default :
make −C $ (KDIR) M=$ (PWD) modules
lsmod
dmesg
dmsg
69
APPENDIX D
Because sys call table is no longer exported in the 2.6 kernels, we can access it only
by brute force. LKMs have access to kernel memory, so it is possible to gain access
to sys call table by comparing known locations with exported system calls. Although
sys call table itself is not exported, a few system calls such as sys read() and sys write( )
are still exported and available to LKMs.
Notice that the my init( ) function is called during initialization. This function at-
tempts to gain access to sys call table by starting at the address of system utsname.
The system utsname structure contains a list of system information and is known
to exist before the system call table. Therefore, the function starts at the location of
system utsname and iterates 1,024 (MAX TRY) times. It advances a byte every time
and compares the current location with that of sys read(), whose address is assumed to
be available to the LKM. Once a match is found, the loop breaks and we have access to
sys call table:
70
while ( i )
{
i f ( s y s t a b l e [ NR read ] == ( u n s i g n e d l o n g )
sys read )
{
s y s c a l l t a b l e=s y s t a b l e ;
f l a g =1;
break ;
}
i −−;
s y s t a b l e ++;
The LKM invokes xchg( ) to alter the system call table to point sys call table[ NR open]
to our fake open function( ):
o r i g i n a l s y s o p e n =( v o i d ∗ ) xchg(& s y s c a l l t a b l e [ NR open ] ,
new open function ) ;
This causes our fake open function( ) to be invoked instead of the original sys open(
) call. The xchg( ) function also returns original sys open, which contains a pointer to
the original sys open( ). We use this pointer to reset the system call table to point to the
original sys open() when the LKM is unloaded:
xchg(& s y s c a l l t a b l e [ NR open ] , o r i g i n a l s y s o p e n ) ;
71
The our fake open function( ) function checks to see if the *filename parameter is set
to the file we are trying to prevent from being opened, which in our case is assumed to be
/tmp/test. However, it is not sufficient to compare /tmp/test with the value of filename
because if a process’s current directory is /tmp, for example, it might invoke sys open(
) with test as the parameter. The surest way to check if filename is indeed referring to
/tmp/test is to compare the inode of /tmp/test with the inode of the file corresponding
to filename. Inodes are data structures that contain information about files in the system.
Because every file has a unique inode, we can be certain of our results. To obtain the
inode, our fake open function( ) invokes user path walk( ) and passes it filename and a
structure of type nameidata as required by the function. However, before user path walk(
) is called with /tmp/test as a parameter, the LKM calls the following functions:
f s=g e t f s ( ) ;
s e t f s ( get ds ( ) ) ;
The user path walk( ) function expects the location of filename to be present in mem-
ory in user space. However, because we are writing a kernel module, our code will be in
kernel space and user path walk( ) will fail because it expects to be run in user mode.
Therefore, before we invoke user path walk( ), we will need to invoke the get fs( ) func-
tion, which reads the value of the highest segment of kernel memory, and then invoke
set fs( ) along with get ds( ) as a parameter. This changes the kernel virtual memory
limit for user space memory so that user path walk( ) can succeed. Once the module is
done calling user path walk( ), it restores the limit:
set fs ( fs ) ;
72
If the files’ inodes are equal, we know the user is attempting to open /tmp/test and
the module returns -EACCES:
i f ( i n o d e==i n o d e t )
r e t u r n −EACCES;
r e t u r n o r i g i n a l s y s o p e n ( f i l e n a m e , f l a g s , mode ) ;
73
APPENDIX E
APPENDIX F
When system requests fail, error code are returned. To understand the nature of the
error these codes need to be interpreted. They are recorded in /usr/include/asm/errno.h