4. ARREGLOS INSTITUCIONALES PARA LA IMPLEMENTACIÓN DEL PRORURAL
4.4 P RINCIPIOS PARA LA REFORMA INSTITUCIONAL SECTORIAL
Recent versions of Linux offer the fanotify API as a new functionality which im- plements file-access monitoring techniques. The interface provides a system of inter- ception and notification for events that occur on the file system. Supported events include the opening of a file, a read operation, a write operation and a close. Such functionality is commonly used during the design of anti-virus software, where a system-wide scan of file-access operations is usually performed in order to identify
3.1. PROFILING THE CONTAINER EXECUTION 51
Figure 3.1: Identification of the essential files
suspicious patterns of the activity of a process. The API could also satisfy our pur- poses, as it offers a way to detect the objects that a Docker container makes use of during its execution.
The kernel delivers file-access monitoring through a set of system calls. First of all, the fanotify init shall be used to create a new notification group. The notification group is an object that lives in the kernel and holds the list of the objects (i.e. files, directories and mount points) that have to be monitored. A second system call, fanotify mark, can therefore be used to add new objects to the group while, for each of them, specifying the events that should be reported. Once the notification group has been created and initialized, processes that are interested in receiving and handling notification events can perform a read on the file descriptor that the initial fanotify init returns. It is a blocking call, meaning that the execution of the listener process will stop until an event is fired. When this happens, the read unlocks and a series of one or more data structures of type fanotify event metadata flows into the buffer. Each of the received structures represent an event that has occurred on the file system and contains multiple descriptive fields. In particular, among the included information we can find the ID of the process that caused the event and the file descriptor for the object being accessed.
As a second approach to monitor the activity of a containerized process, we made use of the fanotify API. Yet, instead of building a program and use the system calls directly, we tried to exploit a tool called fatrace (file-access trace). Fatrace [18] is an open-source program which is freely available on the Internet. By using the fanotify API and the data in the /proc folder, fatrace is able to produce a log of events that report which files are being accessed by any running process.
52 CHAPTER 3. SYSTEM DESIGN
The monitoring of the container through the host file system has proven to be unsuccessful; after all, the documentation of the tool warns that events on virtual and kernel file systems will be ingnored. For this reason, we have decided to perform the profiling of the container within the container itself. In order to be able to launch fatrace inside the container, the executable must be included into its file system. One possibility is to include the binaries in the image by means of a new Dockerfile. Another possibility is to prepare an appropriate folder on the host and make its content accessible from within the isolated environment by means of a bind mound; the goal is to provide the isolated process with the access to the access to the fatrace executable. Figure 3.1 reports a scheme of the profiling mechanism. Listings 5 and 6 show respectively how we made use of it to start the container with the execution of fatrace and launch the application that ought to be profiled. $ docker run --name httpd-profiler
-v "$PWD/profiling":"/profiling"
--cap-add SYS_ADMIN -it httpd /profiling/fatrace -c -t
Listing 5: Initialization of the profiling environment for Apache httpd
$ docker exec httpd-profiler httpd-foreground
Listing 6: Launch of the Apache httpd web server
During the simulation phase we train the container by stimulating an activity that mirrors as much as possible a typical use-case. As we said in the previous section, the kind of operations performed in this stage depend on the application under scrutiny; therefore, there is a large degree of freedom that can be explored. Once the simulation is over, we stop the execution and we retrieve the log produced by the tracing mechanism. Listing 7 provides a sample of it.
Each line of the log corresponds to an event occurred on the file system. In order, from left to right, we can find:
• a timestamp indicating when the event was intercepted; • name and ID of the process that caused the event;
3.1. PROFILING THE CONTAINER EXECUTION 53 17:03:26.646211 runc:[2:INIT](10): O /etc/passwd 17:03:26.646211 runc:[2:INIT](10): O /etc/group 17:03:26.646466 runc:[2:INIT](10): RC /etc/passwd 17:03:26.646466 runc:[2:INIT](10): RC /etc/group 17:03:26.646466 runc:[2:INIT](10): RO /usr/local/bin/docker-ent... 17:03:26.646466 runc:[2:INIT](10): RO /bin/dash 17:03:26.646466 runc:[2:INIT](10): RO /lib/x86_64-linux-gnu/ld-... 17:03:26.647142 docker-entrypoi(10): C /usr/local/bin/docker-en... 17:03:26.647190 docker-entrypoi(10): O /etc/ld.so.cache
Listing 7: Extract from a log produced by fatrace
• type of the event (O for open, R for read, W for write, C for close or a combination of them);
• path of the affected file.
The last step is the filtering of the log data. As we said, we are interested in finding the name of those file that are accessed, regardless of the time, the process nor the type of the operation. The shell command in Listing 8 shows how our requirements can be translated into code.
$ cat output.log | cut -d ' ' -f 4 | sort | uniq
Listing 8: Processing the generated log data
The result proves that the approach is suitable for our purposes.