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

Hardware definition refactoring #541

Merged
merged 4 commits into from
May 9, 2024
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
4 changes: 2 additions & 2 deletions .reuse/dep5
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Source: https://github.com/tiiuae/ghaf

Copyright: 2022-2024 Technology Innovation Institute (TII) <https://github.com/tiiuae/ghaf>
License: Apache-2.0
Files:
Files:
*.lock *.png *.svg *.patch *.db *.key *.pem *.cer *.p12
modules/common/hardware/x86_64-generic/kernel/configs/ghaf_host_hardened_baseline-x86
modules/hardware/x86_64-generic/kernel/configs/ghaf_host_hardened_baseline-x86
modules/jetpack/ghaf_host_hardened_baseline-jetson-orin
10 changes: 5 additions & 5 deletions docs/src/architecture/hardening.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ NixOS provides several mechanisms to customize the kernel. The main methods are:

* [Declaring kernel command line parameters](https://nixos.wiki/wiki/Linux_kernel#Custom_kernel_commandline): [usage in Ghaf](https://github.com/search?q=repo%3Atiiuae%2Fghaf%20kernelparams&type=code).
* [Declaring kernel custom configuration](https://nixos.org/manual/nixos/stable/#sec-linux-config-customizing): [usage in Ghaf](https://github.com/tiiuae/ghaf/blob/main/modules/host/kernel.nix).

Example of entering the kernel development shell to customize the `.config` and build it:

```
~/ghaf $ nix develop .#devShells.x86_64-linux.kernel-x86
...
[ghaf-kernel-devshell:~/ghaf/linux-6.6.7]$ cp ../modules/common/hardware/x86_64-generic/kernel/configs/ghaf_host_hardened_baseline .config
[ghaf-kernel-devshell:~/ghaf/linux-6.6.7]$ cp ../modules/hardware/x86_64-generic/kernel/configs/ghaf_host_hardened_baseline .config
[ghaf-kernel-devshell:~/ghaf/linux-6.6.7]$ make menuconfig
...
[ghaf-kernel-devshell:~/ghaf/linux-6.6.7]$ make -j$(nproc)
Expand All @@ -42,8 +42,8 @@ NixOS provides several mechanisms to customize the kernel. The main methods are:
* [Validating with kernel hardening checker](https://github.com/a13xp0p0v/kernel-hardening-checker):

```
[ghaf-kernel-devshell:~/ghaf/linux-6.6.7]$ cp ../modules/common/hardware/x86_64-generic/kernel/configs/ghaf_host_hardened_baseline .config
[ghaf-kernel-devshell:~/ghaf/linux-6.6.7]$ HS=../modules/common/hardware/x86_64-generic/kernel/host/configs GS=../modules/common/hardware/x86_64-generic/kernel/guest/configs
[ghaf-kernel-devshell:~/ghaf/linux-6.6.7]$ cp ../modules/hardware/x86_64-generic/kernel/configs/ghaf_host_hardened_baseline .config
[ghaf-kernel-devshell:~/ghaf/linux-6.6.7]$ HS=../modules/hardware/x86_64-generic/kernel/host/configs GS=../modules/hardware/x86_64-generic/kernel/guest/configs
[ghaf-kernel-devshell:~/ghaf/linux-6.6.7]$ ./scripts/kconfig/merge_config.sh .config $HS/virtualization.config $HS/networking.config $HS/usb.config $HS/user-input-devices.config $HS/debug.config $GS/guest.config $GS/display-gpu.config
[ghaf-kernel-devshell:~/ghaf/linux-6.6.7]$ kernel-hardening-checker -c .config
[+] Kconfig file to check: .config
Expand Down Expand Up @@ -74,7 +74,7 @@ The host kernel runs on bare metal. The kernel is provided either with Linux ups
The host kernel hardening is based on Linux `make tinyconfig`. The
default `tinyconfig` fails to assertions on NixOS without
modifications. Assertions are fixed in the `ghaf_host_hardened_baseline` Linux configuration under Ghaf
`modules/common/hardware/x86_64-generic/kernel/configs`. Resulting baseline
`modules/hardware/x86_64-generic/kernel/configs`. Resulting baseline
kernel configuration is generic for x86_64 hardware architecture devices.

In addition, NixOS (Ghaf baseline dependency) requires several kernel modules that are added to the config or ignored with `allowMissing = true`. As of now, the kernel builds and early boots on Lenovo X1.
Expand Down
2 changes: 0 additions & 2 deletions modules/common/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,8 @@
./common.nix
./development
./firewall
./hardware
./profiles
./security
./tpm2
./users/accounts.nix
./version
./virtualization/docker.nix
Expand Down
52 changes: 0 additions & 52 deletions modules/common/hardware/lenovo-x1/definitions/default.nix

This file was deleted.

2 changes: 1 addition & 1 deletion modules/common/users/accounts.nix
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ in
extraGroups =
["wheel" "video" "networkmanager"]
++ optionals
config.ghaf.security.tpm2.enable ["tss"];
config.security.tpm2.enable ["tss"];
};
groups."${cfg.user}" = {
name = cfg.user;
Expand Down
1 change: 1 addition & 0 deletions modules/desktop/graphics/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@
./fonts.nix
./window-manager.nix
./boot.nix
./hardware.nix
];
}
51 changes: 51 additions & 0 deletions modules/desktop/graphics/hardware.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Copyright 2024 TII (SSRC) and the Ghaf contributors
# SPDX-License-Identifier: Apache-2.0
{lib, ...}:
with lib; let
pciDevSubmodule = types.submodule {
options = {
path = mkOption {
type = types.str;
description = ''
PCI device path
'';
};
vendorId = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
PCI Vendor ID (optional)
'';
};
productId = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
PCI Product ID (optional)
'';
};
name = mkOption {
type = types.nullOr types.str;
default = null;
description = ''
PCI device name (optional)
'';
};
};
};
in {
options.ghaf.graphics.hardware = {
networkDevices = mkOption {
description = "Network PCI Devices";
type = types.listOf pciDevSubmodule;
default = [];
example = literalExpression ''
[{
path = "0000:00:14.3";
vendorId = "8086";
productId = "51f1";
}]
'';
};
};
}
4 changes: 2 additions & 2 deletions modules/desktop/graphics/waybar.config.nix
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@
...
}: let
cfg = config.ghaf.graphics.labwc;
networkDevice = config.ghaf.hardware.definition.network.pciDevices;
inherit (config.ghaf.graphics.hardware) networkDevices;
inherit (import ../../../lib/icons.nix {inherit pkgs lib;}) svgToPNG;

launchpad-icon = svgToPNG "launchpad" ../../../assets/icons/svg/launchpad.svg "38x38";
admin-icon = svgToPNG "admin" ../../../assets/icons/svg/admin-cog.svg "24x24";
ghaf-icon = svgToPNG "ghaf-white" ../../../assets/icons/svg/ghaf-white.svg "24x24";

wifiDevice = lib.lists.findFirst (d: d.name != null) null networkDevice;
wifiDevice = lib.lists.findFirst (d: d.name != null) null networkDevices;
wifi-signal-strength = pkgs.callPackage ../../../packages/wifi-signal-strength {wifiDevice = wifiDevice.name;};
ghaf-launcher = pkgs.callPackage ./ghaf-launcher.nix {inherit config pkgs;};
timeZone =
Expand Down
5 changes: 4 additions & 1 deletion modules/flake-module.nix
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@
# Modules to be exported from Flake
#
{inputs, ...}: {
imports = [./disko/flake-module.nix];
imports = [
./disko/flake-module.nix
./hardware/flake-module.nix
];

flake.nixosModules = {
common.imports = [
Expand Down
File renamed without changes.
15 changes: 15 additions & 0 deletions modules/hardware/flake-module.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Copyright 2024 TII (SSRC) and the Ghaf contributors
# SPDX-License-Identifier: Apache-2.0
_: {
flake.nixosModules = {
hw-lenovo-x1.imports = [
./definition.nix
./x86_64-generic
./lenovo-x1
];
hw-x86_64-generic.imports = [
./definition.nix
./x86_64-generic
];
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@
# SPDX-License-Identifier: Apache-2.0
{
imports = [
./x86_64-linux.nix
./x86_64-generic
./definition.nix

./ax88179_178a.nix
./definitions
./modules/fprint.nix
];
}
62 changes: 62 additions & 0 deletions modules/hardware/lenovo-x1/definitions/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Copyright 2022-2024 TII (SSRC) and the Ghaf contributors
# SPDX-License-Identifier: Apache-2.0
#
{
config,
lib,
...
}: let
hwDefinition = import (./. + "/x1-${config.ghaf.hardware.generation}.nix");
in {
imports = [
../../definition.nix
];

options.ghaf.hardware.generation = lib.mkOption {
description = "Generation of the hardware configuration";
type = lib.types.str;
default = "gen11";
};

config = {
ghaf.hardware.definition = {
inherit (hwDefinition) mouse;
inherit (hwDefinition) touchpad;
inherit (hwDefinition) disks;
inherit (hwDefinition) network;
inherit (hwDefinition) gpu;

virtioInputHostEvdevs = [
# Lenovo X1 touchpad and keyboard
"/dev/input/by-path/platform-i8042-serio-0-event-kbd"
"/dev/mouse"
"/dev/touchpad"
# Lenovo X1 trackpoint (red button/joystick)
"/dev/input/by-path/platform-i8042-serio-1-event-mouse"
];
};

disko.devices.disk = hwDefinition.disks;

# Notes:
# 1. This assembles udev rules for different hw configurations (i.e., different mice/touchpads) by adding
# all of them to the configuration. This was chosen for simplicity to not have to provide hw identifier at build,
# but is not ideal and should be changed.
# 2. USB camera "passthrough" is handled by qemu and thus available on host. If peripheral VM is implemented,
# the entire host controller should be passthrough'd using the PCI bus (14.0). In x1, bluetooth and fingerprint
# reader are on this bus.
services.udev.extraRules = ''
# Laptop keyboard
SUBSYSTEM=="input", ATTRS{name}=="AT Translated Set 2 keyboard", GROUP="kvm"
# Laptop TrackPoint
SUBSYSTEM=="input", ATTRS{name}=="TPPS/2 Elan TrackPoint", GROUP="kvm"
# Lenovo X1 integrated webcam
KERNEL=="3-8", SUBSYSTEM=="usb", ATTR{busnum}=="3", ATTR{devnum}=="3", GROUP="kvm"
# Lenovo X1 integrated fingerprint reader
KERNEL=="3-6", SUBSYSTEM=="usb", ATTR{busnum}=="3", ATTR{devnum}=="2", GROUP="kvm"
# Mouse and Touchpad
${lib.strings.concatMapStringsSep "\n" (d: ''SUBSYSTEM=="input", ATTRS{name}=="${d}", KERNEL=="event*", GROUP="kvm", SYMLINK+="mouse"'') hwDefinition.mouse}
${lib.strings.concatMapStringsSep "\n" (d: ''SUBSYSTEM=="input", ATTRS{name}=="${d}", KERNEL=="event*", GROUP="kvm", SYMLINK+="touchpad"'') hwDefinition.touchpad}
'';
};
}
94 changes: 94 additions & 0 deletions modules/hardware/lenovo-x1/modules/fprint.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Copyright 2022-2024 TII (SSRC) and the Ghaf contributors
# SPDX-License-Identifier: Apache-2.0
{
config,
lib,
pkgs,
...
}: let
cfg = config.ghaf.hardware.fprint;
in
with lib; {
options.ghaf.hardware.fprint = {
enable = mkEnableOption "Enable fingerprint reader support";
qemuExtraArgs = mkOption {
type = types.listOf types.str;
default = [];
description = ''
Extra arguments to pass to Qemu when enabling the fingerprint reader.
This is useful for passing USB device information to Qemu.
'';
};
extraConfigurations = mkOption {
type = types.attrsOf types.anything;
default = {};
description = ''
Extra configurations to enable when enabling the fingerprint reader.
This is useful for enabling services and packages related to the fingerprint reader.
'';
};
};

config = mkIf cfg.enable {
ghaf.hardware.fprint = {
qemuExtraArgs = [
# Fingerprint reader
"-device"
"qemu-xhci"
"-device"
"usb-host,hostbus=3,hostport=6"
];

extraConfigurations = {
# Enable service and package for fingerprint reader
services.fprintd.enable = true;
environment.systemPackages = with pkgs; [fprintd];

# Enable polkit and add rules
ghaf.systemd.withPolkit = true;
security = {
polkit = {
enable = true;
debug = true;
# Polkit rules for fingerprint reader
extraConfig = ''
// Allow user to verify fingerprints
polkit.addRule(function(action, subject) {
if (action.id == "net.reactivated.fprint.device.verify" &&
subject.user == "ghaf") {
return polkit.Result.YES;
}
});
// Allow user to enroll fingerprints
polkit.addRule(function(action, subject) {
if (action.id == "net.reactivated.fprint.device.enroll" &&
subject.user == "ghaf") {
return polkit.Result.YES;
}
});
'';
};
# PAM rules for swaylock fingerprint reader
mbssrc marked this conversation as resolved.
Show resolved Hide resolved
pam.services = {
swaylock.text = ''
# Account management.
account required pam_unix.so

# Authentication management.
auth sufficient pam_unix.so likeauth try_first_pass
auth sufficient ${pkgs.fprintd}/lib/security/pam_fprintd.so
auth required pam_deny.so

# Password management.
password sufficient pam_unix.so nullok sha512

# Session management.
session required pam_env.so conffile=/etc/pam/environment readenv=0
session required pam_unix.so
'';
};
};
};
};
};
}
Loading