|
Design |
In
our first version of Lisex (Lisex 0.0) we tried to follow the Linux
Kernel design as much as possible. However, due to the addition
of the proposed security features, it was necessary to modify certain
kernel structures and/or functions. In what follows, we explain
several general aspects about the design of Lisex's kernel, and
their relationships with the original design.
The
design document
is
composed of this page and the relationships between every system
call
and
the formal modeled ones.
More detailed information
about the design can be found in the programmer's
manual.
|
Introduction |
Linux
follows most operating system’s basic architecture, that is, a user
level software or application software layer, and a layer that contains
the operating system’s kernel (see figure).
The interaction between these layers is based on shared memory
and procedure calls. The lower layer (kernel layer) defines a set
of functions, widely known as system calls, which are used by the
higher layer (user software) to invoke its services. The kernel
use a protected mode of execution provided by the hardware, which
hinders access of the lower layer data by higher layer software.
The
kernel's system calls can be grouped in a way that conceptually
divides it into several sub-systems (memory management, process
management, filesystems, etc.). There are cases where this division
is not clear nor accurate (some process management functions can
be accessed via the filesystem, for example). At source code level,
these divisions are represented by one o more files (each with extension
".c" or ".h"), located at different directories (filesystem files
are located in the "fs" directory, for example).
Each
sub-system is composed of several data structures and auxiliary functions,
which are not accessible from user space. However, by the sake
of efficiency, they are seldom hided behind abstract interfaces.
|
|
|
|
Components
scheme of the Linux Kernel design. It shows ADTs present in
Lisex design. Arrows indicate the most usual function calls
patterns.This scheme is, by no means, complete, its only objective
is to show components of interest for the present document.
|
|
|
The
Filesystem2> |
As
we said, Lisex 0.0 is an improvement of the Linux kernel restricted
(by now) to the filesystem operation. That's why, we will concentrate
our design efforts in this specific sub-system.
The
Linux filesystem is composed of various components: VFS (or Virtual
Filesystem) and a component for each registered filesystem type
(see figure).
Filesystems which deal with real files are the most common, but
there are other kinds of filesystems registered to VFS (as /proc,
for example) that allow access to (usually not persistent) data
in the same way we access traditional file data. Today, the most
common filesystem type used for real files in Linux is EXT2.
In
general terms, filesystems manage low level access to physical storage
devices, while VFS goal is to show a unified interface which abstract
the peculiarities of different filesystem types. Access to FAT filesystem
files, for example, is done in the same way that EXT2 files are
accessed, since in both cases what are really done are file operations
over VFS structures. Real filesystems and VFS are connected to each
other through the use of procedure calls and shared memory.
Lisex 0.0 introduces changes to VFS
and EXT2. Those changes include system calls, auxiliary functions
and data structures additions and modifications. Every modification
preserves the interfaces, and design is not altered. Additions, on
the other side, alter the design, and are described in detail
in the following sections:
|
New
System Calls |
Lisex
0.0 extends the filesystems by the addition of the following system
calls:
![]() |
sys_acladd() , to
add user or group permissions to files or directories ACLs.
|
![]() |
sys_acldel() ,
to remove user or group permissions from files or directories
ACLs.
|
![]() |
sys_oscstat() ,
to return a file or directory access class.
|
![]() |
sys_chobjsc() , to
change a file or directory access class.
|
![]() |
sys_aclstat() , to
return a file or directory ACL.
|
![]() |
sys_aclfstat() , the
same as the last one, but for opened files or directories.
|
![]() |
sys_chsubsc() , to
change a user access class.
|
![]() |
sys_sscstat() , to
return a user access class.
|
For
more detailed documentation about Lisex's design
see
the specification,
and the programmer's
manual.
|
New auxiliary
functions |
There
are no new auxiliary functions at the EXT2 level. Only the following
VFS
level auxiliary functions
where added:
![]() |
may_open() , decides
if an open operation over a file can be done or not. It uses
the functions permission() and
mac_permission() , and
it is used by
do_execve() , may_delete() , may_create() , sys_setuid() and open_namei() .
|
![]() |
acl_chmod_ok() , to
check if sys_chmod() can
be done. It is used by sys_chmod() .
|
![]() |
is_open() , to
check if a given file is opened or not. It is used by
sys_acladd() , sys_acldel() , sys_hobjsc() , sys_chmod() , sys_chown() y sys_lchown() .
|
![]() |
mac_permission() ,
to implement MAC and MLS security. It is used by may_open() .
|
![]() |
mac_permission() , to
implement MAC and MLS security. It is used by may_open() .
|
![]() |
logged() ,
to check if a there are processes running on behalf of a given
user. It is used by sys_chsubsc() .
|
More
details can be found in the programmer's
manual.
The
next section details the new auxiliary functions added a part of
new abstract data types.
|
New ADTs and
data structures |
Lisex
0.0 introduce four new abstract data types (ADT), that are described
bellow. By saying ADT we mean a data structure together with a set
of sub-programs delivered in a way such that the structure information
can only be accessed and/or modified by the use of these programs.
The data structure in commonly known as the ADT's secret, and the
set of sub-programs its interfaces. Designs like this are said to
be based in the principle of information hiding.
The
Linux kernel is implemented in the C programming language, which
makes it difficult to impose the information hiding principle at
compilation time, as we would do with C++ for example. That is,
it is possible to write code that violates the ADT concept, accessing
and/or modifying data structure information in a direct way. The
only way to follow this principle is to impose a programming discipline
that states that programmers assume the compromise to access data
structure information only via ADTs interfaces.
The
defined ADTs are:
![]() |
vfs-acl , whose
secret is the VFS level ACL implementation, and provides functions
to get the UNIX mode, given an ACL, to initialize an ACL, to
establish user o group permissions, etc.
|
![]() |
sc ,
which hides access class representation, and provide functions
to get and set the level and categories of a given access class,
to compare two access classes, etc.
|
![]() |
acl_entry , whose
secret is the VFS level internal representation of the tuple
(U_G_ID, type, mode), which codifies the
mode of a user or group depending on the value of type,
and provide functions to alter and consult every tuple state.
|
![]() |
subjectsc , which
hides the way in which user access classes are stored, and provide
functions to initialize an access class, to get and set a user
access class, etc.
|
![]() |
ext2_acl_entry , similar
to acl_entry but
at the EXT2 level.
|
More
details can be found in the programmer's
manual.
|
|