Skip to content

Commit

Permalink
Improve BT functionality and hardening
Browse files Browse the repository at this point in the history
- change 'mutableUsers' to false (system-wide)
- add bluetooth system user/group (requires immutability)
- enable hardened systemd configs in audiovm
- add hardened systemd config + dbus policy
- add persistence to save bt device configs
- add uinput kernel module + udev rules
- change control socket in launcher

Signed-off-by: Manuel Bluhm <manuel@ssrc.tii.ae>
  • Loading branch information
mbssrc authored and brianmcgillion committed Sep 20, 2024
1 parent 6ce095f commit 67edf00
Show file tree
Hide file tree
Showing 8 changed files with 164 additions and 32 deletions.
74 changes: 57 additions & 17 deletions modules/common/services/bluetooth.nix
Original file line number Diff line number Diff line change
@@ -1,36 +1,76 @@
# Copyright 2022-2024 TII (SSRC) and the Ghaf contributors
# SPDX-License-Identifier: Apache-2.0
{ config, lib, ... }:
{
config,
lib,
pkgs,
...
}:
let
cfg = config.ghaf.services.bluetooth;
inherit (lib) mkIf mkEnableOption;
bluetoothUser = "bluetooth";
in
{
options.ghaf.services.bluetooth = {
enable = mkEnableOption "Bluetooth configurations";
};
config = mkIf cfg.enable {

# Enable bluetooth
hardware.bluetooth = {
enable = true;
};

# Polkit rules for blueman
ghaf.systemd.withPolkit = true;
security.polkit = {
enable = true;
extraConfig = ''
polkit.addRule(function(action, subject) {
if ((action.id == "org.blueman.network.setup" ||
action.id == "org.blueman.dhcp.client" ||
action.id == "org.blueman.rfkill.setstate" ||
action.id == "org.blueman.pppd.pppconnect") &&
subject.user == "ghaf") {
return polkit.Result.YES;
}
});
'';
# Setup bluetooth user and group
users = {
users."${bluetoothUser}" = {
isSystemUser = true;
group = "${bluetoothUser}";
};
groups."${bluetoothUser}" = { };
};

systemd.tmpfiles.rules = [ "f /var/lib/systemd/linger/${config.ghaf.users.accounts.user}" ];
# Uinput kernel module
boot.kernelModules = [ "uinput" ];

# Rfkill udev rule
services.udev.extraRules = ''
KERNEL=="rfkill", SUBSYSTEM=="misc", GROUP="${bluetoothUser}"
KERNEL=="uinput", SUBSYSTEM=="misc", GROUP="${bluetoothUser}"
'';

# Dbus policy updates
services.dbus.packages = [
(pkgs.writeTextFile {
name = "bluez-dbus-policy";
text = ''
<!DOCTYPE busconfig PUBLIC
"-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
<policy user="${bluetoothUser}">
<allow own="org.bluez"/>
<allow send_destination="org.bluez.*"/>
<allow send_interface="org.bluez.*"/>
<allow send_type="method_call"/>
<allow send_interface="org.freedesktop.DBus.Introspectable"/>
<allow send_interface="org.freedesktop.DBus.Properties"/>
<allow send_interface="org.freedesktop.DBus.ObjectManager"/>
</policy>
<policy user="pipewire">
<allow send_destination="org.bluez"/>
</policy>
</busconfig>
'';
destination = "/share/dbus-1/system.d/bluez.conf";
})
];

# Configure bluetooth service
systemd.services.bluetooth.serviceConfig = {
User = "${bluetoothUser}";
Group = "${bluetoothUser}";
};
};
}
80 changes: 80 additions & 0 deletions modules/common/systemd/hardened-configs/common/bluetooth.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# Copyright 2022-2024 TII (SSRC) and the Ghaf contributors
# SPDX-License-Identifier: Apache-2.0
{
ProtectProc = "noaccess";
ProcSubset = "pid";
ProtectHome = true;
ProtectSystem = "full";
PrivateTmp = true;
PrivateMounts = true;
UMask = 77;
ProtectKernelTunables = true;
ProtectKernelModules = true;
ProtectKernelLogs = true;
KeyringMode = "private";
ProtectHostname = true;
ProtectClock = true;
ProtectControlGroups = true;
RestrictRealtime = true;
RemoveIPC = true;
NotifyAccess = "all";
NoNewPrivileges = true;
RestrictSUIDSGID = true;
LockPersonality = true;
MemoryDenyWriteExecute = true;
IPAddressDeny = "any";
RestrictAddressFamilies = [
"AF_BLUETOOTH"
"AF_ALG"
"AF_UNIX"
];
ReadWritePaths = [ "/var/lib/bluetooth" ];
DeviceAllow = [
"/dev/rfkill"
"/dev/uinput"
];
RestrictNamespaces = [
"~user"
"~pid"
"~net"
"~uts"
"~mnt"
"~cgroup"
"~ipc"
];
AmbientCapabilities = [
"CAP_NET_BIND_SERVICE"
"CAP_NET_ADMIN"
"CAP_NET_RAW"
"CAP_SYS_RESOURCE"
"CAP_AUDIT_WRITE"
];
CapabilityBoundingSet = [
"CAP_NET_BIND_SERVICE"
"CAP_NET_ADMIN"
"CAP_NET_RAW"
"CAP_SYS_RESOURCE"
"CAP_AUDIT_WRITE"
];
SystemCallArchitectures = "native";
SystemCallFilter = [
"~@swap"
"~@timer"
"~@pkey"
"~@debug"
"~@cpu_emulation"
"~@mount"
"~@ipc"
"~@resources"
"~@memlock"
"~@keyring"
"~@raw_io"
"~@clock"
"~@aio"
"~@setuid"
"~@module"
"~@reboot"
"~@sandbox"
"~@chown"
];
}
3 changes: 2 additions & 1 deletion modules/common/users/accounts.nix
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ in

config = mkIf cfg.enable {
users = {
mutableUsers = true;
mutableUsers = false;
users."${cfg.user}" = {
isNormalUser = true;
inherit (cfg) password;
Expand All @@ -50,6 +50,7 @@ in
members = [ cfg.user ];
};
};

# to build ghaf as ghaf-user with caches
nix.settings.trusted-users = mkIf config.ghaf.profiles.debug.enable [ cfg.user ];
};
Expand Down
15 changes: 15 additions & 0 deletions modules/microvm/virtualization/microvm/audiovm.nix
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ let
audiovmBaseConfiguration = {
imports = [
inputs.self.nixosModules.givc-audiovm
inputs.impermanence.nixosModules.impermanence
(import ./common/vm-networking.nix {
inherit
config
Expand All @@ -30,6 +31,7 @@ let
;
internalIP = 5;
})
./common/storagevm.nix
(
{ lib, pkgs, ... }:
{
Expand All @@ -52,9 +54,22 @@ let
withResolved = true;
withTimesyncd = true;
withDebug = configHost.ghaf.profiles.debug.enable;
withHardenedConfigs = true;
};
givc.audiovm.enable = true;
services.audio.enable = true;
storagevm = {
enable = true;
name = "audiovm";
directories = [
{
directory = "/var/lib/bluetooth";
user = "bluetooth";
group = "bluetooth";
mode = "u=rwx,g=,o=";
}
];
};
};

environment = {
Expand Down
9 changes: 3 additions & 6 deletions modules/reference/appvms/business.nix
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,10 @@ in
hardware.pulseaudio = {
enable = true;
extraConfig = ''
load-module module-tunnel-sink sink_name=chromium-speaker server=audio-vm:4713 format=s16le channels=2 rate=48000
load-module module-tunnel-source source_name=chromium-mic server=audio-vm:4713 format=s16le channels=1 rate=48000
# Set sink and source default max volume to about 90% (0-65536)
set-sink-volume chromium-speaker 60000
set-source-volume chromium-mic 60000
load-module module-tunnel-sink-new sink_name=business-speaker server=audio-vm:4713 reconnect_interval_ms=1000
load-module module-tunnel-source-new source_name=business-mic server=audio-vm:4713 reconnect_interval_ms=1000
'';
package = pkgs.pulseaudio-ghaf;
};

time.timeZone = config.time.timeZone;
Expand Down
9 changes: 3 additions & 6 deletions modules/reference/appvms/comms.nix
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,10 @@ in
hardware.pulseaudio = {
enable = true;
extraConfig = ''
load-module module-tunnel-sink sink_name=element-speaker server=audio-vm:4713 format=s16le channels=2 rate=48000
load-module module-tunnel-source source_name=element-mic server=audio-vm:4713 format=s16le channels=1 rate=48000
# Set sink and source default max volume to about 90% (0-65536)
set-sink-volume element-speaker 60000
set-source-volume element-mic 60000
load-module module-tunnel-sink-new sink_name=comms-speaker server=audio-vm:4713 reconnect_interval_ms=1000
load-module module-tunnel-source-new source_name=comms-mic server=audio-vm:4713 reconnect_interval_ms=1000
'';
package = pkgs.pulseaudio-ghaf;
};

systemd = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# Copyright 2022-2024 TII (SSRC) and the Ghaf contributors
# SPDX-License-Identifier: Apache-2.0
diff --git a/src/modules/module-tunnel-sink-new.c b/src/modules/module-tunnel-sink-new.c
index 0b91ce266..ea41c50e2 100644
--- a/src/modules/module-tunnel-sink-new.c
Expand Down
4 changes: 2 additions & 2 deletions packages/bt-launcher/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ writeShellApplication {
export PULSE_SERVER=audio-vm:4713
export DBUS_SESSION_BUS_ADDRESS=unix:path=/tmp/ssh_session_dbus.sock
export DBUS_SYSTEM_BUS_ADDRESS=unix:path=/tmp/ssh_system_dbus.sock
${openssh}/bin/ssh -M -S /tmp/control_socket \
${openssh}/bin/ssh -M -S /tmp/control_socket_bt \
-f -N -q ghaf@audio-vm \
-i /run/waypipe-ssh/id_ed25519 \
-o StrictHostKeyChecking=no \
Expand All @@ -26,7 +26,7 @@ writeShellApplication {
${blueman}/bin/blueman-applet &
${blueman}/bin/blueman-manager
# Use the control socket to close the ssh tunnel.
${openssh}/bin/ssh -q -S /tmp/control_socket -O exit ghaf@audio-vm
${openssh}/bin/ssh -q -S /tmp/control_socket_bt -O exit ghaf@audio-vm
'';

meta = {
Expand Down

0 comments on commit 67edf00

Please sign in to comment.