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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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