I don't yet know which xfields will have which flags, but add some basic
checks that are common to all of them.
apfsck/dir.c | 2 ++
apfsck/inode.c | 16 ++++++++++++++++
apfsck/inode.h | 11 +++++++++++
3 files changed, 29 insertions(+)
diff --git a/apfsck/dir.c b/apfsck/dir.c
index eaaa7e9..af50320 100644
--- a/apfsck/dir.c
+++ b/apfsck/dir.c
@@ -70,6 +70,8 @@ static void parse_dentry_xfields(struct apfs_xf_blob *xblob, int len,
report("Dentry record",
"value size incompatible with xfields.");
+ check_xfield_flags(xfield->x_flags);
+
if (xfield->x_type != APFS_DREC_EXT_TYPE_SIBLING_ID)
report("Dentry xfield", "invalid type.");
xlen = read_sibling_id_xfield(xval, len, sibling_id);
diff --git a/apfsck/inode.c b/apfsck/inode.c
index 37332f3..2e6a2be 100644
--- a/apfsck/inode.c
+++ b/apfsck/inode.c
@@ -302,6 +302,20 @@ static int read_dstream_xfield(char *xval, int len, struct inode *inode)
}
/**
+ * check_xfield_flags - Run common flag checks for all xfield types
+ * @flags: flags to check
+ */
+void check_xfield_flags(u8 flags)
+{
+ if (flags & APFS_XF_RESERVED_4 || flags & APFS_XF_RESERVED_40 ||
+ flags & APFS_XF_RESERVED_80)
+ report("Inode xfield", "reserved flag in use.");
+
+ if (flags & APFS_XF_USER_FIELD && flags & APFS_XF_SYSTEM_FIELD)
+ report("Inode xfield", "created by both user and kernel.");
+}
+
+/**
* parse_inode_xfields - Parse and check an inode extended fields
* @xblob: pointer to the beginning of the xfields in the inode value
* @len: length of the xfields
@@ -343,6 +357,8 @@ static void parse_inode_xfields(struct apfs_xf_blob *xblob, int len,
int xlen, xpad_len;
u16 type_flag;
+ check_xfield_flags(xfield[i].x_flags);
+
switch (xfield[i].x_type) {
case APFS_INO_EXT_TYPE_FS_UUID:
xlen = 16;
diff --git a/apfsck/inode.h b/apfsck/inode.h
index c04515a..e6c4dff 100644
--- a/apfsck/inode.h
+++ b/apfsck/inode.h
@@ -78,6 +78,16 @@ struct apfs_inode_val {
#define APFS_INO_EXT_TYPE_SPARSE_BYTES 13
#define APFS_INO_EXT_TYPE_RDEV 14
+/* Extended field flags */
+#define APFS_XF_DATA_DEPENDENT 0x01
+#define APFS_XF_DO_NOT_COPY 0x02
+#define APFS_XF_RESERVED_4 0x04
+#define APFS_XF_CHILDREN_INHERIT 0x08
+#define APFS_XF_USER_FIELD 0x10
+#define APFS_XF_SYSTEM_FIELD 0x20
+#define APFS_XF_RESERVED_40 0x40
+#define APFS_XF_RESERVED_80 0x80
+
/* Constants for extended fields */
#define APFS_MIN_DOC_ID 3 /* Smallest not reserved document id */
@@ -192,5 +202,6 @@ extern void set_or_check_sibling(u64 parent_id, int namelen, u8 *name,
struct sibling *sibling);
extern void parse_sibling_record(struct apfs_sibling_link_key *key,
struct apfs_sibling_val *val, int len);
+extern void check_xfield_flags(u8 flags);
#endif /* _INODE_H */
--
2.11.0