crypto: ccp: Add the SNP_COMMIT command
authorTom Lendacky <thomas.lendacky@amd.com>
Fri, 26 Jan 2024 04:11:24 +0000 (22:11 -0600)
committerBorislav Petkov (AMD) <bp@alien8.de>
Mon, 29 Jan 2024 19:34:19 +0000 (20:34 +0100)
The SNP_COMMIT command is used to commit the currently installed version
of the SEV firmware. Once committed, the firmware cannot be replaced
with a previous firmware version (cannot be rolled back). This command
will also update the reported TCB to match that of the currently
installed firmware.

  [ mdr: Note the reported TCB update in the documentation/commit. ]

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Michael Roth <michael.roth@amd.com>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Link: https://lore.kernel.org/r/20240126041126.1927228-25-michael.roth@amd.com
Documentation/virt/coco/sev-guest.rst
drivers/crypto/ccp/sev-dev.c
include/linux/psp-sev.h
include/uapi/linux/psp-sev.h

index 6d3d5d336e5f003b304dbe38358d2a8a63a18b9f..007ae828aa2ab71af211fd8b827c3cc952ee3a95 100644 (file)
@@ -151,6 +151,17 @@ The SNP_PLATFORM_STATUS command is used to query the SNP platform status. The
 status includes API major, minor version and more. See the SEV-SNP
 specification for further details.
 
+2.5 SNP_COMMIT
+--------------
+:Technology: sev-snp
+:Type: hypervisor ioctl cmd
+:Returns (out): 0 on success, -negative on error
+
+SNP_COMMIT is used to commit the currently installed firmware using the
+SEV-SNP firmware SNP_COMMIT command. This prevents roll-back to a previously
+committed firmware version. This will also update the reported TCB to match
+that of the currently installed firmware.
+
 3. SEV-SNP CPUID Enforcement
 ============================
 
index ae02efe2736cf7d0dd87cc30e1a4b3186dcc0b66..6e375d15755cbce1f728177629bb7b875034356b 100644 (file)
@@ -222,6 +222,7 @@ static int sev_cmd_buffer_len(int cmd)
        case SEV_CMD_SNP_PLATFORM_STATUS:       return sizeof(struct sev_data_snp_addr);
        case SEV_CMD_SNP_GUEST_REQUEST:         return sizeof(struct sev_data_snp_guest_request);
        case SEV_CMD_SNP_CONFIG:                return sizeof(struct sev_user_data_snp_config);
+       case SEV_CMD_SNP_COMMIT:                return sizeof(struct sev_data_snp_commit);
        default:                                return 0;
        }
 
@@ -1990,6 +1991,19 @@ cleanup:
        return ret;
 }
 
+static int sev_ioctl_do_snp_commit(struct sev_issue_cmd *argp)
+{
+       struct sev_device *sev = psp_master->sev_data;
+       struct sev_data_snp_commit buf;
+
+       if (!sev->snp_initialized)
+               return -EINVAL;
+
+       buf.len = sizeof(buf);
+
+       return __sev_do_cmd_locked(SEV_CMD_SNP_COMMIT, &buf, &argp->error);
+}
+
 static long sev_ioctl(struct file *file, unsigned int ioctl, unsigned long arg)
 {
        void __user *argp = (void __user *)arg;
@@ -2044,6 +2058,9 @@ static long sev_ioctl(struct file *file, unsigned int ioctl, unsigned long arg)
        case SNP_PLATFORM_STATUS:
                ret = sev_ioctl_do_snp_platform_status(&input);
                break;
+       case SNP_COMMIT:
+               ret = sev_ioctl_do_snp_commit(&input);
+               break;
        default:
                ret = -EINVAL;
                goto out;
index 84eabbfbbc0871b450082a307c1d375952fc4706..3705c2044fc04ebabf2fff2b4d9f8aadebbbe1cf 100644 (file)
@@ -801,6 +801,15 @@ struct sev_platform_init_args {
        bool probe;
 };
 
+/**
+ * struct sev_data_snp_commit - SNP_COMMIT structure
+ *
+ * @len: length of the command buffer read by the PSP
+ */
+struct sev_data_snp_commit {
+       u32 len;
+} __packed;
+
 #ifdef CONFIG_CRYPTO_DEV_SP_PSP
 
 /**
index f1e2c55a92b4326ee5def7298261b723cde7c576..35c207664e95d1a3fe7a325ad45147297f232a13 100644 (file)
@@ -29,6 +29,7 @@ enum {
        SEV_GET_ID,     /* This command is deprecated, use SEV_GET_ID2 */
        SEV_GET_ID2,
        SNP_PLATFORM_STATUS,
+       SNP_COMMIT,
 
        SEV_MAX,
 };