\chapter{Implementation} \label{impl} This chapter outlines the software design and architecture of ICFS, detailing how these elements address the challenge of fine-grained access control. Subsequent sections introduce the FUSE framework, methods for managing process-specific permissions, and the architectural strategies employed to mitigate unauthorised filesystem access. \section{FUSE framework} \label{impl:fuse} To regulate filesystem operations, ICFS employs the FUSE (Filesystem in Userspace) framework\cite{FUSE}, which intercepts filesystem calls. FUSE enables the creation of custom filesystems or layers in user space, offering flexibility and ease of implementation. It provides an API for developers to define filesystem behavior. Once implemented (hereafter termed the FUSE application ), the system mounts the custom filesystem at a specified location, substituting standard filesystem operations with methods defined by the API. ICFS implements this API in C using the libfuse3 library. It initializes the FUSE daemon via the \verb|fuse_main()| function, which manages communication between the kernel and the FUSE application. Rather than directly overriding system calls, FUSE interacts with the kernel through \verb|/dev/fuse|, a specialized device file that translates filesystem requests into API method invocations using a dedicated protocol. ICFS does not have a backing store (a separate filesystem that contains actual data). Instead, it functions as a so-called passthrough filesystem, where system calls are forwarded to the original filesystem, if access control policies allow them. To enforce access restrictions, ICFS mounts directly over the target directory, intercepting all access requests directed to it. As part of Linux’s Virtual Filesystem (VFS) architecture, processes interacting with the protected directory are routed through ICFS. However, ICFS retains direct access to the underlying files by opening the directory with the \verb|O_PATH| flag before mount. Subsequent operations are executed using "at"-suffixed system calls like \verb|openat()|, performed directly at the file descriptor level\cite{MANOPEN}, which bypasses ICFS's own layer. \section{Permission tables} To enforce an access control policy over time, filesystem needs to store user decisions in an appropriate data structure. As described in \autoref{icfs:model}, ICFS can give out two types of permissions: temporary and permanent. To accommodate this access control model, ICFS implements two data structures: a temporary permissions table, and a permanent permissions table, which we describe in detail in \autoref{impl:temp} and \autoref{impl:perm} respectively. \subsection{Temporary permissions} \label{impl:temp} To function, temporary permissions storage should contain all information needed to identify the process, and associate the files to which the access is denied or allowed with it. We chose to keep track of processes by comparing the following characteristics: \begin{itemize} \item Process ID: Number that uniquely identifies a process on Linux systems. \item Start time: The time the process started after system boot. The value is expressed in clock ticks. \end{itemize} The process is considered the same if and only if both characteristics match. At first, it might seem that factoring in start time is excessive. However, only using PID as the only identifying property of a process is problematic: PID is only unique among the currently running processes, not across the entire uptime of the system. Processes can not only acquire the PID of another, already finished process, but also attempt to request a specific PID. The start time is looked up in procfs by PID, which is provided by libfuse. The temporary permissions table consists of tuples $(pid, starttime, allowed, denied)$, where $allowed$ and $denied$ are sequences of files, that the process is allowed or denied to access respectively. In our implementation, entries are organised in a hash map, with PIDs as keys. This provides quick lookup of entries, that is much needed for filesystem operations. ICFS uses the hash map implementation from the Convenient Containers library \cite{CC}, that is well-tested and has an intuitive interface, which has helped to simplify the development. \subsection{Permanent permissions} \label{impl:perm}