summaryrefslogtreecommitdiffstats
path: root/fs/ubifs/sb.c
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2018-10-02 08:33:08 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2019-04-24 13:24:57 +0200
commit49b2ae70344bc3212aa268576cb15d903b32558e (patch)
tree33bcab6833dd5c3d6fbbb25e5bae3468052f10b8 /fs/ubifs/sb.c
parentea569a0afd6a2e9a84418cd18ddeaeefaa5eae39 (diff)
downloadbarebox-49b2ae70344bc3212aa268576cb15d903b32558e.tar.gz
barebox-49b2ae70344bc3212aa268576cb15d903b32558e.tar.xz
fs: ubifs: Add authentication support
This adds UBIFS authentication support. For now, we do not do any authentication even on authenticated UBIFS images. Since this behaviour is not what the user normally expects when mounting authenticated images we only do this when the user explicitly allows it in "global.ubifs.allow_authenticated_unauthenticated". If the flag is false then we refuse mounting such an image and return -EPERM instead. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'fs/ubifs/sb.c')
-rw-r--r--fs/ubifs/sb.c42
1 files changed, 40 insertions, 2 deletions
diff --git a/fs/ubifs/sb.c b/fs/ubifs/sb.c
index a13f092eb0..9eb8064d72 100644
--- a/fs/ubifs/sb.c
+++ b/fs/ubifs/sb.c
@@ -220,7 +220,7 @@ failed:
* code. Note, the user of this function is responsible of kfree()'ing the
* returned superblock buffer.
*/
-struct ubifs_sb_node *ubifs_read_sb_node(struct ubifs_info *c)
+static struct ubifs_sb_node *ubifs_read_sb_node(struct ubifs_info *c)
{
struct ubifs_sb_node *sup;
int err;
@@ -239,6 +239,39 @@ struct ubifs_sb_node *ubifs_read_sb_node(struct ubifs_info *c)
return sup;
}
+static int authenticate_sb_node(struct ubifs_info *c,
+ const struct ubifs_sb_node *sup)
+{
+ unsigned int sup_flags = le32_to_cpu(sup->flags);
+ int authenticated = !!(sup_flags & UBIFS_FLG_AUTHENTICATION);
+ int hash_algo;
+ struct digest *digest;
+
+ if (!authenticated)
+ return 0;
+
+ if (!ubifs_allow_authenticated_unauthenticated)
+ return -EPERM;
+
+ hash_algo = le16_to_cpu(sup->hash_algo);
+ if (hash_algo >= HASH_ALGO__LAST) {
+ ubifs_err(c, "superblock uses unknown hash algo %d",
+ hash_algo);
+ return -EINVAL;
+ }
+
+ digest = digest_alloc_by_algo(hash_algo);
+ if (!digest) {
+ ubifs_err(c, "Cannot allocate hash algo %d",
+ hash_algo);
+ return -EINVAL;
+ }
+
+ c->hash_len = digest_length(digest);
+
+ return 0;
+}
+
/*
* removed in barebox
int ubifs_write_sb_node(struct ubifs_info *c, struct ubifs_sb_node *sup)
@@ -266,6 +299,8 @@ int ubifs_read_superblock(struct ubifs_info *c)
if (IS_ERR(sup))
return PTR_ERR(sup);
+ c->sup_node = sup;
+
c->fmt_version = le32_to_cpu(sup->fmt_version);
c->ro_compat_version = le32_to_cpu(sup->ro_compat_version);
@@ -349,6 +384,10 @@ int ubifs_read_superblock(struct ubifs_info *c)
c->double_hash = !!(sup_flags & UBIFS_FLG_DOUBLE_HASH);
c->encrypted = !!(sup_flags & UBIFS_FLG_ENCRYPTION);
+ err = authenticate_sb_node(c, sup);
+ if (err)
+ goto out;
+
if ((sup_flags & ~UBIFS_FLG_MASK) != 0) {
ubifs_err(c, "Unknown feature flags found: %#x",
sup_flags & ~UBIFS_FLG_MASK);
@@ -389,7 +428,6 @@ int ubifs_read_superblock(struct ubifs_info *c)
err = validate_sb(c, sup);
out:
- kfree(sup);
return err;
}