Jail and monitor your applications
Seamless Overview
Software from unknown sources always poses some risks. With the strace analysis tool and the Firejail sandbox, you can monitor and isolate unknown applications to safeguard your system.
Malware can occasionally become an issue for Linux users. If you download software package from third-party providers then install them manually rather than relying on a distribution's official standard repositories, you need to trust the provider. If you aren't sure, you can monitor these programs to check which files they open and which network connections they establish. Starting these tests in a sandbox also denies the program access to your physical system and private configuration files. This article looks at strace
as a monitoring tool and Firejail as a sandbox.
Finding Traces
The strace
[1] system call tracer can be used to discover which software accesses which files. As an example, I'll show you how to use strace
to find out which files the passwd
command opens when you change your password.
Open two terminal windows and enter passwd
as a normal user in one window. Do not answer the prompts for the time being. Instead, pop up a second terminal and enter as root:
strace -yy -o passwd.log -p $(pidof passwd)
This starts logging for the passwd
process in the first window; the tool writes the information to the passwd.log
. Now enter the old password in the first window and then enter the new password twice.
After leaving passwd
, analyze the logfile created by strace
in the second window. In Figure 1, two grep
calls show that the old password is abc123
, while the new password is a49152bcbc
. In addition, passwd
has accessed six files in the /etc
folder since logging began, including /etc/passwd
and /etc/shadow
(the
latter file
contains the cryptographic hashes of the passwords).
As the example shows, strace
can easily monitor processes that are already running. However, it is usually easier to integrate strace
when launching the program. For example, line 1 in Listing 1 starts an SSH login on a computer named server42
. Among other things, strace
logs all network connections that are opened; you can see this by taking a look at the ssh.log
file. Line 3 is a filter for lines that contain sin_addr
. In the example, the program has opened connections to the local DNS server 127.0.0.53
and to server42
(on IP 192.168.178.173
).
Listing 1
Opening a Connection
01 $ strace -o ssh.log ssh server42 02 [...] 03 $ grep ^connect.*sin_addr ssh.log 04 connect(3, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.0.53")}, 16) = 0 05 connect(3, {sa_family=AF_INET, sin_port=htons(22), sin_addr=inet_addr("192.168.178.173")}, 16) = 0
Strace Magic
But how does this logging work? Modern operating systems create a barrier between the hardware and the applications. For example, programs are not allowed to directly talk to a hard disk controller in order to read and search data blocks from a connected disk. Instead, each application has to be configured via system calls (syscalls for short) to ask the operating system for help. Syscalls are selected kernel functions that the program cannot use directly by making a normal function call. Instead, a more roundabout procedure is used here.
Each syscall supported by the operating system has a number that the program needs to write to a processor register. The arguments for the syscall are written to other registers. The program then executes a special machine language instruction, for example, syscall
, sysenter
, or a classic software interrupt 128 (in assembler: int 0x80
). This switches the program from user mode to kernel mode.
At this point, the operating system takes control. In kernel mode, the OS has full access to the hardware. It uses the syscall number to find the appropriate syscall handler. After an authorization check, it then completes the task resulting from the arguments in other registers. Any return values are stored in another register.
After completing the task, the operating system switches from kernel mode back to user mode. The program then reads the return value and continues its work.
Listing 2 shows a test program in the C programming language that uses open()
to open a file named /etc/os-release
and read()
to load up to 4,095 characters into a buffer. It then calls close()
to close the file and calls write()
to write the buffer content to the standard output (i.e., to the terminal window). The open()
, read()
, write()
, and close()
library functions call syscalls of the same name in the kernel, and strace
can monitor their behavior.
Listing 2
C Test Program
#include <unistd.h> #include <fcntl.h> #define BUFSIZE 4096 int main () { char buf[BUFSIZE] = {0}; int fd = open("/etc/os-release", O_RDONLY); int res = read(fd, buf, BUFSIZE-1); close(fd); write(STDOUT_FILENO, buf, res); }
If you compile the program and run it with strace
, you will find the syscalls in the logfile that is created. Listing 3 shows the command for the call and the last lines from the logfile generated by strace
. The return values of the function calls also appear in the log.
Listing 3
Strace Monitors File Access
$ strace -e trace=open,read,write,close -o /tmp/testprog.log ./testprog PRETTY_NAME="Ubuntu 23.10" [...] $ tail -5 /tmp/testprog.log open("/etc/os-release", O_RDONLY) = 3 read(3, "PRETTY_NAME=\"Ubuntu 23.10\"\nNAME="..., 4095) = 393 close(3) = 0 write(1, "PRETTY_NAME=\"Ubuntu 23.10\"\nNAME="..., 393) = 393 +++ exited with 0 +++
If you monitor an application over a longer period of time, the logfile will tend to be very large. It makes sense to use filters during logging. To do so, specify which syscalls you want strace
to log. Details can be found in the Filtering section of the strace
manpage [2]. Table 1 shows some typical examples.
Table 1
Strace Filtering Options
|
Only |
|
All file operations |
|
All network operations |
The -f
(--follow-forks
) option is also important. It tells strace
to additionally monitor child processes. After all, the interesting things often do not happen in the application that was launched first, but further down in the process tree.
Firejail
Firejail [3] lets you lock programs away in a jail or sandbox. Much like Docker and container-based virtualization in general, jail software lets you run programs in isolation from other applications. The view of the filesystem and the network can also be restricted. Firejail offers these features. Preparing the program profiles makes it easier to use Firejail – ideally, simply precede a program call with the firejail
command. Firejail is available for installation in the standard repositories of many distributions.
Typing firejail
launches a shell where network access is disabled and access to the Bash history is prohibited. These and other restrictive rules are defined by the default.profile
, which Firejail loads for the newly launched shell. From default.profile
, two additional rules are used via include lines. Figure 2 clearly shows that Bash, which is locked in the jail, can neither read the history nor ping a computer on the network.
In principle, software running in a jail still has access to the entire filesystem. The only exceptions to this are areas whose use you explicitly prohibit. As an alternative, you can define a private directory in which the program runs and from which it cannot break out. The --private
option lets you do this; you can use it as shown in Listing 4.
Listing 4
Private Folder
$ mkdir ~/privat $ firejail --private=$HOME/privat
This is particularly interesting for programs that you do not want to access your home directory. The folder specified after --private
acts as a substitute home directory in the jail; the application can create subdirectories and store files there, but not in the entire home directory. This also effectively prevents the program from spying on your private data. Firejail also hides other users' private folders. If you add the --noprofile
switch to the call, Firejail does not apply any rules from the standard profiles. In this case, for example, network tools such as ping
will work.
If you run Firejail with a program name as an argument, the software looks for a suitable profile. The firejail-profiles package contains 1,200 profiles for a wide variety of applications. At startup, Firejail shows you which profile files it is using. For MPlayer, for example, there is the mplayer.profile
file, which includes the generic rules from whitelist-player-common.inc
(Figure 3). These rules apply to all media players and allow access to the download folder, for example.
Firejail does not work with software that you install from Snap packages because it cannot find the binaries from the Snaps. Combining Firejail with strace
also seems impossible at first glance, as an attempt to, for example, have them run MPlayer fails. The solution here is an strace
feature that lets the monitor itself run with root privileges, while the monitored program is running on a normal user account. Listing 5 shows the command, which uses the strace
-u
(for user) option.
Listing 5
Strace and Firejail
$ sudo strace -f -u esser \ -o mplayer.log \ firejail \ mplayer -idx big_buck_bunny.avi
Firejail offers numerous other options that you let you fine tune what to allow and what to prevent the software from doing [4]. It is also useful to inspect the profiles in the /etc/firejail/
folder.
Buy this article as PDF
(incl. VAT)
Buy Linux Magazine
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters
Support Our Work
Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.
News
-
Halcyon Creates Anti-Ransomware Protection for Linux
As more Linux systems are targeted by ransomware, Halcyon is stepping up its protection.
-
Valve and Arch Linux Announce Collaboration
Valve and Arch have come together for two projects that will have a serious impact on the Linux distribution.
-
Hacker Successfully Runs Linux on a CPU from the Early ‘70s
From the office of "Look what I can do," Dmitry Grinberg was able to get Linux running on a processor that was created in 1971.
-
OSI and LPI Form Strategic Alliance
With a goal of strengthening Linux and open source communities, this new alliance aims to nurture the growth of more highly skilled professionals.
-
Fedora 41 Beta Available with Some Interesting Additions
If you're a Fedora fan, you'll be excited to hear the beta version of the latest release is now available for testing and includes plenty of updates.
-
AlmaLinux Unveils New Hardware Certification Process
The AlmaLinux Hardware Certification Program run by the Certification Special Interest Group (SIG) aims to ensure seamless compatibility between AlmaLinux and a wide range of hardware configurations.
-
Wind River Introduces eLxr Pro Linux Solution
eLxr Pro offers an end-to-end Linux solution backed by expert commercial support.
-
Juno Tab 3 Launches with Ubuntu 24.04
Anyone looking for a full-blown Linux tablet need look no further. Juno has released the Tab 3.
-
New KDE Slimbook Plasma Available for Preorder
Powered by an AMD Ryzen CPU, the latest KDE Slimbook laptop is powerful enough for local AI tasks.
-
Rhino Linux Announces Latest "Quick Update"
If you prefer your Linux distribution to be of the rolling type, Rhino Linux delivers a beautiful and reliable experience.