xattr.h: statically verify size of xattr header
[wimlib] / include / wimlib / xattr.h
1 #ifndef _WIMLIB_XATTR_H
2 #define _WIMLIB_XATTR_H
3
4 #include <string.h>
5
6 #include "wimlib/endianness.h"
7 #include "wimlib/tagged_items.h"
8 #include "wimlib/util.h"
9
10 #undef HAVE_XATTR_SUPPORT
11 #if defined(HAVE_SYS_XATTR_H) && \
12         defined(HAVE_LLISTXATTR) && defined(HAVE_LGETXATTR) && \
13         defined(HAVE_FSETXATTR) && defined(HAVE_LSETXATTR)
14 #  define HAVE_XATTR_SUPPORT 1
15 #endif
16
17 /*
18  * On-disk format of an entry in an extended attributes tagged item (wimlib
19  * extension).  An xattr item consists of a series of variable-length xattr
20  * name/value pairs, each of which begins with this header.
21  *
22  * Currently this is only used for Linux-style xattrs, but in the future we may
23  * use this for Windows-style xattrs too.
24  */
25 struct wimlib_xattr_entry {
26
27         /* length of xattr name in bytes */
28         le16 name_len;
29
30         /* reserved, must be 0 */
31         le16 reserved;
32
33         /* length of xattr value in bytes */
34         le32 value_len;
35
36         /* followed by the xattr name with no terminating null */
37         char name[0];
38
39         /* followed by the xattr value with no terminating null */
40         /* u8 value[0]; */
41
42         /* then zero-padded to a 4-byte boundary */
43 } _aligned_attribute(4);
44
45 static inline size_t
46 xattr_entry_size(const struct wimlib_xattr_entry *entry)
47 {
48         STATIC_ASSERT(sizeof(*entry) == 8);
49
50         return ALIGN(sizeof(*entry) + le16_to_cpu(entry->name_len) +
51                      le32_to_cpu(entry->value_len), 4);
52 }
53
54 static inline struct wimlib_xattr_entry *
55 xattr_entry_next(const struct wimlib_xattr_entry *entry)
56 {
57         return (void *)entry + xattr_entry_size(entry);
58 }
59
60 /* Currently we use the Linux limits when validating xattr names and values */
61 #define XATTR_NAME_MAX 255
62 #define XATTR_SIZE_MAX 65536
63
64 static inline bool
65 valid_xattr_entry(const struct wimlib_xattr_entry *entry, size_t avail)
66 {
67         if (avail < sizeof(*entry))
68                 return false;
69
70         if (entry->name_len == 0 ||
71             le16_to_cpu(entry->name_len) > XATTR_NAME_MAX)
72                 return false;
73
74         if (entry->reserved != 0)
75                 return false;
76
77         if (le32_to_cpu(entry->value_len) > XATTR_SIZE_MAX)
78                 return false;
79
80         if (avail < xattr_entry_size(entry))
81                 return false;
82
83         if (memchr(entry->name, '\0', le16_to_cpu(entry->name_len)))
84                 return false;
85
86         return true;
87 }
88
89 /* Is the xattr of the specified name security-related? */
90 static inline bool
91 is_security_xattr(const char *name)
92 {
93 #define XATTR_SECURITY_PREFIX "security."
94 #define XATTR_SYSTEM_PREFIX "system."
95 #define XATTR_POSIX_ACL_ACCESS  "posix_acl_access"
96 #define XATTR_NAME_POSIX_ACL_ACCESS XATTR_SYSTEM_PREFIX XATTR_POSIX_ACL_ACCESS
97 #define XATTR_POSIX_ACL_DEFAULT  "posix_acl_default"
98 #define XATTR_NAME_POSIX_ACL_DEFAULT XATTR_SYSTEM_PREFIX XATTR_POSIX_ACL_DEFAULT
99
100         return !strncmp(name, XATTR_SECURITY_PREFIX,
101                         sizeof(XATTR_SECURITY_PREFIX) - 1) ||
102                !strcmp(name, XATTR_NAME_POSIX_ACL_ACCESS) ||
103                !strcmp(name, XATTR_NAME_POSIX_ACL_DEFAULT);
104 }
105
106 static inline const void *
107 inode_get_linux_xattrs(const struct wim_inode *inode, u32 *len_ret)
108 {
109         return inode_get_tagged_item(inode, TAG_WIMLIB_LINUX_XATTRS, 0,
110                                      len_ret);
111 }
112
113 static inline bool
114 inode_has_linux_xattrs(const struct wim_inode *inode)
115 {
116         return inode_get_linux_xattrs(inode, NULL) != NULL;
117 }
118
119 static inline bool
120 inode_set_linux_xattrs(struct wim_inode *inode, const void *entries, u32 len)
121 {
122         return inode_set_tagged_item(inode, TAG_WIMLIB_LINUX_XATTRS,
123                                      entries, len);
124 }
125
126 #endif /* _WIMLIB_XATTR_H  */