Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add initial selinux implementation #683

Merged
merged 11 commits into from
Feb 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,9 @@ Only a few locations are made writable:
* some through [tmpfs mounts](workspaces/preinit/laika), used for configuration, that don't persist over a restart.
* one [persistent location](packages/release/var-lib-bottlerocket.mount) for the data store.

We enable [SELinux](https://selinuxproject.org/) in enforcing mode.
This protects the data store from tampering, and blocks modification of sensitive files such as container archives.

Almost all first-party components are written in [Rust](https://www.rust-lang.org/).
Rust eliminates some classes of memory safety issues, and encourages design patterns that help security.

Expand Down
4 changes: 4 additions & 0 deletions packages/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ members = [
"readline",
"release",
"runc",
"selinux-policy",
"socat",
"strace",
"systemd",
Expand Down
7 changes: 3 additions & 4 deletions packages/containerd/containerd-config-toml_aws-dev
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@ version = 2
root = "/var/lib/containerd"
state = "/run/containerd"
disabled_plugins = [
"io.containerd.internal.v1.opt",
"io.containerd.snapshotter.v1.aufs",
"io.containerd.snapshotter.v1.zfs",
"io.containerd.snapshotter.v1.devmapper",
"io.containerd.snapshotter.v1.native",
"io.containerd.snapshotter.v1.zfs",
"io.containerd.grpc.v1.cri",
]

[grpc]
address = "/run/containerd/containerd.sock"

[plugins."io.containerd.internal.v1.opt"]
path = "/opt/containerd"
8 changes: 4 additions & 4 deletions packages/containerd/containerd-config-toml_aws-k8s
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,18 @@ version = 2
root = "/var/lib/containerd"
state = "/run/containerd"
disabled_plugins = [
"io.containerd.internal.v1.opt",
"io.containerd.snapshotter.v1.aufs",
"io.containerd.snapshotter.v1.zfs",
"io.containerd.snapshotter.v1.devmapper",
"io.containerd.snapshotter.v1.native",
"io.containerd.snapshotter.v1.zfs",
]

[grpc]
address = "/run/containerd/containerd.sock"

[plugins."io.containerd.grpc.v1.cri"]
enable_selinux = true
# Pause container image is specified here, shares the same image as kubelet's pod-infra-container-image
sandbox_image = "{{settings.kubernetes.pod-infra-container-image}}"

Expand All @@ -26,6 +29,3 @@ SystemdCgroup = true
[plugins."io.containerd.grpc.v1.cri".cni]
bin_dir = "/opt/cni/bin"
conf_dir = "/etc/cni/net.d"

[plugins."io.containerd.internal.v1.opt"]
path = "/opt/containerd"
7 changes: 3 additions & 4 deletions packages/host-ctr/host-containerd-config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@ version = 2
root = "/var/lib/host-containerd"
state = "/run/host-containerd"
disabled_plugins = [
"io.containerd.internal.v1.opt",
"io.containerd.snapshotter.v1.aufs",
"io.containerd.snapshotter.v1.zfs",
"io.containerd.snapshotter.v1.devmapper",
"io.containerd.snapshotter.v1.native",
"io.containerd.snapshotter.v1.zfs",
"io.containerd.grpc.v1.cri",
]

[grpc]
address = "/run/host-containerd/containerd.sock"

[plugins."io.containerd.internal.v1.opt"]
path = "/opt/host-containerd"
9 changes: 9 additions & 0 deletions packages/kernel/config-bottlerocket
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,15 @@ CONFIG_DM_VERITY=y
# yama LSM for ptrace restrictions
CONFIG_SECURITY_YAMA=y

# Do not allow SELinux to be disabled at boot.
CONFIG_SECURITY_SELINUX_BOOTPARAM=n

# Do not allow SELinux to be disabled at runtime.
CONFIG_SECURITY_SELINUX_DISABLE=n

# Do not allow SELinux to use `enforcing=0` behavior.
CONFIG_SECURITY_SELINUX_DEVELOP=n

# enable /proc/config.gz
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
Expand Down
1 change: 1 addition & 0 deletions packages/libselinux/libselinux-tmpfiles.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
L /etc/selinux - - - - /usr/lib/selinux
5 changes: 5 additions & 0 deletions packages/libselinux/libselinux.spec
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Summary: Library for SELinux
License: LicenseRef-SELinux-PD
URL: https://github.com/SELinuxProject/
Source0: https://github.com/SELinuxProject/selinux/releases/download/20191204/libselinux-%{version}.tar.gz
Source1: libselinux-tmpfiles.conf
Patch1: 0001-adjust-default-selinux-directory.patch
BuildRequires: %{_cross_os}glibc-devel
BuildRequires: %{_cross_os}libpcre-devel
Expand Down Expand Up @@ -44,10 +45,14 @@ export USE_PCRE2='y' \\\
%set_env
%make_install

install -d %{buildroot}%{_cross_tmpfilesdir}
install -p -m 0644 %{S:1} %{buildroot}%{_cross_tmpfilesdir}/libselinux.conf

%files
%license LICENSE
%{_cross_attribution_file}
%{_cross_libdir}/*.so.*
%{_cross_tmpfilesdir}/libselinux.conf
%exclude %{_cross_sbindir}
%exclude %{_cross_mandir}

Expand Down
5 changes: 4 additions & 1 deletion packages/release/prepare-local.service
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ After=dev-disk-by\x2dpartlabel-BOTTLEROCKET\x2dDATA.device
Type=oneshot
Environment=BOTTLEROCKET_DATA=/dev/disk/by-partlabel/BOTTLEROCKET-DATA
Environment=LOCAL_DIR=/local
Environment=CONTEXT="system_u:object_r:local_t:s0"

# To "grow" the partition, we delete it and recreate it at the larger size, which
# causes the udev links to be deleted and then recreated. We have to wait for the
Expand All @@ -28,7 +29,9 @@ ExecStart=/usr/bin/udevadm settle -E ${BOTTLEROCKET_DATA}
# The above note means we can't have a "normal" mount unit here, because it would
# depend on the link, and would immediately transition to the failed state when the
# link is removed. systemd will create local.mount for us as a side effect.
ExecStart=/usr/bin/mount -o defaults,noatime,nosuid,nodev ${BOTTLEROCKET_DATA} ${LOCAL_DIR}
ExecStart=/usr/bin/mount \
-o defaults,noatime,nosuid,nodev,fscontext="${CONTEXT}",defcontext="${CONTEXT}",rootcontext="${CONTEXT}" \
${BOTTLEROCKET_DATA} ${LOCAL_DIR}

# After the mount is active, we grow the filesystem to fill the resized partition,
# and ensure that it has the directories we need for subsequent mounts.
Expand Down
1 change: 1 addition & 0 deletions packages/release/release.spec
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ Requires: %{_cross_os}bork
Requires: %{_cross_os}moondog
Requires: %{_cross_os}schnauzer
Requires: %{_cross_os}netdog
Requires: %{_cross_os}selinux-policy
Requires: %{_cross_os}signpost
Requires: %{_cross_os}sundog
Requires: %{_cross_os}pluto
Expand Down
2 changes: 1 addition & 1 deletion packages/release/usr-share-licenses.mount.in
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Before=local-fs.target umount.target
What=PREFIX/share/bottlerocket/licenses.squashfs
Where=PREFIX/share/licenses
Type=squashfs
Options=defaults,ro,loop
Options=defaults,ro,loop,noatime,nosuid,nodev,context=system_u:object_r:os_t:s0

[Install]
WantedBy=local-fs.target
2 changes: 1 addition & 1 deletion packages/release/usr-src-kernels.mount.in
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Before=local-fs.target umount.target
What=PREFIX/share/bottlerocket/kernel-devel.squashfs
Where=PREFIX/src/kernels
Type=squashfs
Options=defaults,ro,loop
Options=defaults,ro,loop,noatime,nosuid,nodev,context=system_u:object_r:os_t:s0

[Install]
WantedBy=local-fs.target
2 changes: 1 addition & 1 deletion packages/release/var-lib-bottlerocket.mount
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Before=local-fs.target umount.target
What=/dev/disk/by-partlabel/BOTTLEROCKET-PRIVATE
Where=/var/lib/bottlerocket
Type=ext4
Options=defaults,noatime,nosuid,nodev
Options=defaults,noatime,nosuid,nodev,context=system_u:object_r:private_t:s0

[Install]
WantedBy=local-fs.target
9 changes: 9 additions & 0 deletions packages/selinux-policy/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[package]
name = "selinux-policy"
version = "0.1.0"
edition = "2018"
publish = false
build = "build.rs"

[lib]
path = "pkg.rs"
29 changes: 29 additions & 0 deletions packages/selinux-policy/base.cil
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
; Build an MLS policy. Ensures that we emit the sensitivity tag in
; file_contexts, which makes it compatible as input to `setfiles`.
(mls true)

; MLS has concepts of sensitivities and levels that we can ignore
; since we're not writing a true MLS policy. However, they are still
; required arguments in many places, so we need a minimal set.
(sensitivity s0)
(sensitivityorder (s0))
(sensitivitycategory s0 (range c0 c1023))

(level s0 (s0))
(levelrange s0 (s0 s0))

(level s0-s0 (s0 (range c0 c1023)))
(levelrange s0-s0 (s0 s0-s0))

; The system_r role is used for processes.
(role system_r)

; The object_r role is used for files.
(role object_r)

; Our system_u user has both roles.
(user system_u)
(userrole system_u system_r)
(userrole system_u object_r)
(userlevel system_u s0-s0)
(userrange system_u s0-s0)
9 changes: 9 additions & 0 deletions packages/selinux-policy/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
use std::process::{exit, Command};

fn main() -> Result<(), std::io::Error> {
let ret = Command::new("buildsys").arg("build-package").status()?;
if !ret.success() {
exit(1);
}
Ok(())
}
16 changes: 16 additions & 0 deletions packages/selinux-policy/catgen.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/bin/bash

# Docker uses MCS labels for container separation. It picks low and
# high numbers from the range of 1024 categories to create a unique
# label that does not dominate and is not dominated by other labels.
# For this to work, all categories must be included in the policy.

for i in {0..1023} ; do
echo "(category c${i})"
done

echo "(categoryorder ("
for i in {0..1023} ; do
echo -n " c${i}"
done
echo "))"
75 changes: 75 additions & 0 deletions packages/selinux-policy/fs.cil
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
; Label inodes by using xattrs for supported filesystems.
(fsuse xattr ext4 any)
(fsuse xattr overlay any)
(fsuse xattr xfs any)

; Label inodes by using the type of the creating task.
(fsuse task eventpollfs any)
(fsuse task pipefs any)
(fsuse task sockfs any)

; Label inodes by deriving a type from the creating task.
(fsuse trans devpts any)
(fsuse trans devtmpfs any)
(fsuse trans hugetlbfs any)
(fsuse trans mqueue any)
(fsuse trans shm any)
(fsuse trans tmpfs any)

; Specify a context for filesystems that do not support other ways to label.
(genfscon autofs / any)
(genfscon bdev / any)
(genfscon binfmt_misc / any)
(genfscon bpf / any)
(genfscon cgroup / any)
(genfscon cgroup2 / any)
(genfscon debugfs / any)
(genfscon kvmfs / any)
(genfscon nsfs / any)
(genfscon proc / any)
(genfscon pstore / any)
(genfscon ramfs / any)
(genfscon rootfs / any)
(genfscon securityfs / any)
(genfscon selinuxfs / any)
(genfscon sysfs / any)
(genfscon tracefs / any)

; Label most files.
(filecon "/.*" any os)

; Label entry points.
(filecon "/.*/usr/lib/systemd/systemd" file init_exec)
(filecon "/.*/usr/bin/containerd.*" file runtime_exec)
(filecon "/.*/usr/bin/docker.*" file runtime_exec)
(filecon "/.*/usr/sbin/runc" file runtime_exec)

; Label local storage mounts.
(filecon "/local" any local)
(filecon "/local/.*" any ())
(filecon "/opt" any local)
(filecon "/opt/.*" any ())
(filecon "/var" any local)
(filecon "/var/.*" any ())

; Label kernel filesystem mounts.
(filecon "/proc" any any)
(filecon "/proc/.*" any ())
(filecon "/sys" any any)
(filecon "/sys/.*" any ())
(filecon "/dev" any any)
(filecon "/dev/.*" any ())

; Label tmpfs mounts.
(filecon "/etc" any any)
(filecon "/etc/.*" any ())
(filecon "/tmp" any any)
(filecon "/tmp/.*" any ())
(filecon "/run" any any)
(filecon "/run/.*" any ())

; Label external filesystem mounts.
(filecon "/mnt" any external)
(filecon "/mnt/.*" any ())
(filecon "/media" any external)
(filecon "/media/.*" any ())
2 changes: 2 additions & 0 deletions packages/selinux-policy/lxc_contexts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
process = "system_u:system_r:container_t:s0"
file = "system_u:object_r:local_t:s0"
Loading