aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ubifs/sb.c70
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
520static 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)
527int ubifs_write_sb_node(struct ubifs_info *c, struct ubifs_sb_node *sup) 586int 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);