forked from pool/librtas
- Add support for more kernek rtas call kernek interfaces (jsc#PED-10917) * 0001-librtas-Move-platform-dump-rtas-call-code-to-separat.patch * 0002-librtas-platform-dump-prefer-dev-papr-platform-dump-.patch * 0003-librtas-move-get-set-indices-RTAS-calls-code-to-sepa.patch * 0004-librtas-Add-kernel-uapi-header-papr-indices.h.patch * 0005-librtas-Use-dev-papr-indices-when-available-for-ibm-.patch * 0006-librtas-Use-dev-papr-indices-when-available-for-get-.patch * 0007-librtas-Use-dev-papr-indices-when-available-for-set-.patch * 0008-librtas-Move-physical-attestation-rtas-call-code-to-.patch * 0009-librtas-Use-kernel-interface-when-available-for-ibm-.patch OBS-URL: https://build.opensuse.org/request/show/1254792 OBS-URL: https://build.opensuse.org/package/show/devel:libraries:c_c++/librtas?expand=0&rev=71
256 lines
7.4 KiB
Diff
256 lines
7.4 KiB
Diff
From edd705db27f14c393618ddd68c1b41c43985726a Mon Sep 17 00:00:00 2001
|
|
From: Haren Myneni <haren@linux.ibm.com>
|
|
Date: Sun, 9 Mar 2025 16:29:15 -0700
|
|
Subject: [PATCH 9/9] librtas: Use kernel interface when available for
|
|
ibm,physical-attestation
|
|
|
|
rtas_physical_attestation() uses sys_rtas() to obtain response
|
|
buffer for each attestation command. This RTAS function passes
|
|
RTAS work area to send input attestation command and to retrieve
|
|
response buffer. But the allocation of work area is prohibited
|
|
under system lockdown.
|
|
|
|
This patch adds changes to use new kernel ABI if
|
|
/dev/papr-physical-attestation is available. First execution of
|
|
rtas_physical_attestation() sets the new API if the device node
|
|
is available, otherise execute user space interface.
|
|
|
|
Open /dev/papr-physical-attestation and obtain FD with
|
|
PAPR_PHY_ATTEST_IOC_HANDLE ioctl. The kernel completes the RTAS
|
|
sequence in this ioctl and exposes the reponse buffer with this
|
|
FD. The user space reads the complete buffer with read() calls.
|
|
|
|
Signed-off-by: Haren Myneni <haren@linux.ibm.com>
|
|
---
|
|
Makefile.am | 3 +-
|
|
librtas_src/papr-physical-attestation.h | 31 ++++++
|
|
librtas_src/physical-attestation.c | 137 +++++++++++++++++++++++-
|
|
3 files changed, 166 insertions(+), 5 deletions(-)
|
|
create mode 100644 librtas_src/papr-physical-attestation.h
|
|
|
|
diff --git a/Makefile.am b/Makefile.am
|
|
index e605d98..ccd7ee7 100644
|
|
--- a/Makefile.am
|
|
+++ b/Makefile.am
|
|
@@ -44,7 +44,8 @@ noinst_HEADERS += \
|
|
librtas_src/papr-sysparm.h \
|
|
librtas_src/papr-vpd.h \
|
|
librtas_src/papr-platform-dump.h \
|
|
- librtas_src/papr-indices.h
|
|
+ librtas_src/papr-indices.h \
|
|
+ librtas_src/papr-physical-attestation.h
|
|
|
|
# See "Updating library version information" in the libtool manual for
|
|
# how to maintain these values. They are *not* tied to the release
|
|
diff --git a/librtas_src/papr-physical-attestation.h b/librtas_src/papr-physical-attestation.h
|
|
new file mode 100644
|
|
index 0000000..32b4bae
|
|
--- /dev/null
|
|
+++ b/librtas_src/papr-physical-attestation.h
|
|
@@ -0,0 +1,31 @@
|
|
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
|
+#ifndef _UAPI_PAPR_PHYSICAL_ATTESTATION_H_
|
|
+#define _UAPI_PAPR_PHYSICAL_ATTESTATION_H_
|
|
+
|
|
+#include <linux/types.h>
|
|
+#include <asm/ioctl.h>
|
|
+#include "papr-miscdev.h"
|
|
+
|
|
+#define PAPR_PHYATTEST_MAX_INPUT 4084 /* Max 4K buffer: 4K-12 */
|
|
+
|
|
+/*
|
|
+ * Defined in PAPR 2.13+ 21.6 Attestation Command Structures.
|
|
+ * User space pass this struct and the max size should be 4K.
|
|
+ */
|
|
+struct papr_phy_attest_io_block {
|
|
+ __u8 version;
|
|
+ __u8 command;
|
|
+ __u8 TCG_major_ver;
|
|
+ __u8 TCG_minor_ver;
|
|
+ __be32 length;
|
|
+ __be32 correlator;
|
|
+ __u8 payload[PAPR_PHYATTEST_MAX_INPUT];
|
|
+};
|
|
+
|
|
+/*
|
|
+ * ioctl for /dev/papr-physical-attestation. Returns a attestation
|
|
+ * command fd handle
|
|
+ */
|
|
+#define PAPR_PHY_ATTEST_IOC_HANDLE _IOW(PAPR_MISCDEV_IOC_ID, 8, struct papr_phy_attest_io_block)
|
|
+
|
|
+#endif /* _UAPI_PAPR_PHYSICAL_ATTESTATION_H_ */
|
|
diff --git a/librtas_src/physical-attestation.c b/librtas_src/physical-attestation.c
|
|
index 3e36af3..48108a0 100644
|
|
--- a/librtas_src/physical-attestation.c
|
|
+++ b/librtas_src/physical-attestation.c
|
|
@@ -1,21 +1,27 @@
|
|
// SPDX-License-Identifier: LGPL-2.1-or-later
|
|
-
|
|
+
|
|
// Support for accessing ibm,physical-attestation data
|
|
// via /dev/papr-phy-attestation or the legacy rtas() syscall.
|
|
|
|
#include <stdarg.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
+#include <fcntl.h>
|
|
+#include <pthread.h>
|
|
#include <inttypes.h>
|
|
+#include <stdbool.h>
|
|
+#include <stdlib.h>
|
|
#include <sys/syscall.h>
|
|
+#include <sys/stat.h>
|
|
+#include <sys/ioctl.h>
|
|
#include <linux/unistd.h>
|
|
#include <linux/types.h>
|
|
#include "internal.h"
|
|
#include "librtas.h"
|
|
+#include "papr-physical-attestation.h"
|
|
|
|
/**
|
|
- * rtas_physical_attestation
|
|
- * @brief Interface for ibm,physical-attestation rtas call.
|
|
+ * ibm,physical-attestation RTAS call from user space
|
|
*
|
|
* @param workarea input/output work area for rtas call
|
|
* @param seq_num sequence number of the rtas call
|
|
@@ -23,7 +29,7 @@
|
|
* @param work_area_bytes size of work area
|
|
* @return 0 on success, !0 on failure
|
|
*/
|
|
-int rtas_physical_attestation(char *workarea, int seq_num, int *next_seq_num,
|
|
+int phy_attestation_user(char *workarea, int seq_num, int *next_seq_num,
|
|
int *work_area_bytes)
|
|
{
|
|
uint32_t workarea_pa;
|
|
@@ -76,3 +82,126 @@ int rtas_physical_attestation(char *workarea, int seq_num, int *next_seq_num,
|
|
return rc ? rc : status;
|
|
}
|
|
|
|
+static bool phy_attest_can_use_chardev(void)
|
|
+{
|
|
+ struct stat statbuf;
|
|
+
|
|
+ if (stat("/dev/papr-physical-attestation", &statbuf))
|
|
+ return false;
|
|
+
|
|
+ if (!S_ISCHR(statbuf.st_mode))
|
|
+ return false;
|
|
+
|
|
+ if (close(open("/dev/papr-physical-attestation", O_RDONLY)))
|
|
+ return false;
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
+#define DEVPATH "/dev/papr-physical-attestation"
|
|
+
|
|
+static int phy_attest_fd_new(const char *attest_cmd, unsigned int size)
|
|
+{
|
|
+ const int devfd = open(DEVPATH, O_WRONLY);
|
|
+ struct papr_phy_attest_io_block cmd = {};
|
|
+ int fd = -1;
|
|
+
|
|
+ if (devfd < 0)
|
|
+ return -1;
|
|
+
|
|
+ /*
|
|
+ * Size of each command struct has to be the buffer size
|
|
+ * (WORK_AREA_SIZE - 4K) passed by the user.
|
|
+ */
|
|
+ if (size != sizeof(struct papr_phy_attest_io_block)) {
|
|
+ fd = RTAS_IO_ASSERT;
|
|
+ goto close_devfd;
|
|
+ }
|
|
+
|
|
+ memcpy(&cmd, attest_cmd, sizeof(struct papr_phy_attest_io_block));
|
|
+ fd = ioctl(devfd, PAPR_PHY_ATTEST_IOC_HANDLE, &cmd);
|
|
+
|
|
+close_devfd:
|
|
+ close(devfd);
|
|
+ return fd;
|
|
+}
|
|
+
|
|
+static int
|
|
+phy_attestation_kernel(char *workarea, int seq_num, int *next_seq_num,
|
|
+ int *work_area_bytes)
|
|
+{
|
|
+ int size = *work_area_bytes;
|
|
+ int fd = (seq_num == 1) ? phy_attest_fd_new(workarea, size)
|
|
+ : (int)seq_num;
|
|
+
|
|
+ /*
|
|
+ * Ensure we return a fd > 0 in next_seq_num.
|
|
+ */
|
|
+ if (fd == 1) {
|
|
+ int newfd = dup(fd);
|
|
+ close(fd);
|
|
+ fd = newfd;
|
|
+ }
|
|
+
|
|
+ if (fd < 0)
|
|
+ return -3; /* Synthesize ibm,get-vpd "parameter error" */
|
|
+
|
|
+ /* Caller provided more data than FW can handle */
|
|
+ if (size == 0 || size > WORK_AREA_SIZE) {
|
|
+ close(fd);
|
|
+ return RTAS_IO_ASSERT;
|
|
+ }
|
|
+
|
|
+
|
|
+ int rtas_status = 0;
|
|
+ ssize_t res = read(fd, workarea, *work_area_bytes);
|
|
+ if (res < 0) {
|
|
+ rtas_status = -1; /* Synthesize ibm,get-vpd "hardware error" */
|
|
+ close(fd);
|
|
+ } else if (res == 0 || res < (ssize_t)size) {
|
|
+ rtas_status = 0; /* Done with sequence, no more data */
|
|
+ close(fd);
|
|
+ if (next_seq_num)
|
|
+ *next_seq_num = 1;
|
|
+ if (work_area_bytes)
|
|
+ *work_area_bytes = res;
|
|
+ } else {
|
|
+ rtas_status = 1; /* More data available, call again */
|
|
+ if (next_seq_num)
|
|
+ *next_seq_num = fd;
|
|
+ if (work_area_bytes)
|
|
+ *work_area_bytes = res;
|
|
+ }
|
|
+
|
|
+ return rtas_status;
|
|
+}
|
|
+
|
|
+static int (*phy_attestation_fn)(char *workarea, int seq_num,
|
|
+ int *next_seq_num, int *work_area_bytes);
|
|
+
|
|
+static void phy_attestation_fn_setup(void)
|
|
+{
|
|
+ phy_attestation_fn = phy_attest_can_use_chardev() ?
|
|
+ phy_attestation_kernel : phy_attestation_user;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * rtas_physical_attestation
|
|
+ * @brief Interface for ibm,physical-attestation rtas call.
|
|
+ *
|
|
+ * @param workarea input/output work area for rtas call
|
|
+ * @param seq_num sequence number of the rtas call
|
|
+ * @param next_seq_num next sequence number
|
|
+ * @param work_area_bytes size of input/output work area
|
|
+ * @return 0 on success, !0 on failure
|
|
+ */
|
|
+int rtas_physical_attestation(char *workarea, int seq_num, int *next_seq_num,
|
|
+ int *work_area_bytes)
|
|
+{
|
|
+ static pthread_once_t phy_attestation_fn_once = PTHREAD_ONCE_INIT;
|
|
+
|
|
+ pthread_once(&phy_attestation_fn_once, phy_attestation_fn_setup);
|
|
+
|
|
+ return phy_attestation_fn(workarea, seq_num, next_seq_num,
|
|
+ work_area_bytes);
|
|
+}
|
|
--
|
|
2.47.1
|
|
|