summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2018-09-07 14:36:37 +0200
committerRichard Weinberger <richard@nod.at>2018-10-23 13:48:40 +0200
commit6f06d96fdf624be3e1d65c6100704a1fd79a30b7 (patch)
tree9f73bc0c8b651130327943b8b198aa781513e50e
parent6a98bc4614de8fac8c6d520a6b20b194e23c9936 (diff)
downloadlinux-0-day-6f06d96fdf624be3e1d65c6100704a1fd79a30b7.tar.gz
linux-0-day-6f06d96fdf624be3e1d65c6100704a1fd79a30b7.tar.xz
ubifs: Add auth nodes to garbage collector journal head
To be able to authenticate the garbage collector journal head add authentication nodes to the buds the garbage collector creates. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> Signed-off-by: Richard Weinberger <richard@nod.at>
-rw-r--r--fs/ubifs/gc.c46
1 files changed, 43 insertions, 3 deletions
diff --git a/fs/ubifs/gc.c b/fs/ubifs/gc.c
index 399d764f83cb1..bf75fdc76fc35 100644
--- a/fs/ubifs/gc.c
+++ b/fs/ubifs/gc.c
@@ -365,12 +365,13 @@ static int move_nodes(struct ubifs_info *c, struct ubifs_scan_leb *sleb)
/* Write nodes to their new location. Use the first-fit strategy */
while (1) {
- int avail;
+ int avail, moved = 0;
struct ubifs_scan_node *snod, *tmp;
/* Move data nodes */
list_for_each_entry_safe(snod, tmp, &sleb->nodes, list) {
- avail = c->leb_size - wbuf->offs - wbuf->used;
+ avail = c->leb_size - wbuf->offs - wbuf->used -
+ ubifs_auth_node_sz(c);
if (snod->len > avail)
/*
* Do not skip data nodes in order to optimize
@@ -378,14 +379,21 @@ static int move_nodes(struct ubifs_info *c, struct ubifs_scan_leb *sleb)
*/
break;
+ err = ubifs_shash_update(c, c->jheads[GCHD].log_hash,
+ snod->node, snod->len);
+ if (err)
+ goto out;
+
err = move_node(c, sleb, snod, wbuf);
if (err)
goto out;
+ moved = 1;
}
/* Move non-data nodes */
list_for_each_entry_safe(snod, tmp, &nondata, list) {
- avail = c->leb_size - wbuf->offs - wbuf->used;
+ avail = c->leb_size - wbuf->offs - wbuf->used -
+ ubifs_auth_node_sz(c);
if (avail < min)
break;
@@ -403,9 +411,41 @@ static int move_nodes(struct ubifs_info *c, struct ubifs_scan_leb *sleb)
continue;
}
+ err = ubifs_shash_update(c, c->jheads[GCHD].log_hash,
+ snod->node, snod->len);
+ if (err)
+ goto out;
+
err = move_node(c, sleb, snod, wbuf);
if (err)
goto out;
+ moved = 1;
+ }
+
+ if (ubifs_authenticated(c) && moved) {
+ struct ubifs_auth_node *auth;
+
+ auth = kmalloc(ubifs_auth_node_sz(c), GFP_NOFS);
+ if (!auth) {
+ err = -ENOMEM;
+ goto out;
+ }
+
+ err = ubifs_prepare_auth_node(c, auth,
+ c->jheads[GCHD].log_hash);
+ if (err) {
+ kfree(auth);
+ goto out;
+ }
+
+ err = ubifs_wbuf_write_nolock(wbuf, auth,
+ ubifs_auth_node_sz(c));
+ if (err) {
+ kfree(auth);
+ goto out;
+ }
+
+ ubifs_add_dirt(c, wbuf->lnum, ubifs_auth_node_sz(c));
}
if (list_empty(&sleb->nodes) && list_empty(&nondata))