[RFC PATCH mtd-utils 009/110] mkfs.ubifs: Fix incorrect dir size calculation in encryption scenario

From: Zhihao Cheng
Date: Fri Jun 07 2024 - 00:34:03 EST


The size of directory should be the total length of encrypted entry name,
otherwise it could trigger errors while checking filesystem:
dbg_check_filesystem [ubifs]: directory inode 89 size is 352, but
calculated size is 400

Fixes: 4c55918dd747d ("Implement filename encryption")
Signed-off-by: Zhihao Cheng <chengzhihao1@xxxxxxxxxx>
---
ubifs-utils/mkfs.ubifs/mkfs.ubifs.c | 35 +++++++++++++++++++----------------
1 file changed, 19 insertions(+), 16 deletions(-)

diff --git a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
index 8bf073ce..25c49967 100644
--- a/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
+++ b/ubifs-utils/mkfs.ubifs/mkfs.ubifs.c
@@ -1723,15 +1723,17 @@ static void set_dent_cookie(struct ubifs_dent_node *dent)
* @name: directory entry name
* @inum: target inode number of the directory entry
* @type: type of the target inode
+ * @kname_len: the length of name stored in the directory entry node is
+ * returned here
*/
static int add_dent_node(ino_t dir_inum, const char *name, ino_t inum,
- unsigned char type, struct fscrypt_context *fctx)
+ unsigned char type, struct fscrypt_context *fctx,
+ int *kname_len)
{
struct ubifs_dent_node *dent = node_buf;
union ubifs_key key;
struct qstr dname;
char *kname;
- int kname_len;
int len;

dbg_msg(3, "%s ino %lu type %u dir ino %lu", name, (unsigned long)inum,
@@ -1749,7 +1751,7 @@ static int add_dent_node(ino_t dir_inum, const char *name, ino_t inum,
set_dent_cookie(dent);

if (!fctx) {
- kname_len = dname.len;
+ *kname_len = dname.len;
kname = strdup(name);
if (!kname)
return errmsg("cannot allocate memory");
@@ -1765,18 +1767,18 @@ static int add_dent_node(ino_t dir_inum, const char *name, ino_t inum,
if (ret < 0)
return ret;

- kname_len = ret;
+ *kname_len = ret;
}

- dent_key_init(c, &key, dir_inum, kname, kname_len);
- dent->nlen = cpu_to_le16(kname_len);
- memcpy(dent->name, kname, kname_len);
- dent->name[kname_len] = '\0';
- len = UBIFS_DENT_NODE_SZ + kname_len + 1;
+ dent_key_init(c, &key, dir_inum, kname, *kname_len);
+ dent->nlen = cpu_to_le16(*kname_len);
+ memcpy(dent->name, kname, *kname_len);
+ dent->name[*kname_len] = '\0';
+ len = UBIFS_DENT_NODE_SZ + *kname_len + 1;

key_write(&key, dent->key);

- return add_node(&key, kname, kname_len, dent, len);
+ return add_node(&key, kname, *kname_len, dent, len);
}

/**
@@ -2026,7 +2028,7 @@ static int add_directory(const char *dir_name, ino_t dir_inum, struct stat *st,
{
struct dirent *entry;
DIR *dir = NULL;
- int err = 0;
+ int kname_len, err = 0;
loff_t size = UBIFS_INO_NODE_SZ;
char *name = NULL;
unsigned int nlink = 2;
@@ -2139,13 +2141,13 @@ static int add_directory(const char *dir_name, ino_t dir_inum, struct stat *st,
goto out_free;
}

- err = add_dent_node(dir_inum, entry->d_name, inum, type, fctx);
+ err = add_dent_node(dir_inum, entry->d_name, inum, type, fctx,
+ &kname_len);
if (err) {
free_fscrypt_context(new_fctx);
goto out_free;
}
- size += ALIGN(UBIFS_DENT_NODE_SZ + strlen(entry->d_name) + 1,
- 8);
+ size += ALIGN(UBIFS_DENT_NODE_SZ + kname_len + 1, 8);

if (new_fctx)
free_fscrypt_context(new_fctx);
@@ -2210,13 +2212,14 @@ static int add_directory(const char *dir_name, ino_t dir_inum, struct stat *st,
goto out_free;
}

- err = add_dent_node(dir_inum, nh_elt->name, inum, type, fctx);
+ err = add_dent_node(dir_inum, nh_elt->name, inum, type, fctx,
+ &kname_len);
if (err) {
free_fscrypt_context(new_fctx);
goto out_free;
}

- size += ALIGN(UBIFS_DENT_NODE_SZ + strlen(nh_elt->name) + 1, 8);
+ size += ALIGN(UBIFS_DENT_NODE_SZ + kname_len + 1, 8);

nh_elt = next_name_htbl_element(ph_elt, &itr);
if (new_fctx)
--
2.13.6