inode: Stores general information about a specific file, such as file type and access rights, file owner, group
owner, length in bytes, operations vector, time of last file access, time of last file write, and time of last inode
change. An inode is associated to each file and is described in the kernel by a struct inode data
structure.
file: Stores the interaction between an open file and a process, such as the pointer to a file operation table,
current offset (position within the file), user id, group id, and the dentry object associated with the file. A
file exists only in kernel memory during the period when each process accesses a file. An open file is
described in the SLES kernel by a struct file.
dentry: Stores information about the linking of a directory entry with the corresponding file, such as a
pointer to the inode associated with the file, filename, pointer to dentry object of the parent directory, or
pointer to directory operations.
vfsmount: Stores information about a mounted file system, such as dentry objects of the mount point
and the root of the file system, the name of device containing the file system, and mount flags.
The kernel uses the above data structures while performing pathname translation and file system mounting
operations relevant to security.
5.1.1.1 Pathname translation
When performing a file operation, the kernel translates a pathname to a corresponding inode. The pathname
translation process performs access checks appropriate to the intended file operation. For example, any file
system function that results in a modification to a directory, such as creating a file or deleting a file, checks to
make sure that the process has write access to the directory being modified. Directories cannot be directly
written into.
Access checking in VFS is performed while an inode is derived from the corresponding pathname. Each
access check involves checking DAC policy first, and if access is permitted by DAC policy, then checking the
AppArmor policy. Pathname lookup routines break up the pathname into a sequence of file names, and
depending on whether the pathname is absolute or relative, the lookup routines start the search from the root
of the file system or from the current directory of the process, respectively. The dentry object for this
starting position is available through the fs field of the current process.
Using the inode of the initial directory, the code looks at the entry that matches the first name to derive the
corresponding inode. Then the directory file that has that inode is read from the disk, and the entry
matching the second name is looked up to derive the corresponding inode. This procedure is repeated for
each name included in the path. At each file lookup within a directory stage, an access check is made to
ensure that the process has appropriate permission to perform the search. The last access check performed
depends on the system call.
For example, when a new file is created, an access check is performed to ensure that the process has write
access to the directory. If an existing file is being opened for read, a permission check is made to ensure that
the process has read access to that file.
The example in Figure 5-5 is a simplified description of a pathname lookup. In reality, the algorithm for
lookup becomes more complicated because of the presence of symbolic links, dot (.), dot dot (..) and extra
slash (/) characters in the pathname. Even though these objects complicate the logic of the lookup routine, the
access check mechanism remains the same.
35