diff options
| -rw-r--r-- | fs/ubifs/sb.c | 70 |
1 files changed, 69 insertions, 1 deletions
diff --git a/fs/ubifs/sb.c b/fs/ubifs/sb.c index 572756579532..7f0967771c9f 100644 --- a/fs/ubifs/sb.c +++ b/fs/ubifs/sb.c | |||
| @@ -517,6 +517,65 @@ static struct ubifs_sb_node *ubifs_read_sb_node(struct ubifs_info *c) | |||
| 517 | return sup; | 517 | return sup; |
| 518 | } | 518 | } |
| 519 | 519 | ||
| 520 | static int authenticate_sb_node(struct ubifs_info *c, | ||
| 521 | const struct ubifs_sb_node *sup) | ||
| 522 | { | ||
| 523 | unsigned int sup_flags = le32_to_cpu(sup->flags); | ||
| 524 | u8 hmac_wkm[UBIFS_HMAC_ARR_SZ]; | ||
| 525 | int authenticated = !!(sup_flags & UBIFS_FLG_AUTHENTICATION); | ||
| 526 | int hash_algo; | ||
| 527 | int err; | ||
| 528 | |||
| 529 | if (c->authenticated && !authenticated) { | ||
| 530 | ubifs_err(c, "authenticated FS forced, but found FS without authentication"); | ||
| 531 | return -EINVAL; | ||
| 532 | } | ||
| 533 | |||
| 534 | if (!c->authenticated && authenticated) { | ||
| 535 | ubifs_err(c, "authenticated FS found, but no key given"); | ||
| 536 | return -EINVAL; | ||
| 537 | } | ||
| 538 | |||
| 539 | ubifs_msg(c, "Mounting in %sauthenticated mode", | ||
| 540 | c->authenticated ? "" : "un"); | ||
| 541 | |||
| 542 | if (!c->authenticated) | ||
| 543 | return 0; | ||
| 544 | |||
| 545 | if (!IS_ENABLED(CONFIG_UBIFS_FS_AUTHENTICATION)) | ||
| 546 | return -EOPNOTSUPP; | ||
| 547 | |||
| 548 | hash_algo = le16_to_cpu(sup->hash_algo); | ||
| 549 | if (hash_algo >= HASH_ALGO__LAST) { | ||
| 550 | ubifs_err(c, "superblock uses unknown hash algo %d", | ||
| 551 | hash_algo); | ||
| 552 | return -EINVAL; | ||
| 553 | } | ||
| 554 | |||
| 555 | if (strcmp(hash_algo_name[hash_algo], c->auth_hash_name)) { | ||
| 556 | ubifs_err(c, "This filesystem uses %s for hashing," | ||
| 557 | " but %s is specified", hash_algo_name[hash_algo], | ||
| 558 | c->auth_hash_name); | ||
| 559 | return -EINVAL; | ||
| 560 | } | ||
| 561 | |||
| 562 | err = ubifs_hmac_wkm(c, hmac_wkm); | ||
| 563 | if (err) | ||
| 564 | return err; | ||
| 565 | |||
| 566 | if (ubifs_check_hmac(c, hmac_wkm, sup->hmac_wkm)) { | ||
| 567 | ubifs_err(c, "provided key does not fit"); | ||
| 568 | return -ENOKEY; | ||
| 569 | } | ||
| 570 | |||
| 571 | err = ubifs_node_verify_hmac(c, sup, sizeof(*sup), | ||
| 572 | offsetof(struct ubifs_sb_node, hmac)); | ||
| 573 | if (err) | ||
| 574 | ubifs_err(c, "Failed to authenticate superblock: %d", err); | ||
| 575 | |||
| 576 | return err; | ||
| 577 | } | ||
| 578 | |||
| 520 | /** | 579 | /** |
| 521 | * ubifs_write_sb_node - write superblock node. | 580 | * ubifs_write_sb_node - write superblock node. |
| 522 | * @c: UBIFS file-system description object | 581 | * @c: UBIFS file-system description object |
| @@ -527,8 +586,13 @@ static struct ubifs_sb_node *ubifs_read_sb_node(struct ubifs_info *c) | |||
| 527 | int ubifs_write_sb_node(struct ubifs_info *c, struct ubifs_sb_node *sup) | 586 | int ubifs_write_sb_node(struct ubifs_info *c, struct ubifs_sb_node *sup) |
| 528 | { | 587 | { |
| 529 | int len = ALIGN(UBIFS_SB_NODE_SZ, c->min_io_size); | 588 | int len = ALIGN(UBIFS_SB_NODE_SZ, c->min_io_size); |
| 589 | int err; | ||
| 590 | |||
| 591 | err = ubifs_prepare_node_hmac(c, sup, UBIFS_SB_NODE_SZ, | ||
| 592 | offsetof(struct ubifs_sb_node, hmac), 1); | ||
| 593 | if (err) | ||
| 594 | return err; | ||
| 530 | 595 | ||
| 531 | ubifs_prepare_node(c, sup, UBIFS_SB_NODE_SZ, 1); | ||
| 532 | return ubifs_leb_change(c, UBIFS_SB_LNUM, sup, len); | 596 | return ubifs_leb_change(c, UBIFS_SB_LNUM, sup, len); |
| 533 | } | 597 | } |
| 534 | 598 | ||
| @@ -642,6 +706,10 @@ int ubifs_read_superblock(struct ubifs_info *c) | |||
| 642 | c->double_hash = !!(sup_flags & UBIFS_FLG_DOUBLE_HASH); | 706 | c->double_hash = !!(sup_flags & UBIFS_FLG_DOUBLE_HASH); |
| 643 | c->encrypted = !!(sup_flags & UBIFS_FLG_ENCRYPTION); | 707 | c->encrypted = !!(sup_flags & UBIFS_FLG_ENCRYPTION); |
| 644 | 708 | ||
| 709 | err = authenticate_sb_node(c, sup); | ||
| 710 | if (err) | ||
| 711 | goto out; | ||
| 712 | |||
| 645 | if ((sup_flags & ~UBIFS_FLG_MASK) != 0) { | 713 | if ((sup_flags & ~UBIFS_FLG_MASK) != 0) { |
| 646 | ubifs_err(c, "Unknown feature flags found: %#x", | 714 | ubifs_err(c, "Unknown feature flags found: %#x", |
| 647 | sup_flags & ~UBIFS_FLG_MASK); | 715 | sup_flags & ~UBIFS_FLG_MASK); |
