Landlock Convert Example

💾 convert.c

The convert tool reads from an input file (by default stdin), converts the data into a different format, and writes the result to an output file (by default stdout).

Analysis

Risk: The main complexity in this kind of tool is that it might use large libraries for processing file formats. Such libraries, particularly for media processing, often have performance as a primary goal, which can be at odds with secure coding conventions. The size of these libraries can make it more difficult to assess whether they are safe.

(For our example code, we won’t use an actual media processing library though.)

Untrusted input: A media conversion tool might be run with input files from untrusted sources. (In fact, the sanitization of untrusted input is a common use case for such tools.)

Trusted input: The flags provided to the tool are assumed to be safe.

stdin flags convert process stdout

Conclusion: The convert tool is written with Landlock ABI version 3 in mind. Just before starting to process the input to be converted, it will restrict itself so that it can’t open new files from the file system.

Implementation

Let’s break down the main() function:

💚 Initialization phase

In the initialization phase of main(), we parse the command line flags and care about assigning infd and outfd to the right file descriptors. parse_flags() interprets the explicit command line arguments for input and output files, opens them if needed, and stores the resulting file descriptors in infd and outfd.

int main(int argc, char *argv[]) {
  /* Initialization phase: Parse flags. */
  int infd = STDIN_FILENO;
  int outfd = STDOUT_FILENO;
  parse_flags(argc, argv, &infd, &outfd);

🛡️ Enabling the sandbox

After the initialization phase, everything is ready to process the input file. This is the time when we enable our sandbox and forbid further accesses to the file system.

Forbidding all further file accesses is a common case, so we use a helper function for it, which implements the LandlockRulesetEnforcement.

  /* Enable the sandbox. */
  if (promise_no_further_file_access() < 0)
    err(1, "landlock");

The helper function promise_no_further_file_access() enables the sandbox so that no further files from the file system can be accessed if they are not opened already.

It follows the general LandlockRulesetEnforcement scheme, with the following differences:

🔴 Process untrusted input

Now that the Landlock policy is enabled, we start processing the untrusted input from the input file.

While we have already opened the untrusted file during the initialization phase, we do not start reading from the untrusted file descriptor until we have sandboxed ourselves.

  /* Start processing untrusted input: Convert. */
  convert(infd, outfd);
}

And that’s it. The sandbox stays enabled until the program exits.