lol

nixos/amd.sev: add `hardware.cpu.amd.sevGuest` option

Allow setting the owner, group and mode of the `/dev/sev-guest` device,
similar to what is already possible for `/dev/sev` through the
`hardware.cpu.amd.sev` options.

The `/dev/sev` device is available to AMD SEV hosts, e.g., to start an
AMD SEV-SNP guest. In contrast, the `/dev/sev-guest` device is only
available within SEV-SNP guests. The guest uses the device, for example,
to request an attestation report. Linux has in-tree support for SEV-SNP
guests since 5.19.

+59 -30
+59 -30
nixos/modules/hardware/cpu/amd-sev.nix
··· 1 - { config, lib, ... }: 1 + { config, options, lib, ... }: 2 2 with lib; 3 3 let 4 - cfg = config.hardware.cpu.amd.sev; 5 - defaultGroup = "sev"; 4 + cfgSev = config.hardware.cpu.amd.sev; 5 + cfgSevGuest = config.hardware.cpu.amd.sevGuest; 6 + 7 + optionsFor = device: group: { 8 + enable = mkEnableOption (lib.mdDoc "access to the AMD ${device} device"); 9 + user = mkOption { 10 + description = lib.mdDoc "Owner to assign to the ${device} device."; 11 + type = types.str; 12 + default = "root"; 13 + }; 14 + group = mkOption { 15 + description = lib.mdDoc "Group to assign to the ${device} device."; 16 + type = types.str; 17 + default = group; 18 + }; 19 + mode = mkOption { 20 + description = lib.mdDoc "Mode to set for the ${device} device."; 21 + type = types.str; 22 + default = "0660"; 23 + }; 24 + }; 6 25 in 7 - with lib; { 8 - options.hardware.cpu.amd.sev = { 9 - enable = mkEnableOption (lib.mdDoc "access to the AMD SEV device"); 10 - user = mkOption { 11 - description = lib.mdDoc "Owner to assign to the SEV device."; 12 - type = types.str; 13 - default = "root"; 14 - }; 15 - group = mkOption { 16 - description = lib.mdDoc "Group to assign to the SEV device."; 17 - type = types.str; 18 - default = defaultGroup; 19 - }; 20 - mode = mkOption { 21 - description = lib.mdDoc "Mode to set for the SEV device."; 22 - type = types.str; 23 - default = "0660"; 24 - }; 25 - }; 26 + with lib; { 27 + options.hardware.cpu.amd.sev = optionsFor "SEV" "sev"; 28 + 29 + options.hardware.cpu.amd.sevGuest = optionsFor "SEV guest" "sev-guest"; 26 30 27 - config = mkIf cfg.enable { 31 + config = mkMerge [ 32 + # /dev/sev 33 + (mkIf cfgSev.enable { 28 34 assertions = [ 29 35 { 30 - assertion = hasAttr cfg.user config.users.users; 36 + assertion = hasAttr cfgSev.user config.users.users; 31 37 message = "Given user does not exist"; 32 38 } 33 39 { 34 - assertion = (cfg.group == defaultGroup) || (hasAttr cfg.group config.users.groups); 40 + assertion = (cfgSev.group == options.hardware.cpu.amd.sev.group.default) || (hasAttr cfgSev.group config.users.groups); 35 41 message = "Given group does not exist"; 36 42 } 37 43 ]; ··· 40 46 options kvm_amd sev=1 41 47 ''; 42 48 43 - users.groups = optionalAttrs (cfg.group == defaultGroup) { 44 - "${cfg.group}" = {}; 49 + users.groups = optionalAttrs (cfgSev.group == options.hardware.cpu.amd.sev.group.default) { 50 + "${cfgSev.group}" = { }; 45 51 }; 46 52 47 - services.udev.extraRules = with cfg; '' 53 + services.udev.extraRules = with cfgSev; '' 48 54 KERNEL=="sev", OWNER="${user}", GROUP="${group}", MODE="${mode}" 49 55 ''; 50 - }; 51 - } 56 + }) 57 + 58 + # /dev/sev-guest 59 + (mkIf cfgSevGuest.enable { 60 + assertions = [ 61 + { 62 + assertion = hasAttr cfgSevGuest.user config.users.users; 63 + message = "Given user does not exist"; 64 + } 65 + { 66 + assertion = (cfgSevGuest.group == options.hardware.cpu.amd.sevGuest.group.default) || (hasAttr cfgSevGuest.group config.users.groups); 67 + message = "Given group does not exist"; 68 + } 69 + ]; 70 + 71 + users.groups = optionalAttrs (cfgSevGuest.group == options.hardware.cpu.amd.sevGuest.group.default) { 72 + "${cfgSevGuest.group}" = { }; 73 + }; 74 + 75 + services.udev.extraRules = with cfgSevGuest; '' 76 + KERNEL=="sev-guest", OWNER="${user}", GROUP="${group}", MODE="${mode}" 77 + ''; 78 + }) 79 + ]; 80 + }