diff options
Diffstat (limited to 'fs/ubifs/super.c')
-rw-r--r-- | fs/ubifs/super.c | 91 |
1 files changed, 75 insertions, 16 deletions
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index fec62e9dfbe6..1fac1133dadd 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -579,6 +579,9 @@ static int init_constants_early(struct ubifs_info *c) c->ranges[UBIFS_REF_NODE].len = UBIFS_REF_NODE_SZ; c->ranges[UBIFS_TRUN_NODE].len = UBIFS_TRUN_NODE_SZ; c->ranges[UBIFS_CS_NODE].len = UBIFS_CS_NODE_SZ; + c->ranges[UBIFS_AUTH_NODE].min_len = UBIFS_AUTH_NODE_SZ; + c->ranges[UBIFS_AUTH_NODE].max_len = UBIFS_AUTH_NODE_SZ + + UBIFS_MAX_HMAC_LEN; c->ranges[UBIFS_INO_NODE].min_len = UBIFS_INO_NODE_SZ; c->ranges[UBIFS_INO_NODE].max_len = UBIFS_MAX_INO_NODE_SZ; @@ -816,6 +819,9 @@ static int alloc_wbufs(struct ubifs_info *c) c->jheads[i].wbuf.sync_callback = &bud_wbuf_callback; c->jheads[i].wbuf.jhead = i; c->jheads[i].grouped = 1; + c->jheads[i].log_hash = ubifs_hash_get_desc(c); + if (IS_ERR(c->jheads[i].log_hash)) + goto out; } /* @@ -826,6 +832,12 @@ static int alloc_wbufs(struct ubifs_info *c) c->jheads[GCHD].grouped = 0; return 0; + +out: + while (i--) + kfree(c->jheads[i].log_hash); + + return err; } /** @@ -840,6 +852,7 @@ static void free_wbufs(struct ubifs_info *c) for (i = 0; i < c->jhead_cnt; i++) { kfree(c->jheads[i].wbuf.buf); kfree(c->jheads[i].wbuf.inodes); + kfree(c->jheads[i].log_hash); } kfree(c->jheads); c->jheads = NULL; @@ -924,6 +937,8 @@ static int check_volume_empty(struct ubifs_info *c) * Opt_no_chk_data_crc: do not check CRCs when reading data nodes * Opt_override_compr: override default compressor * Opt_assert: set ubifs_assert() action + * Opt_auth_key: The key name used for authentication + * Opt_auth_hash_name: The hash type used for authentication * Opt_err: just end of array marker */ enum { @@ -935,6 +950,8 @@ enum { Opt_no_chk_data_crc, Opt_override_compr, Opt_assert, + Opt_auth_key, + Opt_auth_hash_name, Opt_ignore, Opt_err, }; @@ -947,6 +964,8 @@ static const match_table_t tokens = { {Opt_chk_data_crc, "chk_data_crc"}, {Opt_no_chk_data_crc, "no_chk_data_crc"}, {Opt_override_compr, "compr=%s"}, + {Opt_auth_key, "auth_key=%s"}, + {Opt_auth_hash_name, "auth_hash_name=%s"}, {Opt_ignore, "ubi=%s"}, {Opt_ignore, "vol=%s"}, {Opt_assert, "assert=%s"}, @@ -1070,6 +1089,16 @@ static int ubifs_parse_options(struct ubifs_info *c, char *options, kfree(act); break; } + case Opt_auth_key: + c->auth_key_name = kstrdup(args[0].from, GFP_KERNEL); + if (!c->auth_key_name) + return -ENOMEM; + break; + case Opt_auth_hash_name: + c->auth_hash_name = kstrdup(args[0].from, GFP_KERNEL); + if (!c->auth_hash_name) + return -ENOMEM; + break; case Opt_ignore: break; default: @@ -1249,6 +1278,19 @@ static int mount_ubifs(struct ubifs_info *c) c->mounting = 1; + if (c->auth_key_name) { + if (IS_ENABLED(CONFIG_UBIFS_FS_AUTHENTICATION)) { + err = ubifs_init_authentication(c); + if (err) + goto out_free; + } else { + ubifs_err(c, "auth_key_name, but UBIFS is built without" + " authentication support"); + err = -EINVAL; + goto out_free; + } + } + err = ubifs_read_superblock(c); if (err) goto out_free; @@ -1367,12 +1409,21 @@ static int mount_ubifs(struct ubifs_info *c) } if (c->need_recovery) { - err = ubifs_recover_size(c); - if (err) - goto out_orphans; + if (!ubifs_authenticated(c)) { + err = ubifs_recover_size(c, true); + if (err) + goto out_orphans; + } + err = ubifs_rcvry_gc_commit(c); if (err) goto out_orphans; + + if (ubifs_authenticated(c)) { + err = ubifs_recover_size(c, false); + if (err) + goto out_orphans; + } } else { err = take_gc_lnum(c); if (err) @@ -1391,7 +1442,7 @@ static int mount_ubifs(struct ubifs_info *c) if (err) goto out_orphans; } else if (c->need_recovery) { - err = ubifs_recover_size(c); + err = ubifs_recover_size(c, false); if (err) goto out_orphans; } else { @@ -1557,7 +1608,10 @@ static void ubifs_umount(struct ubifs_info *c) free_wbufs(c); free_orphans(c); ubifs_lpt_free(c, 0); + ubifs_exit_authentication(c); + kfree(c->auth_key_name); + kfree(c->auth_hash_name); kfree(c->cbuf); kfree(c->rcvrd_mst_node); kfree(c->mst_node); @@ -1605,16 +1659,10 @@ static int ubifs_remount_rw(struct ubifs_info *c) goto out; if (c->old_leb_cnt != c->leb_cnt) { - struct ubifs_sb_node *sup; + struct ubifs_sb_node *sup = c->sup_node; - sup = ubifs_read_sb_node(c); - if (IS_ERR(sup)) { - err = PTR_ERR(sup); - goto out; - } sup->leb_cnt = cpu_to_le32(c->leb_cnt); err = ubifs_write_sb_node(c, sup); - kfree(sup); if (err) goto out; } @@ -1624,9 +1672,11 @@ static int ubifs_remount_rw(struct ubifs_info *c) err = ubifs_write_rcvrd_mst_node(c); if (err) goto out; - err = ubifs_recover_size(c); - if (err) - goto out; + if (!ubifs_authenticated(c)) { + err = ubifs_recover_size(c, true); + if (err) + goto out; + } err = ubifs_clean_lebs(c, c->sbuf); if (err) goto out; @@ -1692,10 +1742,19 @@ static int ubifs_remount_rw(struct ubifs_info *c) goto out; } - if (c->need_recovery) + if (c->need_recovery) { err = ubifs_rcvry_gc_commit(c); - else + if (err) + goto out; + + if (ubifs_authenticated(c)) { + err = ubifs_recover_size(c, false); + if (err) + goto out; + } + } else { err = ubifs_leb_unmap(c, c->gc_lnum); + } if (err) goto out; |