1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright(c) 2023 Intel Corporation. All rights reserved. */
3
4 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
5
6 #include <linux/tsm.h>
7 #include <linux/err.h>
8 #include <linux/slab.h>
9 #include <linux/rwsem.h>
10 #include <linux/string.h>
11 #include <linux/module.h>
12 #include <linux/cleanup.h>
13 #include <linux/configfs.h>
14
15 static struct tsm_provider {
16 const struct tsm_report_ops *ops;
17 void *data;
18 atomic_t count;
19 } provider;
20 static DECLARE_RWSEM(tsm_rwsem);
21
22 /**
23 * DOC: Trusted Security Module (TSM) Attestation Report Interface
24 *
25 * The TSM report interface is a common provider of blobs that facilitate
26 * attestation of a TVM (confidential computing guest) by an attestation
27 * service. A TSM report combines a user-defined blob (likely a public-key with
28 * a nonce for a key-exchange protocol) with a signed attestation report. That
29 * combined blob is then used to obtain secrets provided by an agent that can
30 * validate the attestation report. The expectation is that this interface is
31 * invoked infrequently, however configfs allows for multiple agents to
32 * own their own report generation instances to generate reports as
33 * often as needed.
34 *
35 * The attestation report format is TSM provider specific, when / if a standard
36 * materializes that can be published instead of the vendor layout. Until then
37 * the 'provider' attribute indicates the format of 'outblob', and optionally
38 * 'auxblob' and 'manifestblob'.
39 */
40
41 struct tsm_report_state {
42 struct tsm_report report;
43 unsigned long write_generation;
44 unsigned long read_generation;
45 struct config_item cfg;
46 };
47
48 enum tsm_data_select {
49 TSM_REPORT,
50 TSM_CERTS,
51 TSM_MANIFEST,
52 };
53
to_tsm_report(struct config_item * cfg)54 static struct tsm_report *to_tsm_report(struct config_item *cfg)
55 {
56 struct tsm_report_state *state =
57 container_of(cfg, struct tsm_report_state, cfg);
58
59 return &state->report;
60 }
61
to_state(struct tsm_report * report)62 static struct tsm_report_state *to_state(struct tsm_report *report)
63 {
64 return container_of(report, struct tsm_report_state, report);
65 }
66
try_advance_write_generation(struct tsm_report * report)67 static int try_advance_write_generation(struct tsm_report *report)
68 {
69 struct tsm_report_state *state = to_state(report);
70
71 lockdep_assert_held_write(&tsm_rwsem);
72
73 /*
74 * Malicious or broken userspace has written enough times for
75 * read_generation == write_generation by modular arithmetic without an
76 * interim read. Stop accepting updates until the current report
77 * configuration is read.
78 */
79 if (state->write_generation == state->read_generation - 1)
80 return -EBUSY;
81 state->write_generation++;
82 return 0;
83 }
84
tsm_report_privlevel_store(struct config_item * cfg,const char * buf,size_t len)85 static ssize_t tsm_report_privlevel_store(struct config_item *cfg,
86 const char *buf, size_t len)
87 {
88 struct tsm_report *report = to_tsm_report(cfg);
89 unsigned int val;
90 int rc;
91
92 rc = kstrtouint(buf, 0, &val);
93 if (rc)
94 return rc;
95
96 guard(rwsem_write)(&tsm_rwsem);
97 if (!provider.ops)
98 return -ENXIO;
99
100 /*
101 * The valid privilege levels that a TSM might accept, if it accepts a
102 * privilege level setting at all, are a max of TSM_PRIVLEVEL_MAX (see
103 * SEV-SNP GHCB) and a minimum of a TSM selected floor value no less
104 * than 0.
105 */
106 if (provider.ops->privlevel_floor > val || val > TSM_REPORT_PRIVLEVEL_MAX)
107 return -EINVAL;
108
109 rc = try_advance_write_generation(report);
110 if (rc)
111 return rc;
112 report->desc.privlevel = val;
113
114 return len;
115 }
116 CONFIGFS_ATTR_WO(tsm_report_, privlevel);
117
tsm_report_privlevel_floor_show(struct config_item * cfg,char * buf)118 static ssize_t tsm_report_privlevel_floor_show(struct config_item *cfg,
119 char *buf)
120 {
121 guard(rwsem_read)(&tsm_rwsem);
122
123 if (!provider.ops)
124 return -ENXIO;
125
126 return sysfs_emit(buf, "%u\n", provider.ops->privlevel_floor);
127 }
128 CONFIGFS_ATTR_RO(tsm_report_, privlevel_floor);
129
tsm_report_service_provider_store(struct config_item * cfg,const char * buf,size_t len)130 static ssize_t tsm_report_service_provider_store(struct config_item *cfg,
131 const char *buf, size_t len)
132 {
133 struct tsm_report *report = to_tsm_report(cfg);
134 size_t sp_len;
135 char *sp;
136 int rc;
137
138 guard(rwsem_write)(&tsm_rwsem);
139 rc = try_advance_write_generation(report);
140 if (rc)
141 return rc;
142
143 sp_len = (buf[len - 1] != '\n') ? len : len - 1;
144
145 sp = kstrndup(buf, sp_len, GFP_KERNEL);
146 if (!sp)
147 return -ENOMEM;
148 kfree(report->desc.service_provider);
149
150 report->desc.service_provider = sp;
151
152 return len;
153 }
154 CONFIGFS_ATTR_WO(tsm_report_, service_provider);
155
tsm_report_service_guid_store(struct config_item * cfg,const char * buf,size_t len)156 static ssize_t tsm_report_service_guid_store(struct config_item *cfg,
157 const char *buf, size_t len)
158 {
159 struct tsm_report *report = to_tsm_report(cfg);
160 int rc;
161
162 guard(rwsem_write)(&tsm_rwsem);
163 rc = try_advance_write_generation(report);
164 if (rc)
165 return rc;
166
167 report->desc.service_guid = guid_null;
168
169 rc = guid_parse(buf, &report->desc.service_guid);
170 if (rc)
171 return rc;
172
173 return len;
174 }
175 CONFIGFS_ATTR_WO(tsm_report_, service_guid);
176
tsm_report_service_manifest_version_store(struct config_item * cfg,const char * buf,size_t len)177 static ssize_t tsm_report_service_manifest_version_store(struct config_item *cfg,
178 const char *buf, size_t len)
179 {
180 struct tsm_report *report = to_tsm_report(cfg);
181 unsigned int val;
182 int rc;
183
184 rc = kstrtouint(buf, 0, &val);
185 if (rc)
186 return rc;
187
188 guard(rwsem_write)(&tsm_rwsem);
189 rc = try_advance_write_generation(report);
190 if (rc)
191 return rc;
192 report->desc.service_manifest_version = val;
193
194 return len;
195 }
196 CONFIGFS_ATTR_WO(tsm_report_, service_manifest_version);
197
tsm_report_inblob_write(struct config_item * cfg,const void * buf,size_t count)198 static ssize_t tsm_report_inblob_write(struct config_item *cfg,
199 const void *buf, size_t count)
200 {
201 struct tsm_report *report = to_tsm_report(cfg);
202 int rc;
203
204 guard(rwsem_write)(&tsm_rwsem);
205 rc = try_advance_write_generation(report);
206 if (rc)
207 return rc;
208
209 report->desc.inblob_len = count;
210 memcpy(report->desc.inblob, buf, count);
211 return count;
212 }
213 CONFIGFS_BIN_ATTR_WO(tsm_report_, inblob, NULL, TSM_REPORT_INBLOB_MAX);
214
tsm_report_generation_show(struct config_item * cfg,char * buf)215 static ssize_t tsm_report_generation_show(struct config_item *cfg, char *buf)
216 {
217 struct tsm_report *report = to_tsm_report(cfg);
218 struct tsm_report_state *state = to_state(report);
219
220 guard(rwsem_read)(&tsm_rwsem);
221 return sysfs_emit(buf, "%lu\n", state->write_generation);
222 }
223 CONFIGFS_ATTR_RO(tsm_report_, generation);
224
tsm_report_provider_show(struct config_item * cfg,char * buf)225 static ssize_t tsm_report_provider_show(struct config_item *cfg, char *buf)
226 {
227 guard(rwsem_read)(&tsm_rwsem);
228 if (!provider.ops)
229 return -ENXIO;
230
231 return sysfs_emit(buf, "%s\n", provider.ops->name);
232 }
233 CONFIGFS_ATTR_RO(tsm_report_, provider);
234
__read_report(struct tsm_report * report,void * buf,size_t count,enum tsm_data_select select)235 static ssize_t __read_report(struct tsm_report *report, void *buf, size_t count,
236 enum tsm_data_select select)
237 {
238 loff_t offset = 0;
239 ssize_t len;
240 u8 *out;
241
242 if (select == TSM_REPORT) {
243 out = report->outblob;
244 len = report->outblob_len;
245 } else if (select == TSM_MANIFEST) {
246 out = report->manifestblob;
247 len = report->manifestblob_len;
248 } else {
249 out = report->auxblob;
250 len = report->auxblob_len;
251 }
252
253 /*
254 * Recall that a NULL @buf is configfs requesting the size of
255 * the buffer.
256 */
257 if (!buf)
258 return len;
259 return memory_read_from_buffer(buf, count, &offset, out, len);
260 }
261
read_cached_report(struct tsm_report * report,void * buf,size_t count,enum tsm_data_select select)262 static ssize_t read_cached_report(struct tsm_report *report, void *buf,
263 size_t count, enum tsm_data_select select)
264 {
265 struct tsm_report_state *state = to_state(report);
266
267 guard(rwsem_read)(&tsm_rwsem);
268 if (!report->desc.inblob_len)
269 return -EINVAL;
270
271 /*
272 * A given TSM backend always fills in ->outblob regardless of
273 * whether the report includes an auxblob/manifestblob or not.
274 */
275 if (!report->outblob ||
276 state->read_generation != state->write_generation)
277 return -EWOULDBLOCK;
278
279 return __read_report(report, buf, count, select);
280 }
281
tsm_report_read(struct tsm_report * report,void * buf,size_t count,enum tsm_data_select select)282 static ssize_t tsm_report_read(struct tsm_report *report, void *buf,
283 size_t count, enum tsm_data_select select)
284 {
285 struct tsm_report_state *state = to_state(report);
286 const struct tsm_report_ops *ops;
287 ssize_t rc;
288
289 /* try to read from the existing report if present and valid... */
290 rc = read_cached_report(report, buf, count, select);
291 if (rc >= 0 || rc != -EWOULDBLOCK)
292 return rc;
293
294 /* slow path, report may need to be regenerated... */
295 guard(rwsem_write)(&tsm_rwsem);
296 ops = provider.ops;
297 if (!ops)
298 return -ENXIO;
299 if (!report->desc.inblob_len)
300 return -EINVAL;
301
302 /* did another thread already generate this report? */
303 if (report->outblob &&
304 state->read_generation == state->write_generation)
305 goto out;
306
307 kvfree(report->outblob);
308 kvfree(report->auxblob);
309 kvfree(report->manifestblob);
310 report->outblob = NULL;
311 report->auxblob = NULL;
312 report->manifestblob = NULL;
313 rc = ops->report_new(report, provider.data);
314 if (rc < 0)
315 return rc;
316 state->read_generation = state->write_generation;
317 out:
318 return __read_report(report, buf, count, select);
319 }
320
tsm_report_outblob_read(struct config_item * cfg,void * buf,size_t count)321 static ssize_t tsm_report_outblob_read(struct config_item *cfg, void *buf,
322 size_t count)
323 {
324 struct tsm_report *report = to_tsm_report(cfg);
325
326 return tsm_report_read(report, buf, count, TSM_REPORT);
327 }
328 CONFIGFS_BIN_ATTR_RO(tsm_report_, outblob, NULL, TSM_REPORT_OUTBLOB_MAX);
329
tsm_report_auxblob_read(struct config_item * cfg,void * buf,size_t count)330 static ssize_t tsm_report_auxblob_read(struct config_item *cfg, void *buf,
331 size_t count)
332 {
333 struct tsm_report *report = to_tsm_report(cfg);
334
335 return tsm_report_read(report, buf, count, TSM_CERTS);
336 }
337 CONFIGFS_BIN_ATTR_RO(tsm_report_, auxblob, NULL, TSM_REPORT_OUTBLOB_MAX);
338
tsm_report_manifestblob_read(struct config_item * cfg,void * buf,size_t count)339 static ssize_t tsm_report_manifestblob_read(struct config_item *cfg, void *buf,
340 size_t count)
341 {
342 struct tsm_report *report = to_tsm_report(cfg);
343
344 return tsm_report_read(report, buf, count, TSM_MANIFEST);
345 }
346 CONFIGFS_BIN_ATTR_RO(tsm_report_, manifestblob, NULL, TSM_REPORT_OUTBLOB_MAX);
347
348 static struct configfs_attribute *tsm_report_attrs[] = {
349 [TSM_REPORT_GENERATION] = &tsm_report_attr_generation,
350 [TSM_REPORT_PROVIDER] = &tsm_report_attr_provider,
351 [TSM_REPORT_PRIVLEVEL] = &tsm_report_attr_privlevel,
352 [TSM_REPORT_PRIVLEVEL_FLOOR] = &tsm_report_attr_privlevel_floor,
353 [TSM_REPORT_SERVICE_PROVIDER] = &tsm_report_attr_service_provider,
354 [TSM_REPORT_SERVICE_GUID] = &tsm_report_attr_service_guid,
355 [TSM_REPORT_SERVICE_MANIFEST_VER] = &tsm_report_attr_service_manifest_version,
356 NULL,
357 };
358
359 static struct configfs_bin_attribute *tsm_report_bin_attrs[] = {
360 [TSM_REPORT_INBLOB] = &tsm_report_attr_inblob,
361 [TSM_REPORT_OUTBLOB] = &tsm_report_attr_outblob,
362 [TSM_REPORT_AUXBLOB] = &tsm_report_attr_auxblob,
363 [TSM_REPORT_MANIFESTBLOB] = &tsm_report_attr_manifestblob,
364 NULL,
365 };
366
tsm_report_item_release(struct config_item * cfg)367 static void tsm_report_item_release(struct config_item *cfg)
368 {
369 struct tsm_report *report = to_tsm_report(cfg);
370 struct tsm_report_state *state = to_state(report);
371
372 kvfree(report->manifestblob);
373 kvfree(report->auxblob);
374 kvfree(report->outblob);
375 kfree(report->desc.service_provider);
376 kfree(state);
377 }
378
379 static struct configfs_item_operations tsm_report_item_ops = {
380 .release = tsm_report_item_release,
381 };
382
tsm_report_is_visible(struct config_item * item,struct configfs_attribute * attr,int n)383 static bool tsm_report_is_visible(struct config_item *item,
384 struct configfs_attribute *attr, int n)
385 {
386 guard(rwsem_read)(&tsm_rwsem);
387 if (!provider.ops)
388 return false;
389
390 if (!provider.ops->report_attr_visible)
391 return true;
392
393 return provider.ops->report_attr_visible(n);
394 }
395
tsm_report_is_bin_visible(struct config_item * item,struct configfs_bin_attribute * attr,int n)396 static bool tsm_report_is_bin_visible(struct config_item *item,
397 struct configfs_bin_attribute *attr, int n)
398 {
399 guard(rwsem_read)(&tsm_rwsem);
400 if (!provider.ops)
401 return false;
402
403 if (!provider.ops->report_bin_attr_visible)
404 return true;
405
406 return provider.ops->report_bin_attr_visible(n);
407 }
408
409 static struct configfs_group_operations tsm_report_attr_group_ops = {
410 .is_visible = tsm_report_is_visible,
411 .is_bin_visible = tsm_report_is_bin_visible,
412 };
413
414 static const struct config_item_type tsm_report_type = {
415 .ct_owner = THIS_MODULE,
416 .ct_bin_attrs = tsm_report_bin_attrs,
417 .ct_attrs = tsm_report_attrs,
418 .ct_item_ops = &tsm_report_item_ops,
419 .ct_group_ops = &tsm_report_attr_group_ops,
420 };
421
tsm_report_make_item(struct config_group * group,const char * name)422 static struct config_item *tsm_report_make_item(struct config_group *group,
423 const char *name)
424 {
425 struct tsm_report_state *state;
426
427 guard(rwsem_read)(&tsm_rwsem);
428 if (!provider.ops)
429 return ERR_PTR(-ENXIO);
430
431 state = kzalloc(sizeof(*state), GFP_KERNEL);
432 if (!state)
433 return ERR_PTR(-ENOMEM);
434
435 atomic_inc(&provider.count);
436 config_item_init_type_name(&state->cfg, name, &tsm_report_type);
437 return &state->cfg;
438 }
439
tsm_report_drop_item(struct config_group * group,struct config_item * item)440 static void tsm_report_drop_item(struct config_group *group, struct config_item *item)
441 {
442 config_item_put(item);
443 atomic_dec(&provider.count);
444 }
445
446 static struct configfs_group_operations tsm_report_group_ops = {
447 .make_item = tsm_report_make_item,
448 .drop_item = tsm_report_drop_item,
449 };
450
451 static const struct config_item_type tsm_reports_type = {
452 .ct_owner = THIS_MODULE,
453 .ct_group_ops = &tsm_report_group_ops,
454 };
455
456 static const struct config_item_type tsm_root_group_type = {
457 .ct_owner = THIS_MODULE,
458 };
459
460 static struct configfs_subsystem tsm_configfs = {
461 .su_group = {
462 .cg_item = {
463 .ci_namebuf = "tsm",
464 .ci_type = &tsm_root_group_type,
465 },
466 },
467 .su_mutex = __MUTEX_INITIALIZER(tsm_configfs.su_mutex),
468 };
469
tsm_report_register(const struct tsm_report_ops * ops,void * priv)470 int tsm_report_register(const struct tsm_report_ops *ops, void *priv)
471 {
472 const struct tsm_report_ops *conflict;
473
474 guard(rwsem_write)(&tsm_rwsem);
475 conflict = provider.ops;
476 if (conflict) {
477 pr_err("\"%s\" ops already registered\n", conflict->name);
478 return -EBUSY;
479 }
480
481 if (atomic_read(&provider.count)) {
482 pr_err("configfs/tsm/report not empty\n");
483 return -EBUSY;
484 }
485
486 provider.ops = ops;
487 provider.data = priv;
488 return 0;
489 }
490 EXPORT_SYMBOL_GPL(tsm_report_register);
491
tsm_report_unregister(const struct tsm_report_ops * ops)492 int tsm_report_unregister(const struct tsm_report_ops *ops)
493 {
494 guard(rwsem_write)(&tsm_rwsem);
495 if (ops != provider.ops)
496 return -EBUSY;
497 if (atomic_read(&provider.count))
498 pr_warn("\"%s\" unregistered with items present in configfs/tsm/report\n",
499 provider.ops->name);
500 provider.ops = NULL;
501 provider.data = NULL;
502 return 0;
503 }
504 EXPORT_SYMBOL_GPL(tsm_report_unregister);
505
506 static struct config_group *tsm_report_group;
507
tsm_report_init(void)508 static int __init tsm_report_init(void)
509 {
510 struct config_group *root = &tsm_configfs.su_group;
511 struct config_group *tsm;
512 int rc;
513
514 config_group_init(root);
515 rc = configfs_register_subsystem(&tsm_configfs);
516 if (rc)
517 return rc;
518
519 tsm = configfs_register_default_group(root, "report",
520 &tsm_reports_type);
521 if (IS_ERR(tsm)) {
522 configfs_unregister_subsystem(&tsm_configfs);
523 return PTR_ERR(tsm);
524 }
525 tsm_report_group = tsm;
526
527 return 0;
528 }
529 module_init(tsm_report_init);
530
tsm_report_exit(void)531 static void __exit tsm_report_exit(void)
532 {
533 configfs_unregister_default_group(tsm_report_group);
534 configfs_unregister_subsystem(&tsm_configfs);
535 }
536 module_exit(tsm_report_exit);
537
538 MODULE_LICENSE("GPL");
539 MODULE_DESCRIPTION("Provide Trusted Security Module attestation reports via configfs");
540