summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilip Tricca <flihp@twobit.us>2015-06-17 15:30:56 -0700
committerJoe MacDonald <joe_macdonald@mentor.com>2015-08-08 16:43:23 -0400
commit22ade8fbe7f72bce1159fa645a246c84fe2195a2 (patch)
tree04211f85b0357290d26041c0759562aa85ce5ab4
parentb2ce05b5c18289a895f32fa30d8b47c44aa1de53 (diff)
downloadmeta-selinux-22ade8fbe7f72bce1159fa645a246c84fe2195a2.tar.gz
e2fsprogs: Copy xattr block from source file.
Signed-off-by: Philip Tricca <flihp@twobit.us> Signed-off-by: Joe MacDonald <joe_macdonald@mentor.com>
-rw-r--r--recipes-devtools/e2fsprogs/e2fsprogs/misc-xattr-create-xattr-block.patch341
-rw-r--r--recipes-devtools/e2fsprogs/e2fsprogs_1.42.9.bbappend1
2 files changed, 342 insertions, 0 deletions
diff --git a/recipes-devtools/e2fsprogs/e2fsprogs/misc-xattr-create-xattr-block.patch b/recipes-devtools/e2fsprogs/e2fsprogs/misc-xattr-create-xattr-block.patch
new file mode 100644
index 0000000..5955b44
--- /dev/null
+++ b/recipes-devtools/e2fsprogs/e2fsprogs/misc-xattr-create-xattr-block.patch
@@ -0,0 +1,341 @@
1To build the xattr disk block we process the output from listxattr and
2lgetxattr from the source file system object. This data is formated in a disk
3block according to the format specified in the kernel ext2 file system driver.
4See the comment block at the beginning of fs/ext2/xattr.c for details.
5
6Currently we only process attributes with the 'security.' prefix as our use
7case is SELinux labels and IMA. Additional prefixes can likely be supported with
8minimal effort but none have been tested.
9
10Once the xattr block has been created it is written to disk. The xattr block is
11associated with the appropriate file system object through the i_file_acl inode
12member and the inode is updated on disk.
13
14Signed-off-by: Philip Tricca <flihp@twobit.us>
15
16Index: e2fsprogs-1.42.9/misc/xattr.c
17===================================================================
18--- e2fsprogs-1.42.9.orig/misc/xattr.c
19+++ e2fsprogs-1.42.9/misc/xattr.c
20@@ -1,6 +1,23 @@
21 #include "xattr.h"
22
23+#include <attr/xattr.h>
24+#include <ctype.h>
25+#include <errno.h>
26+#include <ext2fs/ext2_ext_attr.h>
27+#include <linux/xattr.h>
28+#include <stdint.h>
29 #include <stdio.h>
30+#include <stdlib.h>
31+#include <string.h>
32+#include <sys/stat.h>
33+#include <sys/types.h>
34+#include <unistd.h>
35+
36+#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
37+#define HEADER(ptr) ((struct ext2_ext_attr_header *)(ptr))
38+#define ENTRY(ptr) ((struct ext2_ext_attr_entry *)(ptr))
39+#define FIRST_ENTRY(ptr) ENTRY(HEADER(ptr) + 1)
40+#define VALUE(hdr, ent) (((char*)hdr) + (ent->e_value_offs))
41
42 #ifdef XATTR_DEBUG
43 #define XATTR_STDERR(fmt, args...) fprintf (stderr, fmt, ##args)
44@@ -8,6 +25,28 @@
45 #define XATTR_STDERR(fmt, args...) do {} while (0)
46 #endif
47
48+/* structure for mapping xattr name prefix data */
49+typedef struct xattr_prefix {
50+ int index;
51+ char *name;
52+ size_t length;
53+} xattr_prefix_t;
54+
55+xattr_prefix_t xattr_prefixes [] = {
56+/* Only interested in security prefix. Can support others though.
57+ {
58+ .index = EXT2_XATTR_INDEX_USER,
59+ .name = XATTR_USER_PREFIX,
60+ .length = XATTR_USER_PREFIX_LEN,
61+ },
62+*/
63+ {
64+ .index = EXT2_XATTR_INDEX_SECURITY,
65+ .name = XATTR_SECURITY_PREFIX,
66+ .length = XATTR_SECURITY_PREFIX_LEN,
67+ },
68+ { 0 },
69+};
70
71 /* Free remaining resources after all files have been processed. */
72 void
73@@ -16,6 +55,211 @@ xattr_cleanup ()
74 XATTR_STDERR ("Cleaning up resources from xattrs.\n");
75 }
76
77+/* Get value for named xattr from file at path.
78+ * Returns pointer to allocated block for value and length in length param.
79+ * If no value, return NULL pointer and length of 0.
80+ * On error return NULL pointer and length set to -1.
81+ */
82+static char*
83+xattr_get_value (const char *path, const char *name, ssize_t *length)
84+{
85+ char *value = NULL;
86+
87+ *length = lgetxattr (path, name, NULL, 0);
88+ if (*length == -1) {
89+ com_err (__func__, errno, "lgetattr");
90+ goto out;
91+ }
92+ if (*length == 0) {
93+ fprintf (stderr, "xattr %s has value length 0\n", name);
94+ goto out;
95+ }
96+ value = calloc (1, *length);
97+ if (value == NULL) {
98+ com_err (__func__, errno, "calloc");
99+ goto out;
100+ }
101+ *length = lgetxattr (path, name, value, *length);
102+ if (*length == -1) {
103+ com_err (__func__, errno, "lgetattr");
104+ goto value_err;
105+ }
106+out:
107+ return value;
108+
109+value_err:
110+ if (value)
111+ free (value);
112+ return NULL;
113+}
114+
115+/* Get all attribute names for file at path. Return pointer to allocated memory
116+ * block holding all names and the length through parameter size.
117+ * If no xattrs: return NULL and set size to 0
118+ * If error: return NULL and set size to -1
119+ */
120+static char*
121+xattr_get_names (const char *path, ssize_t *size)
122+{
123+ char *names = NULL;
124+
125+ *size = llistxattr (path, NULL, 0);
126+ if (*size == -1) {
127+ com_err (__func__, errno, "llistxattr");
128+ goto out;
129+ }
130+ if (*size == 0) {
131+ /* no xattrs */
132+ goto out;
133+ }
134+ names = calloc (1, *size);
135+ if (names == NULL) {
136+ com_err (__func__, errno, "calloc");
137+ goto out;
138+ }
139+ *size = llistxattr (path, names, *size);
140+ if (*size == -1) {
141+ com_err (__func__, errno, "llistxattr");
142+ goto cleanup;
143+ }
144+ if (*size == 0) {
145+ fprintf (stdout, "Conflicting data, no xattrs for file: %s\n", path);
146+ goto cleanup;
147+ }
148+out:
149+ return names;
150+
151+cleanup:
152+ if (names)
153+ free (names);
154+ return NULL;
155+}
156+
157+/* return pointer to next string in xattr name block, don't go beyond length
158+ */
159+static inline char*
160+next_name (char *name, size_t length)
161+{
162+ int i = 0;
163+
164+ for (i = 0; i < length; ++i)
165+ if (name [i] == '\0') {
166+ ++i;
167+ break;
168+ }
169+
170+ return name + i;
171+}
172+
173+/* Find entry in xattr_table with matching prefix. */
174+static const xattr_prefix_t*
175+xattr_find_prefix (char *name, size_t length)
176+{
177+ int i = 0;
178+
179+ XATTR_STDERR ("find_attr_data: searching for prefix from xattr name: %s\n", name);
180+ for (i = 0; xattr_prefixes[i].index != 0; ++i) {
181+ if (!strncmp (name, xattr_prefixes[i].name, MIN (length, xattr_prefixes[i].length))) {
182+ XATTR_STDERR ("found match in table with index: %d\n", xattr_prefixes[i].index);
183+ return &xattr_prefixes[i];
184+ }
185+ }
186+ return NULL;
187+}
188+
189+/* Query file at path for attributes. build up structure the file system
190+ * expects of an extended attribute disk block (header parameter).
191+ *
192+ * The main loop walks through the xattr names one at a time. It gets the value
193+ * for each named xattr and copies the data into the xattr block pointed to by
194+ * the header parameter. To do this the loop also tracks the location of the
195+ * associated entry and value. Values start at the end of the buffer and grow
196+ * back towards the header while the entries start immediately after the header
197+ * and grow towards the end of the block.
198+ *
199+ * See the comment block at the beginning of the xattr.c file in the ext2 file
200+ * system code in the kernel: fs/ext2/xattr.c
201+ * Assume the xattr block pointed to by header parameter is initialized to 0s.
202+ */
203+static int
204+xattr_build_block (const char *path,
205+ struct ext2_ext_attr_header **header,
206+ size_t header_length)
207+{
208+ struct ext2_ext_attr_entry *entry = NULL;
209+ char *names = NULL, *value = NULL, *name_curr = NULL;
210+ ssize_t names_length = 0, value_length = 0;
211+ size_t name_length = 0, value_index = 0, len_rem = 0;
212+ const xattr_prefix_t *prefix = NULL;
213+ int ret = 0;
214+
215+ XATTR_STDERR ("xattr_build_block for file: %s\n", path);
216+ *header = NULL;
217+ names = xattr_get_names (path, &names_length);
218+ if (names == NULL) {
219+ // no xattrs for file @ path or error
220+ ret = names_length;
221+ goto out;
222+ }
223+ *header = calloc (1, header_length);
224+ if (*header == NULL) {
225+ com_err (__func__, errno, "calloc");
226+ goto out;
227+ }
228+ (*header)->h_magic = EXT2_EXT_ATTR_MAGIC;
229+ (*header)->h_blocks = 1;
230+ /* Values start at end of buffer. NOTE: It must be moved before a value can
231+ * be stored.
232+ */
233+ value_index = header_length;
234+ for (name_curr = names, entry = FIRST_ENTRY(*header), len_rem = names_length;
235+ name_curr < names + names_length;
236+ len_rem = names_length - (name_curr - names),
237+ name_curr = next_name (name_curr, len_rem),
238+ entry = EXT2_EXT_ATTR_NEXT(entry))
239+ {
240+ XATTR_STDERR ("xattr_build_block: processing xattr with name %s\n", name_curr);
241+ name_length = strnlen (name_curr, len_rem);
242+ prefix = xattr_find_prefix (name_curr, name_length);
243+ if (!prefix) {
244+ fprintf (stderr, "Don't currently handle xattr: %s\n", name_curr);
245+ continue;
246+ }
247+ value = xattr_get_value (path, name_curr, &value_length);
248+ if (value == NULL) {
249+ // no xattr value or error
250+ fprintf (stderr, "failed to get value, skipping\n");
251+ goto next;
252+ }
253+ /* setup offsets and lengths for name and value */
254+ entry->e_name_len = name_length - prefix->length;
255+ entry->e_name_index = prefix->index;
256+ /* Can't know these till we know the length of the value. */
257+ entry->e_value_offs = value_index -= EXT2_EXT_ATTR_SIZE(value_length);
258+ entry->e_value_size = value_length;
259+ /* Check to be sure entry name and value don't overlap before copy. */
260+ if (EXT2_EXT_ATTR_NAME(entry) + entry->e_name_len > VALUE(*header, entry)) {
261+ fprintf (stderr, "xattr entry name and value overlap! Too much xattr data.");
262+ ret = -1;
263+ goto out;
264+ }
265+ /* copy name and value data then calculate the hash */
266+ memcpy (EXT2_EXT_ATTR_NAME(entry),
267+ name_curr + prefix->length,
268+ entry->e_name_len);
269+ memcpy (VALUE(*header, entry), value, entry->e_value_size);
270+ entry->e_hash = ext2fs_ext_attr_hash_entry (entry, VALUE(*header, entry));
271+next:
272+ if (value)
273+ free (value);
274+ }
275+ XATTR_STDERR ("xattr_build_block: done building xattr buffer\n");
276+out:
277+ if (names)
278+ free (names);
279+ return ret;
280+}
281+
282 /* This is the entry point to the xattr module. This function copies the xattrs
283 * from the file at 'path' to the file system object at 'ino'.
284 *
285@@ -28,7 +272,56 @@ errcode_t
286 set_inode_xattr (ext2_filsys fs, ext2_ino_t ino, const char *path)
287 {
288 errcode_t ret = 0;
289+ char *buf = NULL;
290+ struct ext2_inode inode = { 0 };
291+ blk_t block = 0;
292+ struct ext2_ext_attr_header *header = NULL;
293+ uint32_t newcount = 0;
294
295 XATTR_STDERR ("Copying xattrs from %s to inode 0x%x.\n", path, ino);
296+ /* Populate the xattr block for the file at path */
297+ if (ret = xattr_build_block (path, &header, fs->blocksize)) {
298+ goto out;
299+ }
300+ if (header == NULL) {
301+ XATTR_STDERR ("set_inode_xattrs: no xattrs for %s\n", path);
302+ goto out;
303+ }
304+ if (ret = ext2fs_read_inode (fs, ino, &inode)) {
305+ com_err(__func__, ret, "ext2fs_read_inode");
306+ goto out;
307+ }
308+ if (ret = ext2fs_alloc_block (fs, 0, NULL, &block)) {
309+ com_err(__func__, ret, "ext2fs_alloc_block: returned %d", ret);
310+ goto out;
311+ }
312+ ext2fs_mark_block_bitmap2 (fs->block_map, block);
313+ XATTR_STDERR ("writing xattr block 0x%x to disk:\n", block);
314+ if (ret = ext2fs_write_ext_attr (fs, block, header)) {
315+ com_err(__func__, ret, "ext2fs_write_ext_attr: returned %d", ret);
316+ goto out;
317+ }
318+ /* point inode for current file to xattr block, update block count and
319+ * write inode to disk
320+ */
321+ inode.i_file_acl = block;
322+ if (ret = ext2fs_adjust_ea_refcount2(fs,
323+ block,
324+ (char*)header,
325+ 1,
326+ &newcount))
327+ {
328+ com_err(__func__, ret, "ext2fs_adjust_ea_refcount");
329+ goto out;
330+ }
331+ if (ret = ext2fs_iblk_add_blocks (fs, &inode, 1)) {
332+ com_err(__func__, ret, "ext2fs_iblk_add_blocks failed");
333+ goto out;
334+ }
335+ if (ret = ext2fs_write_inode (fs, ino, &inode))
336+ com_err(__func__, ret, "ext2fs_write_inode: returned %d", ret);
337+out:
338+ if (header)
339+ free (header);
340 return ret;
341 }
diff --git a/recipes-devtools/e2fsprogs/e2fsprogs_1.42.9.bbappend b/recipes-devtools/e2fsprogs/e2fsprogs_1.42.9.bbappend
index a4576b1..edc94d8 100644
--- a/recipes-devtools/e2fsprogs/e2fsprogs_1.42.9.bbappend
+++ b/recipes-devtools/e2fsprogs/e2fsprogs_1.42.9.bbappend
@@ -4,4 +4,5 @@ SRC_URI += " \
4 file://misc-xattr-add-xattr-module-stub.patch \ 4 file://misc-xattr-add-xattr-module-stub.patch \
5 file://mke2fs.c-create_inode.c-copy-xattrs.patch \ 5 file://mke2fs.c-create_inode.c-copy-xattrs.patch \
6 file://lib-ext2fs-ext2_ext_attr.h-add-xattr-index.patch \ 6 file://lib-ext2fs-ext2_ext_attr.h-add-xattr-index.patch \
7 file://misc-xattr-create-xattr-block.patch \
7" 8"