summaryrefslogtreecommitdiff
path: root/fs/bcachefs/dirent.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/bcachefs/dirent.c')
-rw-r--r--fs/bcachefs/dirent.c21
1 files changed, 17 insertions, 4 deletions
diff --git a/fs/bcachefs/dirent.c b/fs/bcachefs/dirent.c
index a87c4e5f089d..6f9eb88c7dba 100644
--- a/fs/bcachefs/dirent.c
+++ b/fs/bcachefs/dirent.c
@@ -15,10 +15,18 @@
static unsigned bch2_dirent_name_bytes(struct bkey_s_c_dirent d)
{
- unsigned len = bkey_val_bytes(d.k) -
- offsetof(struct bch_dirent, d_name);
-
- return strnlen(d.v->d_name, len);
+ unsigned bkey_u64s = bkey_val_u64s(d.k);
+ unsigned bkey_bytes = bkey_u64s * sizeof(u64);
+ u64 last_u64 = ((u64*)d.v)[bkey_u64s - 1];
+#if CPU_BIG_ENDIAN
+ unsigned trailing_nuls = last_u64 ? __builtin_ctzll(last_u64) / 8 : 64 / 8;
+#else
+ unsigned trailing_nuls = last_u64 ? __builtin_clzll(last_u64) / 8 : 64 / 8;
+#endif
+
+ return bkey_bytes -
+ offsetof(struct bch_dirent, d_name) -
+ trailing_nuls;
}
struct qstr bch2_dirent_get_name(struct bkey_s_c_dirent d)
@@ -113,6 +121,11 @@ int bch2_dirent_invalid(const struct bch_fs *c, struct bkey_s_c k,
return -BCH_ERR_invalid_bkey;
}
+ if (d_name.len != strnlen(d_name.name, d_name.len)) {
+ prt_printf(err, "dirent has stray data after name's NUL");
+ return -BCH_ERR_invalid_bkey;
+ }
+
if (d_name.len == 1 && !memcmp(d_name.name, ".", 1)) {
prt_printf(err, "invalid name");
return -BCH_ERR_invalid_bkey;