File Index
Files and directories
Sign in
FILE

papr-phy-attest.c

File preview with syntax highlighting.

linux-6.19.14/arch/powerpc/platforms/pseries/papr-phy-attest.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2
  3#define pr_fmt(fmt) "papr-phy-attest: " fmt
  4
  5#include <linux/build_bug.h>
  6#include <linux/file.h>
  7#include <linux/fs.h>
  8#include <linux/init.h>
  9#include <linux/lockdep.h>
 10#include <linux/kernel.h>
 11#include <linux/miscdevice.h>
 12#include <linux/signal.h>
 13#include <linux/slab.h>
 14#include <linux/string.h>
 15#include <linux/string_helpers.h>
 16#include <linux/uaccess.h>
 17#include <asm/machdep.h>
 18#include <asm/rtas-work-area.h>
 19#include <asm/rtas.h>
 20#include <uapi/asm/papr-physical-attestation.h>
 21#include "papr-rtas-common.h"
 22
 23/**
 24 * struct rtas_phy_attest_params - Parameters (in and out) for
 25 * ibm,physical-attestation.
 26 *
 27 * @cmd:  In: Caller-provided attestation command buffer. Must be
 28 *        RTAS-addressable.
 29 * @work_area: In: Caller-provided work area buffer for attestation
 30 *             command structure
 31 *             Out: Caller-provided work area buffer for the response
 32 * @cmd_len:   In: Caller-provided attestation command structure
 33 *             length
 34 * @sequence:  In: Sequence number. Out: Next sequence number.
 35 * @written:   Out: Bytes written by ibm,physical-attestation to
 36 *             @work_area.
 37 * @status:    Out: RTAS call status.
 38 */
 39struct rtas_phy_attest_params {
 40	struct papr_phy_attest_io_block cmd;
 41	struct rtas_work_area *work_area;
 42	u32 cmd_len;
 43	u32 sequence;
 44	u32 written;
 45	s32 status;
 46};
 47
 48/**
 49 * rtas_physical_attestation() - Call ibm,physical-attestation to
 50 * fill a work area buffer.
 51 * @params: See &struct rtas_phy_attest_params.
 52 *
 53 * Calls ibm,physical-attestation until it errors or successfully
 54 * deposits data into the supplied work area. Handles RTAS retry
 55 * statuses. Maps RTAS error statuses to reasonable errno values.
 56 *
 57 * The caller is expected to invoke rtas_physical_attestation()
 58 * multiple times to retrieve all the data for the provided
 59 * attestation command. Only one sequence should be in progress at
 60 * any time; starting a new sequence will disrupt any sequence
 61 * already in progress. Serialization of attestation retrieval
 62 * sequences is the responsibility of the caller.
 63 *
 64 * The caller should inspect @params.status to determine whether more
 65 * calls are needed to complete the sequence.
 66 *
 67 * Context: May sleep.
 68 * Return: -ve on error, 0 otherwise.
 69 */
 70static int rtas_physical_attestation(struct rtas_phy_attest_params *params)
 71{
 72	struct rtas_work_area *work_area;
 73	s32 fwrc, token;
 74	u32 rets[2];
 75	int ret;
 76
 77	work_area = params->work_area;
 78	token = rtas_function_token(RTAS_FN_IBM_PHYSICAL_ATTESTATION);
 79	if (token == RTAS_UNKNOWN_SERVICE)
 80		return -ENOENT;
 81
 82	lockdep_assert_held(&rtas_ibm_physical_attestation_lock);
 83
 84	do {
 85		fwrc = rtas_call(token, 3, 3, rets,
 86				 rtas_work_area_phys(work_area),
 87				 params->cmd_len,
 88				 params->sequence);
 89	} while (rtas_busy_delay(fwrc));
 90
 91	switch (fwrc) {
 92	case RTAS_HARDWARE_ERROR:
 93		ret = -EIO;
 94		break;
 95	case RTAS_INVALID_PARAMETER:
 96		ret = -EINVAL;
 97		break;
 98	case RTAS_SEQ_MORE_DATA:
 99		params->sequence = rets[0];
100		fallthrough;
101	case RTAS_SEQ_COMPLETE:
102		params->written = rets[1];
103		/*
104		 * Kernel or firmware bug, do not continue.
105		 */
106		if (WARN(params->written > rtas_work_area_size(work_area),
107			 "possible write beyond end of work area"))
108			ret = -EFAULT;
109		else
110			ret = 0;
111		break;
112	default:
113		ret = -EIO;
114		pr_err_ratelimited("unexpected ibm,get-phy_attest status %d\n", fwrc);
115		break;
116	}
117
118	params->status = fwrc;
119	return ret;
120}
121
122/*
123 * Internal physical-attestation sequence APIs. A physical-attestation
124 * sequence is a series of calls to get ibm,physical-attestation
125 * for a given attestation command. The sequence ends when an error
126 * is encountered or all data for the attestation command has been
127 * returned.
128 */
129
130/**
131 * phy_attest_sequence_begin() - Begin a response data for attestation
132 * command retrieval sequence.
133 * @seq: user specified parameters for RTAS call from seq struct.
134 *
135 * Context: May sleep.
136 */
137static void phy_attest_sequence_begin(struct papr_rtas_sequence *seq)
138{
139	struct rtas_phy_attest_params *param;
140
141	/*
142	 * We could allocate the work area before acquiring the
143	 * function lock, but that would allow concurrent requests to
144	 * exhaust the limited work area pool for no benefit. So
145	 * allocate the work area under the lock.
146	 */
147	mutex_lock(&rtas_ibm_physical_attestation_lock);
148	param =  (struct rtas_phy_attest_params *)seq->params;
149	param->work_area = rtas_work_area_alloc(SZ_4K);
150	memcpy(rtas_work_area_raw_buf(param->work_area), &param->cmd,
151			param->cmd_len);
152	param->sequence = 1;
153	param->status = 0;
154}
155
156/**
157 * phy_attest_sequence_end() - Finalize a attestation command
158 * response retrieval sequence.
159 * @seq: Sequence state.
160 *
161 * Releases resources obtained by phy_attest_sequence_begin().
162 */
163static void phy_attest_sequence_end(struct papr_rtas_sequence *seq)
164{
165	struct rtas_phy_attest_params *param;
166
167	param =  (struct rtas_phy_attest_params *)seq->params;
168	rtas_work_area_free(param->work_area);
169	mutex_unlock(&rtas_ibm_physical_attestation_lock);
170	kfree(param);
171}
172
173/*
174 * Generator function to be passed to papr_rtas_blob_generate().
175 */
176static const char *phy_attest_sequence_fill_work_area(struct papr_rtas_sequence *seq,
177						size_t *len)
178{
179	struct rtas_phy_attest_params *p;
180	bool init_state;
181
182	p = (struct rtas_phy_attest_params *)seq->params;
183	init_state = (p->written == 0) ? true : false;
184
185	if (papr_rtas_sequence_should_stop(seq, p->status, init_state))
186		return NULL;
187	if (papr_rtas_sequence_set_err(seq, rtas_physical_attestation(p)))
188		return NULL;
189	*len = p->written;
190	return rtas_work_area_raw_buf(p->work_area);
191}
192
193static const struct file_operations papr_phy_attest_handle_ops = {
194	.read = papr_rtas_common_handle_read,
195	.llseek = papr_rtas_common_handle_seek,
196	.release = papr_rtas_common_handle_release,
197};
198
199/**
200 * papr_phy_attest_create_handle() - Create a fd-based handle for
201 * reading the response for the given attestation command.
202 * @ulc: Attestation command in user memory; defines the scope of
203 *       data for the attestation command to retrieve.
204 *
205 * Handler for PAPR_PHYSICAL_ATTESTATION_IOC_CREATE_HANDLE ioctl
206 * command. Validates @ulc and instantiates an immutable response
207 * "blob" for attestation command. The blob is attached to a file
208 * descriptor for reading by user space. The memory backing the blob
209 * is freed when the file is released.
210 *
211 * The entire requested response buffer for the attestation command
212 * retrieved by this call and all necessary RTAS interactions are
213 * performed before returning the fd to user space. This keeps the
214 * read handler simple and ensures that kernel can prevent
215 * interleaving ibm,physical-attestation call sequences.
216 *
217 * Return: The installed fd number if successful, -ve errno otherwise.
218 */
219static long papr_phy_attest_create_handle(struct papr_phy_attest_io_block __user *ulc)
220{
221	struct rtas_phy_attest_params *params;
222	struct papr_rtas_sequence seq = {};
223	int fd;
224
225	/*
226	 * Freed in phy_attest_sequence_end().
227	 */
228	params =  kzalloc(sizeof(*params), GFP_KERNEL_ACCOUNT);
229	if (!params)
230		return -ENOMEM;
231
232	if (copy_from_user(&params->cmd, ulc,
233			sizeof(struct papr_phy_attest_io_block)))
234		return -EFAULT;
235
236	params->cmd_len = be32_to_cpu(params->cmd.length);
237	seq = (struct papr_rtas_sequence) {
238		.begin = phy_attest_sequence_begin,
239		.end = phy_attest_sequence_end,
240		.work = phy_attest_sequence_fill_work_area,
241	};
242
243	seq.params = (void *)params;
244
245	fd = papr_rtas_setup_file_interface(&seq,
246			&papr_phy_attest_handle_ops,
247			"[papr-physical-attestation]");
248
249	return fd;
250}
251
252/*
253 * Top-level ioctl handler for /dev/papr-physical-attestation.
254 */
255static long papr_phy_attest_dev_ioctl(struct file *filp, unsigned int ioctl, unsigned long arg)
256{
257	void __user *argp = (__force void __user *)arg;
258	long ret;
259
260	switch (ioctl) {
261	case PAPR_PHY_ATTEST_IOC_HANDLE:
262		ret = papr_phy_attest_create_handle(argp);
263		break;
264	default:
265		ret = -ENOIOCTLCMD;
266		break;
267	}
268	return ret;
269}
270
271static const struct file_operations papr_phy_attest_ops = {
272	.unlocked_ioctl = papr_phy_attest_dev_ioctl,
273};
274
275static struct miscdevice papr_phy_attest_dev = {
276	.minor = MISC_DYNAMIC_MINOR,
277	.name = "papr-physical-attestation",
278	.fops = &papr_phy_attest_ops,
279};
280
281static __init int papr_phy_attest_init(void)
282{
283	if (!rtas_function_implemented(RTAS_FN_IBM_PHYSICAL_ATTESTATION))
284		return -ENODEV;
285
286	return misc_register(&papr_phy_attest_dev);
287}
288machine_device_initcall(pseries, papr_phy_attest_init);
~/ Read-only file preview.