mirror of
https://github.com/netblue30/firejail.git
synced 2026-05-15 14:16:14 -06:00
feature: add Landlock support
Based on 5315 by ChrysoliteAzalea. It is based on the same underlying structure, but with a lot of refactoring/simplification and with bugfixes and improvements. Co-authored-by: Kelvin M. Klann <kmk3.code@protonmail.com> Co-authored-by: Азалия Смарагдова <charming.flurry@yandex.ru>
This commit is contained in:
parent
5456ec6477
commit
13b2c566df
18 changed files with 616 additions and 30 deletions
3
README
3
README
|
|
@ -197,7 +197,8 @@ avoidr (https://github.com/avoidr)
|
|||
- fixed mpv profile
|
||||
- various other fixes
|
||||
Азалия Смарагдова/ChrysoliteAzalea (https://github.com/ChrysoliteAzalea)
|
||||
- add support for custom AppArmor profiles (--apparmor=)
|
||||
- add support for custom AppArmor profiles (--apparmor=)
|
||||
- add Landlock support
|
||||
backspac (https://github.com/backspac)
|
||||
- firecfg fixes
|
||||
- add steam-runtime alias
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ HAVE_FIRETUNNEL=@HAVE_FIRETUNNEL@
|
|||
HAVE_FORCE_NONEWPRIVS=@HAVE_FORCE_NONEWPRIVS@
|
||||
HAVE_GLOBALCFG=@HAVE_GLOBALCFG@
|
||||
HAVE_IDS=@HAVE_IDS@
|
||||
HAVE_LANDLOCK=@HAVE_LANDLOCK@
|
||||
HAVE_LTS=@HAVE_LTS@
|
||||
HAVE_NETWORK=@HAVE_NETWORK@
|
||||
HAVE_ONLY_SYSCFG_PROFILES=@HAVE_ONLY_SYSCFG_PROFILES@
|
||||
|
|
@ -60,6 +61,7 @@ MANFLAGS = \
|
|||
$(HAVE_FORCE_NONEWPRIVS) \
|
||||
$(HAVE_GLOBALCFG) \
|
||||
$(HAVE_IDS) \
|
||||
$(HAVE_LANDLOCK) \
|
||||
$(HAVE_LTS) \
|
||||
$(HAVE_NETWORK) \
|
||||
$(HAVE_ONLY_SYSCFG_PROFILES) \
|
||||
|
|
|
|||
86
configure
vendored
86
configure
vendored
|
|
@ -675,6 +675,7 @@ HAVE_OVERLAYFS
|
|||
HAVE_DBUSPROXY
|
||||
EXTRA_LDFLAGS
|
||||
EXTRA_CFLAGS
|
||||
HAVE_LANDLOCK
|
||||
HAVE_SELINUX
|
||||
AA_LIBS
|
||||
AA_CFLAGS
|
||||
|
|
@ -737,6 +738,7 @@ enable_sanitizer
|
|||
enable_ids
|
||||
enable_apparmor
|
||||
enable_selinux
|
||||
enable_landlock
|
||||
enable_dbusproxy
|
||||
enable_output
|
||||
enable_usertmpfs
|
||||
|
|
@ -1396,6 +1398,7 @@ Optional Features:
|
|||
--enable-ids enable ids
|
||||
--enable-apparmor enable apparmor
|
||||
--enable-selinux SELinux labeling support
|
||||
--enable-landlock Landlock self-restriction support
|
||||
--disable-dbusproxy disable dbus proxy
|
||||
--disable-output disable --output logging
|
||||
--disable-usertmpfs disable tmpfs as regular user
|
||||
|
|
@ -3739,6 +3742,58 @@ then :
|
|||
|
||||
fi
|
||||
|
||||
HAVE_LANDLOCK=""
|
||||
|
||||
# Check whether --enable-landlock was given.
|
||||
if test ${enable_landlock+y}
|
||||
then :
|
||||
enableval=$enable_landlock;
|
||||
fi
|
||||
|
||||
ac_header= ac_cache=
|
||||
for ac_item in $ac_header_c_list
|
||||
do
|
||||
if test $ac_cache; then
|
||||
ac_fn_c_check_header_compile "$LINENO" $ac_header ac_cv_header_$ac_cache "$ac_includes_default"
|
||||
if eval test \"x\$ac_cv_header_$ac_cache\" = xyes; then
|
||||
printf "%s\n" "#define $ac_item 1" >> confdefs.h
|
||||
fi
|
||||
ac_header= ac_cache=
|
||||
elif test $ac_header; then
|
||||
ac_cache=$ac_item
|
||||
else
|
||||
ac_header=$ac_item
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if test $ac_cv_header_stdlib_h = yes && test $ac_cv_header_string_h = yes
|
||||
then :
|
||||
|
||||
printf "%s\n" "#define STDC_HEADERS 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
if test "x$enable_landlock" != "xno"
|
||||
then :
|
||||
|
||||
ac_fn_c_check_header_compile "$LINENO" "linux/landlock.h" "ac_cv_header_linux_landlock_h" "$ac_includes_default"
|
||||
if test "x$ac_cv_header_linux_landlock_h" = xyes
|
||||
then :
|
||||
HAVE_LANDLOCK="-DHAVE_LANDLOCK"
|
||||
else $as_nop
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: header not found: linux/landlock.h, building without Landlock support" >&5
|
||||
printf "%s\n" "$as_me: WARNING: header not found: linux/landlock.h, building without Landlock support" >&2;}
|
||||
fi
|
||||
|
||||
|
||||
fi
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -4112,6 +4167,7 @@ if test "x$enable_lts" = "xyes"
|
|||
then :
|
||||
|
||||
HAVE_LTS="-DHAVE_LTS"
|
||||
HAVE_LANDLOCK=""
|
||||
HAVE_IDS=""
|
||||
HAVE_DBUSPROXY=""
|
||||
HAVE_OVERLAYFS=""
|
||||
|
|
@ -4132,35 +4188,6 @@ then :
|
|||
|
||||
fi
|
||||
|
||||
ac_header= ac_cache=
|
||||
for ac_item in $ac_header_c_list
|
||||
do
|
||||
if test $ac_cache; then
|
||||
ac_fn_c_check_header_compile "$LINENO" $ac_header ac_cv_header_$ac_cache "$ac_includes_default"
|
||||
if eval test \"x\$ac_cv_header_$ac_cache\" = xyes; then
|
||||
printf "%s\n" "#define $ac_item 1" >> confdefs.h
|
||||
fi
|
||||
ac_header= ac_cache=
|
||||
elif test $ac_header; then
|
||||
ac_cache=$ac_item
|
||||
else
|
||||
ac_header=$ac_item
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if test $ac_cv_header_stdlib_h = yes && test $ac_cv_header_string_h = yes
|
||||
then :
|
||||
|
||||
printf "%s\n" "#define STDC_HEADERS 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
ac_fn_c_check_header_compile "$LINENO" "linux/seccomp.h" "ac_cv_header_linux_seccomp_h" "$ac_includes_default"
|
||||
if test "x$ac_cv_header_linux_seccomp_h" = xyes
|
||||
then :
|
||||
|
|
@ -5360,6 +5387,7 @@ Features:
|
|||
firetunnel support: $HAVE_FIRETUNNEL
|
||||
global config: $HAVE_GLOBALCFG
|
||||
IDS support: $HAVE_IDS
|
||||
Landlock support: $HAVE_LANDLOCK
|
||||
LTS: $HAVE_LTS
|
||||
manpage support: $HAVE_MAN
|
||||
network: $HAVE_NETWORK
|
||||
|
|
|
|||
12
configure.ac
12
configure.ac
|
|
@ -81,6 +81,16 @@ AS_IF([test "x$enable_selinux" = "xyes"], [
|
|||
LIBS="$LIBS -lselinux"
|
||||
])
|
||||
|
||||
HAVE_LANDLOCK=""
|
||||
AC_SUBST([HAVE_LANDLOCK])
|
||||
AC_ARG_ENABLE([landlock],
|
||||
[AS_HELP_STRING([--enable-landlock], [Landlock self-restriction support])])
|
||||
AS_IF([test "x$enable_landlock" != "xno"], [
|
||||
AC_CHECK_HEADER([linux/landlock.h],
|
||||
[HAVE_LANDLOCK="-DHAVE_LANDLOCK"],
|
||||
[AC_MSG_WARN([header not found: linux/landlock.h, building without Landlock support])])
|
||||
])
|
||||
|
||||
AC_SUBST([EXTRA_CFLAGS])
|
||||
AC_SUBST([EXTRA_LDFLAGS])
|
||||
|
||||
|
|
@ -264,6 +274,7 @@ AC_ARG_ENABLE([lts],
|
|||
[AS_HELP_STRING([--enable-lts], [enable long-term support software version (LTS)])])
|
||||
AS_IF([test "x$enable_lts" = "xyes"], [
|
||||
HAVE_LTS="-DHAVE_LTS"
|
||||
HAVE_LANDLOCK=""
|
||||
HAVE_IDS=""
|
||||
HAVE_DBUSPROXY=""
|
||||
HAVE_OVERLAYFS=""
|
||||
|
|
@ -324,6 +335,7 @@ Features:
|
|||
firetunnel support: $HAVE_FIRETUNNEL
|
||||
global config: $HAVE_GLOBALCFG
|
||||
IDS support: $HAVE_IDS
|
||||
Landlock support: $HAVE_LANDLOCK
|
||||
LTS: $HAVE_LTS
|
||||
manpage support: $HAVE_MAN
|
||||
network: $HAVE_NETWORK
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ keep-config-pulse
|
|||
keep-dev-shm
|
||||
keep-shell-rc
|
||||
keep-var-tmp
|
||||
landlock
|
||||
machine-id
|
||||
memory-deny-write-execute
|
||||
netfilter
|
||||
|
|
|
|||
|
|
@ -29,6 +29,11 @@ ip6
|
|||
iprange
|
||||
join-or-start
|
||||
keep-fd
|
||||
landlock.execute
|
||||
landlock.proc
|
||||
landlock.read
|
||||
landlock.special
|
||||
landlock.write
|
||||
mac
|
||||
mkdir
|
||||
mkfile
|
||||
|
|
|
|||
|
|
@ -42,6 +42,25 @@ _firejail()
|
|||
_filedir -d
|
||||
return 0
|
||||
;;
|
||||
--landlock)
|
||||
return 0
|
||||
;;
|
||||
--landlock.read)
|
||||
_filedir
|
||||
return 0
|
||||
;;
|
||||
--landlock.write)
|
||||
_filedir
|
||||
return 0
|
||||
;;
|
||||
--landlock.special)
|
||||
_filedir
|
||||
return 0
|
||||
;;
|
||||
--landlock.execute)
|
||||
_filedir
|
||||
return 0
|
||||
;;
|
||||
--tmpfs)
|
||||
_filedir
|
||||
return 0
|
||||
|
|
|
|||
|
|
@ -363,6 +363,13 @@ static const char *const compiletime_support =
|
|||
"disabled"
|
||||
#endif
|
||||
|
||||
"\n\t- Landlock support is "
|
||||
#ifdef HAVE_LANDLOCK
|
||||
"enabled"
|
||||
#else
|
||||
"disabled"
|
||||
#endif
|
||||
|
||||
"\n\t- networking support is "
|
||||
#ifdef HAVE_NETWORK
|
||||
"enabled"
|
||||
|
|
|
|||
|
|
@ -281,6 +281,9 @@ extern int arg_overlay; // overlay option
|
|||
extern int arg_overlay_keep; // place overlay diff in a known directory
|
||||
extern int arg_overlay_reuse; // allow the reuse of overlays
|
||||
|
||||
extern int arg_landlock; // add basic Landlock rules
|
||||
extern int arg_landlock_proc; // 0 - no access; 1 -read-only; 2 - read-write
|
||||
|
||||
extern int arg_seccomp; // enable default seccomp filter
|
||||
extern int arg_seccomp32; // enable default seccomp filter for 32 bit arch
|
||||
extern int arg_seccomp_postexec; // need postexec ld.preload library?
|
||||
|
|
@ -950,4 +953,23 @@ void run_ids(int argc, char **argv);
|
|||
// oom.c
|
||||
void oom_set(const char *oom_string);
|
||||
|
||||
// landlock.c
|
||||
#ifdef HAVE_LANDLOCK
|
||||
int ll_get_fd(void);
|
||||
int ll_read(const char *allowed_path);
|
||||
int ll_write(const char *allowed_path);
|
||||
int ll_special(const char *allowed_path);
|
||||
int ll_exec(const char *allowed_path);
|
||||
int ll_basic_system(void);
|
||||
int ll_restrict(__u32 flags);
|
||||
#else
|
||||
static inline int ll_get_fd(void) { return -1; }
|
||||
static inline int ll_read(...) { return 0; }
|
||||
static inline int ll_write(...) { return 0; }
|
||||
static inline int ll_special(...) { return 0; }
|
||||
static inline int ll_exec(...) { return 0; }
|
||||
static inline int ll_basic_system(void) { return 0; }
|
||||
static inline int ll_restrict(...) { return 0; }
|
||||
#endif /* HAVE_LANDLOCK */
|
||||
|
||||
#endif
|
||||
|
|
|
|||
263
src/firejail/landlock.c
Normal file
263
src/firejail/landlock.c
Normal file
|
|
@ -0,0 +1,263 @@
|
|||
/*
|
||||
* Copyright (C) 2014-2023 Firejail Authors
|
||||
*
|
||||
* This file is part of firejail project
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_LANDLOCK
|
||||
#include "firejail.h"
|
||||
#include <linux/landlock.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
static int ll_ruleset_fd = -1;
|
||||
|
||||
int ll_get_fd(void) {
|
||||
return ll_ruleset_fd;
|
||||
}
|
||||
|
||||
#ifndef landlock_create_ruleset
|
||||
static inline int
|
||||
landlock_create_ruleset(const struct landlock_ruleset_attr *const attr,
|
||||
const size_t size, const __u32 flags) {
|
||||
return syscall(__NR_landlock_create_ruleset, attr, size, flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef landlock_add_rule
|
||||
static inline int
|
||||
landlock_add_rule(const int ruleset_fd,
|
||||
const enum landlock_rule_type rule_type,
|
||||
const void *const rule_attr,
|
||||
const __u32 flags) {
|
||||
return syscall(__NR_landlock_add_rule, ruleset_fd, rule_type,
|
||||
rule_attr, flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef landlock_restrict_self
|
||||
static inline int
|
||||
landlock_restrict_self(const int ruleset_fd, const __u32 flags) {
|
||||
return syscall(__NR_landlock_restrict_self, ruleset_fd, flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int ll_create_full_ruleset() {
|
||||
struct landlock_ruleset_attr attr;
|
||||
attr.handled_access_fs =
|
||||
LANDLOCK_ACCESS_FS_EXECUTE |
|
||||
LANDLOCK_ACCESS_FS_MAKE_BLOCK |
|
||||
LANDLOCK_ACCESS_FS_MAKE_CHAR |
|
||||
LANDLOCK_ACCESS_FS_MAKE_DIR |
|
||||
LANDLOCK_ACCESS_FS_MAKE_FIFO |
|
||||
LANDLOCK_ACCESS_FS_MAKE_REG |
|
||||
LANDLOCK_ACCESS_FS_MAKE_SOCK |
|
||||
LANDLOCK_ACCESS_FS_MAKE_SYM |
|
||||
LANDLOCK_ACCESS_FS_READ_DIR |
|
||||
LANDLOCK_ACCESS_FS_READ_FILE |
|
||||
LANDLOCK_ACCESS_FS_REMOVE_DIR |
|
||||
LANDLOCK_ACCESS_FS_REMOVE_FILE |
|
||||
LANDLOCK_ACCESS_FS_WRITE_FILE;
|
||||
|
||||
ll_ruleset_fd = landlock_create_ruleset(&attr, sizeof(attr), 0);
|
||||
if (ll_ruleset_fd < 0) {
|
||||
fprintf(stderr, "Error: failed to create a Landlock ruleset: %s\n",
|
||||
strerror(errno));
|
||||
}
|
||||
return ll_ruleset_fd;
|
||||
}
|
||||
|
||||
int ll_read(const char *allowed_path) {
|
||||
if (ll_ruleset_fd == -1)
|
||||
ll_ruleset_fd = ll_create_full_ruleset();
|
||||
|
||||
int error;
|
||||
int allowed_fd = open(allowed_path, O_PATH | O_CLOEXEC);
|
||||
if (allowed_fd < 0) {
|
||||
if (arg_debug) {
|
||||
fprintf(stderr, "%s: failed to open %s: %s\n",
|
||||
__func__, allowed_path, strerror(errno));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
struct landlock_path_beneath_attr target;
|
||||
target.parent_fd = allowed_fd;
|
||||
target.allowed_access =
|
||||
LANDLOCK_ACCESS_FS_READ_DIR |
|
||||
LANDLOCK_ACCESS_FS_READ_FILE;
|
||||
|
||||
error = landlock_add_rule(ll_ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
|
||||
&target, 0);
|
||||
if (error) {
|
||||
fprintf(stderr, "Error: %s: failed to add Landlock rule for %s: %s\n",
|
||||
__func__, allowed_path, strerror(errno));
|
||||
}
|
||||
close(allowed_fd);
|
||||
return error;
|
||||
}
|
||||
|
||||
int ll_write(const char *allowed_path) {
|
||||
if (ll_ruleset_fd == -1)
|
||||
ll_ruleset_fd = ll_create_full_ruleset();
|
||||
|
||||
int error;
|
||||
int allowed_fd = open(allowed_path, O_PATH | O_CLOEXEC);
|
||||
if (allowed_fd < 0) {
|
||||
if (arg_debug) {
|
||||
fprintf(stderr, "%s: failed to open %s: %s\n",
|
||||
__func__, allowed_path, strerror(errno));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
struct landlock_path_beneath_attr target;
|
||||
target.parent_fd = allowed_fd;
|
||||
target.allowed_access =
|
||||
LANDLOCK_ACCESS_FS_MAKE_DIR |
|
||||
LANDLOCK_ACCESS_FS_MAKE_REG |
|
||||
LANDLOCK_ACCESS_FS_MAKE_SYM |
|
||||
LANDLOCK_ACCESS_FS_REMOVE_DIR |
|
||||
LANDLOCK_ACCESS_FS_REMOVE_FILE |
|
||||
LANDLOCK_ACCESS_FS_WRITE_FILE;
|
||||
|
||||
error = landlock_add_rule(ll_ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
|
||||
&target, 0);
|
||||
if (error) {
|
||||
fprintf(stderr, "Error: %s: failed to add Landlock rule for %s: %s\n",
|
||||
__func__, allowed_path, strerror(errno));
|
||||
}
|
||||
close(allowed_fd);
|
||||
return error;
|
||||
}
|
||||
|
||||
int ll_special(const char *allowed_path) {
|
||||
if (ll_ruleset_fd == -1)
|
||||
ll_ruleset_fd = ll_create_full_ruleset();
|
||||
|
||||
int error;
|
||||
int allowed_fd = open(allowed_path, O_PATH | O_CLOEXEC);
|
||||
if (allowed_fd < 0) {
|
||||
if (arg_debug) {
|
||||
fprintf(stderr, "%s: failed to open %s: %s\n",
|
||||
__func__, allowed_path, strerror(errno));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
struct landlock_path_beneath_attr target;
|
||||
target.parent_fd = allowed_fd;
|
||||
target.allowed_access =
|
||||
LANDLOCK_ACCESS_FS_MAKE_BLOCK |
|
||||
LANDLOCK_ACCESS_FS_MAKE_CHAR |
|
||||
LANDLOCK_ACCESS_FS_MAKE_FIFO |
|
||||
LANDLOCK_ACCESS_FS_MAKE_SOCK;
|
||||
|
||||
error = landlock_add_rule(ll_ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
|
||||
&target, 0);
|
||||
if (error) {
|
||||
fprintf(stderr, "Error: %s: failed to add Landlock rule for %s: %s\n",
|
||||
__func__, allowed_path, strerror(errno));
|
||||
}
|
||||
close(allowed_fd);
|
||||
return error;
|
||||
}
|
||||
|
||||
int ll_exec(const char *allowed_path) {
|
||||
if (ll_ruleset_fd == -1)
|
||||
ll_ruleset_fd = ll_create_full_ruleset();
|
||||
|
||||
int error;
|
||||
int allowed_fd = open(allowed_path, O_PATH | O_CLOEXEC);
|
||||
if (allowed_fd < 0) {
|
||||
if (arg_debug) {
|
||||
fprintf(stderr, "%s: failed to open %s: %s\n",
|
||||
__func__, allowed_path, strerror(errno));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
struct landlock_path_beneath_attr target;
|
||||
target.parent_fd = allowed_fd;
|
||||
target.allowed_access =
|
||||
LANDLOCK_ACCESS_FS_EXECUTE;
|
||||
|
||||
error = landlock_add_rule(ll_ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
|
||||
&target, 0);
|
||||
if (error) {
|
||||
fprintf(stderr, "Error: %s: failed to add Landlock rule for %s: %s\n",
|
||||
__func__, allowed_path, strerror(errno));
|
||||
}
|
||||
close(allowed_fd);
|
||||
return error;
|
||||
}
|
||||
|
||||
int ll_basic_system(void) {
|
||||
assert(cfg.homedir);
|
||||
|
||||
if (ll_ruleset_fd == -1)
|
||||
ll_ruleset_fd = ll_create_full_ruleset();
|
||||
|
||||
int error =
|
||||
ll_read("/bin/") ||
|
||||
ll_read("/dev/") ||
|
||||
ll_read("/etc/") ||
|
||||
ll_read("/lib/") ||
|
||||
ll_read("/opt/") ||
|
||||
ll_read("/usr/") ||
|
||||
ll_read("/var/") ||
|
||||
ll_read(cfg.homedir) ||
|
||||
|
||||
ll_write("/dev/") ||
|
||||
ll_write(cfg.homedir) ||
|
||||
|
||||
ll_exec("/bin/") ||
|
||||
ll_exec("/lib/") ||
|
||||
ll_exec("/opt/") ||
|
||||
ll_exec("/usr/");
|
||||
|
||||
if (error) {
|
||||
fprintf(stderr, "Error: %s: failed to set --landlock rules\n",
|
||||
__func__);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
int ll_restrict(__u32 flags) {
|
||||
if (ll_ruleset_fd == -1)
|
||||
return 0;
|
||||
|
||||
int error;
|
||||
error = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
|
||||
if (error) {
|
||||
fprintf(stderr, "Error: %s: failed to restrict privileges: %s\n",
|
||||
__func__, strerror(errno));
|
||||
goto out;
|
||||
}
|
||||
error = landlock_restrict_self(ll_ruleset_fd, flags);
|
||||
if (error) {
|
||||
fprintf(stderr, "Error: %s: failed to enforce Landlock: %s\n",
|
||||
__func__, strerror(errno));
|
||||
goto out;
|
||||
}
|
||||
if (arg_debug)
|
||||
printf("%s: Enforcing Landlock\n", __func__);
|
||||
out:
|
||||
close(ll_ruleset_fd);
|
||||
return error;
|
||||
}
|
||||
|
||||
#endif /* HAVE_LANDLOCK */
|
||||
|
|
@ -75,6 +75,9 @@ int arg_overlay = 0; // overlay option
|
|||
int arg_overlay_keep = 0; // place overlay diff in a known directory
|
||||
int arg_overlay_reuse = 0; // allow the reuse of overlays
|
||||
|
||||
int arg_landlock = 0; // add basic Landlock rules
|
||||
int arg_landlock_proc = 2; // 0 - no access; 1 -read-only; 2 - read-write
|
||||
|
||||
int arg_seccomp = 0; // enable default seccomp filter
|
||||
int arg_seccomp32 = 0; // enable default seccomp filter for 32 bit arch
|
||||
int arg_seccomp_postexec = 0; // need postexec ld.preload library?
|
||||
|
|
@ -1500,6 +1503,31 @@ int main(int argc, char **argv, char **envp) {
|
|||
else
|
||||
exit_err_feature("seccomp");
|
||||
}
|
||||
#ifdef HAVE_LANDLOCK
|
||||
else if (strcmp(argv[i], "--landlock") == 0)
|
||||
arg_landlock = 1;
|
||||
else if (strncmp(argv[i], "--landlock.proc=", 16) == 0) {
|
||||
if (strncmp(argv[i] + 16, "no", 2) == 0)
|
||||
arg_landlock_proc = 0;
|
||||
else if (strncmp(argv[i] + 16, "ro", 2) == 0)
|
||||
arg_landlock_proc = 1;
|
||||
else if (strncmp(argv[i] + 16, "rw", 2) == 0)
|
||||
arg_landlock_proc = 2;
|
||||
else {
|
||||
fprintf(stderr, "Error: invalid landlock.proc value: %s\n",
|
||||
argv[i] + 16);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else if (strncmp(argv[i], "--landlock.read=", 16) == 0)
|
||||
ll_read(argv[i] + 16);
|
||||
else if (strncmp(argv[i], "--landlock.write=", 17) == 0)
|
||||
ll_write(argv[i] + 17);
|
||||
else if (strncmp(argv[i], "--landlock.special=", 19) == 0)
|
||||
ll_special(argv[i] + 19);
|
||||
else if (strncmp(argv[i], "--landlock.execute=", 19) == 0)
|
||||
ll_exec(argv[i] + 19);
|
||||
#endif
|
||||
else if (strcmp(argv[i], "--memory-deny-write-execute") == 0) {
|
||||
if (checkcfg(CFG_SECCOMP))
|
||||
arg_memory_deny_write_execute = 1;
|
||||
|
|
|
|||
|
|
@ -1077,6 +1077,44 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LANDLOCK
|
||||
// Landlock ruleset paths
|
||||
if (strcmp(ptr, "landlock") == 0) {
|
||||
arg_landlock = 1;
|
||||
return 0;
|
||||
}
|
||||
if (strncmp(ptr, "landlock.proc ", 14) == 0) {
|
||||
if (strncmp(ptr + 14, "no", 2) == 0)
|
||||
arg_landlock_proc = 0;
|
||||
else if (strncmp(ptr + 14, "ro", 2) == 0)
|
||||
arg_landlock_proc = 1;
|
||||
else if (strncmp(ptr + 14, "rw", 2) == 0)
|
||||
arg_landlock_proc = 2;
|
||||
else {
|
||||
fprintf(stderr, "Error: invalid landlock.proc value: %s\n",
|
||||
ptr + 14);
|
||||
exit(1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (strncmp(ptr, "landlock.read ", 14) == 0) {
|
||||
ll_read(ptr + 14);
|
||||
return 0;
|
||||
}
|
||||
if (strncmp(ptr, "landlock.write ", 15) == 0) {
|
||||
ll_write(ptr + 15);
|
||||
return 0;
|
||||
}
|
||||
if (strncmp(ptr, "landlock.special ", 17) == 0) {
|
||||
ll_special(ptr + 17);
|
||||
return 0;
|
||||
}
|
||||
if (strncmp(ptr, "landlock.execute ", 17) == 0) {
|
||||
ll_exec(ptr + 17);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
// memory deny write&execute
|
||||
if (strcmp(ptr, "memory-deny-write-execute") == 0) {
|
||||
if (checkcfg(CFG_SECCOMP))
|
||||
|
|
|
|||
|
|
@ -516,6 +516,28 @@ void start_application(int no_sandbox, int fd, char *set_sandbox_status) {
|
|||
printf("LD_PRELOAD=%s\n", getenv("LD_PRELOAD"));
|
||||
}
|
||||
|
||||
#ifdef HAVE_LANDLOCK
|
||||
//****************************
|
||||
// Configure Landlock
|
||||
//****************************
|
||||
if (arg_landlock)
|
||||
ll_basic_system();
|
||||
|
||||
if (ll_get_fd() != -1) {
|
||||
if (arg_landlock_proc >= 1)
|
||||
ll_read("/proc/");
|
||||
if (arg_landlock_proc == 2)
|
||||
ll_write("/proc/");
|
||||
}
|
||||
|
||||
if (ll_restrict(0)) {
|
||||
// It isn't safe to continue if Landlock self-restriction was
|
||||
// enabled and the "landlock_restrict_self" syscall has failed.
|
||||
fprintf(stderr, "Error: ll_restrict() failed, exiting...\n");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (just_run_the_shell) {
|
||||
char *arg[2];
|
||||
arg[0] = cfg.usershell;
|
||||
|
|
|
|||
|
|
@ -133,6 +133,14 @@ static const char *const usage_str =
|
|||
" --keep-fd - inherit open file descriptors to sandbox.\n"
|
||||
" --keep-shell-rc - do not copy shell rc files from /etc/skel\n"
|
||||
" --keep-var-tmp - /var/tmp directory is untouched.\n"
|
||||
#ifdef HAVE_LANDLOCK
|
||||
" --landlock - add basic rules to the Landlock ruleset.\n"
|
||||
" --landlock.proc=no|ro|rw - add an access rule for /proc to the Landlock ruleset.\n"
|
||||
" --landlock.read=path - add a read access rule for the path to the Landlock ruleset.\n"
|
||||
" --landlock.write=path - add a write access rule for the path to the Landlock ruleset.\n"
|
||||
" --landlock.special=path - add an access rule for the path to the Landlock ruleset for creating block/char devices, named pipes and sockets.\n"
|
||||
" --landlock.execute=path - add an execute access rule for the path to the Landlock ruleset.\n"
|
||||
#endif
|
||||
" --list - list all sandboxes.\n"
|
||||
#ifdef HAVE_FILE_TRANSFER
|
||||
" --ls=name|pid dir_or_filename - list files in sandbox container.\n"
|
||||
|
|
|
|||
|
|
@ -1338,6 +1338,13 @@ void close_all(int *keep_list, size_t sz) {
|
|||
if (keep)
|
||||
continue;
|
||||
|
||||
#ifdef HAVE_LANDLOCK
|
||||
// Don't close the file descriptor of the Landlock ruleset; it
|
||||
// will be automatically closed by the "ll_restrict" wrapper
|
||||
// function.
|
||||
if (fd == ll_get_fd())
|
||||
continue;
|
||||
#endif
|
||||
close(fd);
|
||||
}
|
||||
closedir(dir);
|
||||
|
|
|
|||
|
|
@ -507,6 +507,37 @@ Blacklist all Linux capabilities.
|
|||
.TP
|
||||
\fBcaps.keep capability,capability,capability
|
||||
Whitelist given Linux capabilities.
|
||||
#ifdef HAVE_LANDLOCK
|
||||
.TP
|
||||
\fBlandlock
|
||||
Create a Landlock ruleset (if it doesn't already exist) and add basic access
|
||||
rules to it.
|
||||
.TP
|
||||
\fBlandlock.proc no|ro|rw
|
||||
Add an access rule for /proc directory (read-only if set to \fBro\fR and
|
||||
read-write if set to \fBrw\fR).
|
||||
The access rule for /proc is added after this directory is set up in the
|
||||
sandbox.
|
||||
Access rules for /proc set up with other Landlock-related profile options have
|
||||
no effect.
|
||||
.TP
|
||||
\fBlandlock.read path
|
||||
Create a Landlock ruleset (if it doesn't already exist) and add a read access
|
||||
rule for path.
|
||||
.TP
|
||||
\fBlandlock.write path
|
||||
Create a Landlock ruleset (if it doesn't already exist) and add a write access
|
||||
rule for path.
|
||||
.TP
|
||||
\fBlandlock.special path
|
||||
Create a Landlock ruleset (if it doesn't already exist) and add a rule that
|
||||
allows the creation of block devices, character devices, named pipes (FIFOs)
|
||||
and Unix domain sockets beneath given path.
|
||||
.TP
|
||||
\fBlandlock.execute path
|
||||
Create a Landlock ruleset (if it doesn't already exist) and add an execution
|
||||
permission rule for path.
|
||||
#endif
|
||||
.TP
|
||||
\fBmemory-deny-write-execute
|
||||
Install a seccomp filter to block attempts to create memory mappings
|
||||
|
|
|
|||
|
|
@ -1243,6 +1243,52 @@ Example:
|
|||
.br
|
||||
$ firejail --keep-var-tmp
|
||||
|
||||
#ifdef HAVE_LANDLOCK
|
||||
.TP
|
||||
\fB\-\-landlock
|
||||
Create a Landlock ruleset (if it doesn't already exist) and add basic access
|
||||
rules to it.
|
||||
The basic set of rules applies the following access permissions:
|
||||
.PP
|
||||
.RS
|
||||
- read: /bin, /dev, /etc, /lib, /opt, /proc, /usr, /var
|
||||
.br
|
||||
- write: /dev, /proc
|
||||
.br
|
||||
- exec: /bin, /lib, /opt, /usr
|
||||
.RE
|
||||
.PP
|
||||
See the \fBLANDLOCK\fR section for more information.
|
||||
.TP
|
||||
\fB\-\-landlock.proc=no|ro|rw
|
||||
Add an access rule for /proc directory (read-only if set to \fBro\fR and
|
||||
read-write if set to \fBrw\fR).
|
||||
The access rule for /proc is added after this directory is set up in the
|
||||
sandbox.
|
||||
Access rules for /proc set up with other Landlock-related command-line options
|
||||
have no effect.
|
||||
.TP
|
||||
\fB\-\-landlock.read=path
|
||||
Create a Landlock ruleset (if it doesn't already exist) and add a read access
|
||||
rule for path.
|
||||
.TP
|
||||
\fB\-\-landlock.write=path
|
||||
Create a Landlock ruleset (if it doesn't already exist) and add a write access
|
||||
rule for path.
|
||||
.TP
|
||||
\fB\-\-landlock.special=path
|
||||
Create a Landlock ruleset (if it doesn't already exist) and add a rule that
|
||||
allows the creation of block devices, character devices, named pipes (FIFOs)
|
||||
and Unix domain sockets beneath given path.
|
||||
.TP
|
||||
\fB\-\-landlock.execute=path
|
||||
Create a Landlock ruleset (if it doesn't already exist) and add an execution
|
||||
permission rule for path.
|
||||
.PP
|
||||
Example:
|
||||
.PP
|
||||
$ firejail \-\-landlock.read=/ \-\-landlock.write=/home \-\-landlock.execute=/usr
|
||||
#endif
|
||||
.TP
|
||||
\fB\-\-list
|
||||
List all sandboxes, see \fBMONITORING\fR section for more details.
|
||||
|
|
@ -3365,6 +3411,47 @@ To enable AppArmor confinement on top of your current Firejail security features
|
|||
$ firejail --apparmor firefox
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LANDLOCK
|
||||
.SH LANDLOCK
|
||||
Landlock is a Linux security module first introduced in version 5.13 of the
|
||||
Linux kernel.
|
||||
It allows unprivileged processes to restrict their access to the filesystem.
|
||||
Once imposed, these restrictions can never be removed, and all child processes
|
||||
created by a Landlock-restricted processes inherit these restrictions.
|
||||
Firejail supports Landlock as an additional sandboxing feature.
|
||||
It can be used to ensure that a sandboxed application can only access files and
|
||||
directories that it was explicitly allowed to access.
|
||||
Firejail supports populating the ruleset with both a basic set of rules (see
|
||||
\fB\-\-landlock\fR) and with a custom set of rules.
|
||||
.TP
|
||||
Important notes:
|
||||
.PP
|
||||
.RS
|
||||
- A process can install a Landlock ruleset only if it has either
|
||||
\fBCAP_SYS_ADMIN\fR in its effective capability set, or the "No New
|
||||
Privileges" restriction enabled.
|
||||
Because of this, enabling the Landlock feature will also cause Firejail to
|
||||
enable the "No New Privileges" restriction, regardless of the profile or the
|
||||
\fB\-\-no\-new\-privs\fR command line option.
|
||||
.PP
|
||||
- Access to the /proc directory is managed through the \fB\-\-landlock.proc\fR
|
||||
command line option.
|
||||
.PP
|
||||
- Access to the /etc directory is automatically allowed.
|
||||
To override this, use the \fB\-\-writable\-etc\fR command line option.
|
||||
You can also use the \fB\-\-private\-etc\fR option to restrict access to the
|
||||
/etc directory.
|
||||
.RE
|
||||
.PP
|
||||
To enable Landlock self-restriction on top of your current Firejail security
|
||||
features, pass \fB\-\-landlock\fR flag to Firejail command line.
|
||||
You can also use \fB\-\-landlock.read\fR, \fB\-\-landlock.write\fR,
|
||||
\fB\-\-landlock.special\fR and \fB\-\-landlock.execute\fR options together with
|
||||
\fB\-\-landlock\fR or instead of it.
|
||||
Example:
|
||||
.PP
|
||||
$ firejail \-\-landlock \-\-landlock.read=/media \-\-landlock.proc=ro mc
|
||||
#endif
|
||||
.SH DESKTOP INTEGRATION
|
||||
A symbolic link to /usr/bin/firejail under the name of a program, will start the program in Firejail sandbox.
|
||||
The symbolic link should be placed in the first $PATH position. On most systems, a good place
|
||||
|
|
|
|||
|
|
@ -106,6 +106,11 @@ _firejail_args=(
|
|||
'--keep-fd[inherit open file descriptors to sandbox]: :'
|
||||
'--keep-shell-rc[do not copy shell rc files from /etc/skel]'
|
||||
'--keep-var-tmp[/var/tmp directory is untouched]'
|
||||
'--landlock.proc=-[add an access rule for /proc to the Landlock ruleset]: :(no ro rw)'
|
||||
'--landlock.read=-[add a read access rule for the path to the Landlock ruleset]: :_files'
|
||||
'--landlock.write=-[add a write access rule for the path to the Landlock ruleset]: :_files'
|
||||
'--landlock.special=-[add an access rule for the path to the Landlock ruleset for creating block/char devices, named pipes and sockets]: :_files'
|
||||
'--landlock.execute=-[add an execute access rule for the path to the Landlock ruleset]: :_files'
|
||||
'--machine-id[spoof /etc/machine-id with a random id]'
|
||||
'--memory-deny-write-execute[seccomp filter to block attempts to create memory mappings that are both writable and executable]'
|
||||
'*--mkdir=-[create a directory]:'
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue