summaryrefslogtreecommitdiff
path: root/fs/ubifs/super.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ubifs/super.c')
-rw-r--r--fs/ubifs/super.c91
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;