Skip to content

mballarin/perl-linux-landlock

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

41 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

NAME

Linux::Landlock - A higher level interface to the Linux Landlock API

DESCRIPTION

Landlock is a sandboxing feature specific to Linux that allows a process to restrict its own access to the file system. Once set, restrictions cannot be undone and they are inherited by all future child processes.

Since the restrictions are set at runtime, from within the process itself, you can take into account dynamic information from your configuration. For example, a server that is supposed to serve files from a specific directory can restrict itself to that directory and its subdirectories to mitigate any bugs allowing directory traversal attacks. This is much less intrusive than chroot and does not require root privileges.

This module provides an object-oriented interface to the Linux Landlock API. It uses the lower-level interface provided by Linux::Landlock::Direct.

See https://docs.kernel.org/userspace-api/landlock.html for more information about Landlock.

METHODS

SYNOPSIS

  use Linux::Landlock;

  my $ruleset = Linux::Landlock->new(); # this can die
  $ruleset->add_path_rule('/etc/fstab', qw(read_file));
  $ruleset->add_net_rule(22222, qw(bind_tcp));
  $ruleset->apply();

  print -r '/etc/fstab' ? "allowed\n" : "not allowed\n"; # allowed ...
  IO::File->new('/etc/fstab', 'r') and print "succeeded: $!\n"; # ... and opening works
  print -r '/etc/passwd' ? "allowed\n" : "not allowed\n"; # allowed ...
  IO::File->new('/etc/passwd', 'r') or print "failed\n"; # ... but opening fails because of Landlock

  system('/usr/bin/cat /etc/fstab') and print "failed: $!\n"; # this fails, because we cannot execute cat

  IO::Socket::INET->new(LocalPort => 33333, Proto => 'tcp') or print "failed: $!\n"; # failed
  IO::Socket::INET->new(LocalPort => 22222, Proto => 'tcp') and print "succeeded\n"; # succeeded
  • new([handled_fs_actions => \@fs_actions, handled_net_actions => \@net_actions, die_on_unsupported => 1|0])

    Create a new Linux::Landlock instance.

    handled_fs_actions and handled_net_actions restrict the set of actions that can be used in rules and that will be prevented if not allowed by any rule. By default, all actions supported by the kernel and known to this module are covered. This should usually not be changed.

    If die_on_unsupported is set to a true value, the module will die if an unsupported access right is requested. Otherwise, access rights will be set on a best-effort basis, as intended by the upstream Landlock API design. This option should usually not be used.

  • apply()

    Apply the ruleset to the current process and all future children. Dies on error.

  • get_abi_version()

    Int, returns the ABI version of the Landlock kernel module. Can be called as a static method. A version < 1 means that Landlock is not available.

  • add_path_beneath_rule($path, @allowed)

    Add a rule to the ruleset that allows the specified access to the given path. $path can be a file or a directory. @allowed is a list of access rights to allow.

    Possible access rights are:

      execute
      write_file
      read_file
      read_dir
      remove_dir
      remove_file
      make_char
      make_dir
      make_reg
      make_sock
      make_fifo
      make_block
      make_sym
      refer
      truncate
    

    See https://docs.kernel.org/userspace-api/landlock.html for all possible access rights.

    This method dies on error. Errors are: non-existing or non-accessible paths and empty rules. If die_on_unsupported is used, it will also die if the rules are not supported by the current kernel.

    Beware: While the API accepts a path or user space file descriptor, the rule is actually applied to the kernel internal file system object. This means that you will lose access if a path or directory you allowed access to is renamed or replaced.

  • add_net_port_rule($port, @allowed)

    Add a rule to the ruleset that allows the specified access to the given port. $port is allowed port, @allowed is a list of allowed operations.

    Possible operations are:

      bind_tcp
      connect_tcp
    
  • allow_perl_inc_access()

    A convenience method that adds rules to allow reading files and directories in all directories in @INC. This will not allow access to ".", even if it is in @INC.

LIMITATIONS

This module requires a Linux system supporting the Landlock functionality. As of 2024, this is the case for almost all distributions, however, the version of the available Landlock ABI varies.

Notably, the TRUNCATE access right is only supported by the kernel since ABI version 3 (kernel version 6.2 or newer, unless backported).

Network functionality is only available since ABI version 4.

Also keep in mind, that some Perl, or even libc, functions might implicitly rely on file system access that could have been restricted by Landlock.

AUTHOR

Marc Ballarin, ballarin.marc@gmx.de

COPYRIGHT AND LICENSE

Copyright (C) 2024 by Marc Ballarin

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages