> -----Original Message-----
> From: yocto-boun...@yoctoproject.org [mailto:yocto-boun...@yoctoproject.org] 
> On Behalf Of Philip
> Tricca
> Sent: Thursday, June 18, 2015 6:31 AM
> To: yocto@yoctoproject.org
> Subject: [yocto] [meta-selinux][PATCHv2 6/8] e2fsprogs: Copy xattr block from 
> source file.
> 
> Signed-off-by: Philip Tricca <fl...@twobit.us>
> ---
>  .../e2fsprogs/misc-xattr-create-xattr-block.patch  | 341 
> +++++++++++++++++++++
>  .../e2fsprogs/e2fsprogs_1.42.9.bbappend            |   1 +
>  2 files changed, 342 insertions(+)
>  create mode 100644 
> recipes-devtools/e2fsprogs/e2fsprogs/misc-xattr-create-xattr-block.patch
> 
> 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 @@
> +To build the xattr disk block we process the output from listxattr and
> +lgetxattr from the source file system object. This data is formated in
> +a disk block according to the format specified in the kernel ext2 file 
> system driver.
> +See the comment block at the beginning of fs/ext2/xattr.c for details.
> +
> +Currently we only process attributes with the 'security.' prefix as our
> +use case is SELinux labels and IMA. Additional prefixes can likely be
> +supported with minimal effort but none have been tested.
> +
> +Once the xattr block has been created it is written to disk. The xattr
> +block is associated with the appropriate file system object through the
> +i_file_acl inode member and the inode is updated on disk.
> +
> +Signed-off-by: Philip Tricca <fl...@twobit.us>
> +
> +Index: e2fsprogs-1.42.9/misc/xattr.c
> +===================================================================
> +--- e2fsprogs-1.42.9.orig/misc/xattr.c
> ++++ e2fsprogs-1.42.9/misc/xattr.c
> +@@ -1,6 +1,23 @@
> + #include "xattr.h"
> +
> ++#include <attr/xattr.h>
> ++#include <ctype.h>
> ++#include <errno.h>
> ++#include <ext2fs/ext2_ext_attr.h>
> ++#include <linux/xattr.h>
> ++#include <stdint.h>
> + #include <stdio.h>
> ++#include <stdlib.h>
> ++#include <string.h>
> ++#include <sys/stat.h>
> ++#include <sys/types.h>
> ++#include <unistd.h>
> ++
> ++#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y)) #define HEADER(ptr)
> ++((struct ext2_ext_attr_header *)(ptr)) #define ENTRY(ptr)  ((struct
> ++ext2_ext_attr_entry *)(ptr)) #define FIRST_ENTRY(ptr)
> ++ENTRY(HEADER(ptr) + 1) #define VALUE(hdr, ent) (((char*)hdr) +
> ++(ent->e_value_offs))
> +
> + #ifdef XATTR_DEBUG
> + #define XATTR_STDERR(fmt, args...) fprintf (stderr, fmt, ##args) @@
> +-8,6 +25,28 @@  #define XATTR_STDERR(fmt, args...) do {} while (0)
> +#endif
> +
> ++/* structure for mapping xattr name prefix data */ typedef struct
> ++xattr_prefix {
> ++    int index;
> ++    char *name;
> ++    size_t length;
> ++} xattr_prefix_t;
> ++
> ++xattr_prefix_t xattr_prefixes [] = {
> ++/* Only interested in security prefix. Can support others though.
> ++    {
> ++            .index = EXT2_XATTR_INDEX_USER,
> ++            .name = XATTR_USER_PREFIX,
> ++            .length = XATTR_USER_PREFIX_LEN,
> ++    },
> ++*/
> ++    {
> ++            .index = EXT2_XATTR_INDEX_SECURITY,
> ++            .name = XATTR_SECURITY_PREFIX,
> ++            .length = XATTR_SECURITY_PREFIX_LEN,

Hi Philip,

This cause build errors on some host OS when building e2fsprogs-native:

| 
/build/yp/y_x64_150821/tmp/work/x86_64-linux/e2fsprogs-native/1.42.9-r0/e2fsprogs-1.42.9/debugfs/../misc/xattr.c:62:11:
 error: 'XATTR_SECURITY_PREFIX' undeclared here (not in a function)
|    .name = XATTR_SECURITY_PREFIX,
|            ^
| 
/build/yp/y_x64_150821/tmp/work/x86_64-linux/e2fsprogs-native/1.42.9-r0/e2fsprogs-1.42.9/debugfs/../misc/xattr.c:63:13:
 error: 'XATTR_SECURITY_PREFIX_LEN' undeclared here (not in a function)
|    .length = XATTR_SECURITY_PREFIX_LEN,
|              ^

I did some investigate and found that your patch needs the header linux/xattr.h,
which is provided by linux-libc-headers, but for -native package, there is no 
linux-libc-headers-native,
so it search the one from host OS, but the problem is, there is no 
XATTR_SECURITY_PREFIX definition
in the linux/xattr.h on some host OS like: SUSE 11.x, centos 6, etc.

I'm not sure if your patch is really needed by the e2fsprogs-native, if not, I 
think we can make this
patch only apply for target package. If yes, you may need to make it avoid the 
dependency on host's
header or you may have a better idea about this.

Thanks,
Jackie

> ++    },
> ++    { 0 },
> ++};
> +
> + /* Free remaining resources after all files have been processed. */
> +void @@ -16,6 +55,211 @@ xattr_cleanup ()
> +     XATTR_STDERR ("Cleaning up resources from xattrs.\n");  }
> +
> ++/* Get value for named xattr from file at path.
> ++ * Returns pointer to allocated block for value and length in length param.
> ++ * If no value, return NULL pointer and length of 0.
> ++ * On error return NULL pointer and length set to -1.
> ++ */
> ++static char*
> ++xattr_get_value (const char *path, const char *name, ssize_t *length)
> ++{
> ++    char *value = NULL;
> ++
> ++    *length = lgetxattr (path, name, NULL, 0);
> ++    if (*length == -1) {
> ++            com_err (__func__, errno, "lgetattr");
> ++            goto out;
> ++    }
> ++    if (*length == 0) {
> ++            fprintf (stderr, "xattr %s has value length 0\n", name);
> ++            goto out;
> ++    }
> ++    value = calloc (1, *length);
> ++    if (value == NULL) {
> ++            com_err (__func__, errno, "calloc");
> ++            goto out;
> ++    }
> ++    *length = lgetxattr (path, name, value, *length);
> ++    if (*length == -1) {
> ++            com_err (__func__, errno, "lgetattr");
> ++            goto value_err;
> ++    }
> ++out:
> ++    return value;
> ++
> ++value_err:
> ++    if (value)
> ++            free (value);
> ++    return NULL;
> ++}
> ++
> ++/* Get all attribute names for file at path. Return pointer to
> ++allocated memory
> ++ * block holding all names and the length through parameter size.
> ++ * If no xattrs: return NULL and set size to 0
> ++ * If error: return NULL and set size to -1  */ static char*
> ++xattr_get_names (const char *path, ssize_t *size) {
> ++    char *names = NULL;
> ++
> ++    *size = llistxattr (path, NULL, 0);
> ++    if (*size == -1) {
> ++            com_err (__func__, errno, "llistxattr");
> ++            goto out;
> ++    }
> ++    if (*size == 0) {
> ++            /* no xattrs */
> ++            goto out;
> ++    }
> ++    names = calloc (1, *size);
> ++    if (names == NULL) {
> ++            com_err (__func__, errno, "calloc");
> ++            goto out;
> ++    }
> ++    *size = llistxattr (path, names, *size);
> ++    if (*size == -1) {
> ++            com_err (__func__, errno, "llistxattr");
> ++            goto cleanup;
> ++    }
> ++    if (*size == 0) {
> ++            fprintf (stdout, "Conflicting data, no xattrs for file: %s\n", 
> path);
> ++            goto cleanup;
> ++    }
> ++out:
> ++    return names;
> ++
> ++cleanup:
> ++    if (names)
> ++            free (names);
> ++    return NULL;
> ++}
> ++
> ++/* return pointer to next string in xattr name block, don't go beyond
> ++length  */ static inline char* next_name (char *name, size_t length) {
> ++    int i = 0;
> ++
> ++    for (i = 0; i < length; ++i)
> ++            if (name [i] == '\0') {
> ++                    ++i;
> ++                    break;
> ++            }
> ++
> ++    return name + i;
> ++}
> ++
> ++/* Find entry in xattr_table with matching prefix. */ static const
> ++xattr_prefix_t* xattr_find_prefix (char *name, size_t length) {
> ++    int i = 0;
> ++
> ++    XATTR_STDERR ("find_attr_data: searching for prefix from xattr name: 
> %s\n", name);
> ++    for (i = 0; xattr_prefixes[i].index != 0; ++i) {
> ++            if (!strncmp (name, xattr_prefixes[i].name, MIN (length, 
> xattr_prefixes[i].length))) {
> ++                    XATTR_STDERR ("found match in table with index: %d\n",
> xattr_prefixes[i].index);
> ++                    return &xattr_prefixes[i];
> ++            }
> ++    }
> ++    return NULL;
> ++}
> ++
> ++/* Query file at path for attributes. build up structure the file
> ++system
> ++ * expects of an extended attribute disk block (header parameter).
> ++ *
> ++ * The main loop walks through the xattr names one at a time. It gets
> ++the value
> ++ * for each named xattr and copies the data into the xattr block
> ++pointed to by
> ++ * the header parameter. To do this the loop also tracks the location
> ++of the
> ++ * associated entry and value. Values start at the end of the buffer
> ++and grow
> ++ * back towards the header while the entries start immediately after
> ++the header
> ++ * and grow towards the end of the block.
> ++ *
> ++ * See the comment block at the beginning of the xattr.c file in the
> ++ext2 file
> ++ * system code in the kernel: fs/ext2/xattr.c
> ++ * Assume the xattr block pointed to by header parameter is initialized to 
> 0s.
> ++ */
> ++static int
> ++xattr_build_block (const char *path,
> ++            struct ext2_ext_attr_header **header,
> ++            size_t header_length)
> ++{
> ++    struct ext2_ext_attr_entry *entry = NULL;
> ++    char *names = NULL, *value = NULL, *name_curr = NULL;
> ++    ssize_t names_length = 0, value_length = 0;
> ++    size_t name_length = 0, value_index = 0, len_rem = 0;
> ++    const xattr_prefix_t *prefix = NULL;
> ++    int ret = 0;
> ++
> ++    XATTR_STDERR ("xattr_build_block for file: %s\n", path);
> ++    *header = NULL;
> ++    names = xattr_get_names (path, &names_length);
> ++    if (names == NULL) {
> ++            // no xattrs for file @ path or error
> ++            ret = names_length;
> ++            goto out;
> ++    }
> ++    *header = calloc (1, header_length);
> ++    if (*header == NULL) {
> ++            com_err (__func__, errno, "calloc");
> ++            goto out;
> ++    }
> ++    (*header)->h_magic = EXT2_EXT_ATTR_MAGIC;
> ++    (*header)->h_blocks = 1;
> ++    /* Values start at end of buffer. NOTE: It must be moved before a value 
> can
> ++     * be stored.
> ++     */
> ++    value_index = header_length;
> ++    for (name_curr = names, entry = FIRST_ENTRY(*header), len_rem = 
> names_length;
> ++            name_curr < names + names_length;
> ++            len_rem = names_length - (name_curr - names),
> ++                    name_curr = next_name (name_curr, len_rem),
> ++                    entry = EXT2_EXT_ATTR_NEXT(entry))
> ++    {
> ++            XATTR_STDERR ("xattr_build_block: processing xattr with name 
> %s\n", name_curr);
> ++            name_length = strnlen (name_curr, len_rem);
> ++            prefix = xattr_find_prefix (name_curr, name_length);
> ++            if (!prefix) {
> ++                    fprintf (stderr, "Don't currently handle xattr: %s\n", 
> name_curr);
> ++                    continue;
> ++            }
> ++            value = xattr_get_value (path, name_curr, &value_length);
> ++            if (value == NULL) {
> ++                    // no xattr value or error
> ++                    fprintf (stderr, "failed to get value, skipping\n");
> ++                    goto next;
> ++            }
> ++            /* setup offsets and lengths for name and value */
> ++            entry->e_name_len = name_length - prefix->length;
> ++            entry->e_name_index = prefix->index;
> ++            /* Can't know these till we know the length of the value. */
> ++            entry->e_value_offs = value_index -= 
> EXT2_EXT_ATTR_SIZE(value_length);
> ++            entry->e_value_size = value_length;
> ++            /* Check to be sure entry name and value don't overlap before 
> copy. */
> ++            if (EXT2_EXT_ATTR_NAME(entry) + entry->e_name_len > 
> VALUE(*header, entry)) {
> ++                    fprintf (stderr, "xattr entry name and value overlap! 
> Too much xattr data.");
> ++                    ret = -1;
> ++                    goto out;
> ++            }
> ++            /* copy name and value data then calculate the hash */
> ++            memcpy (EXT2_EXT_ATTR_NAME(entry),
> ++                    name_curr + prefix->length,
> ++                    entry->e_name_len);
> ++            memcpy (VALUE(*header, entry), value, entry->e_value_size);
> ++            entry->e_hash = ext2fs_ext_attr_hash_entry (entry, 
> VALUE(*header,
> ++entry));
> ++next:
> ++            if (value)
> ++                    free (value);
> ++    }
> ++    XATTR_STDERR ("xattr_build_block: done building xattr buffer\n");
> ++out:
> ++    if (names)
> ++            free (names);
> ++    return ret;
> ++}
> ++
> + /* This is the entry point to the xattr module. This function copies
> +the xattrs
> +  * from the file at 'path' to the file system object at 'ino'.
> +  *
> +@@ -28,7 +272,56 @@ errcode_t
> + set_inode_xattr (ext2_filsys fs, ext2_ino_t ino, const char *path)  {
> +     errcode_t ret = 0;
> ++    char *buf = NULL;
> ++    struct ext2_inode inode = { 0 };
> ++    blk_t block = 0;
> ++    struct ext2_ext_attr_header *header = NULL;
> ++    uint32_t newcount = 0;
> +
> +     XATTR_STDERR ("Copying xattrs from %s to inode 0x%x.\n", path, ino);
> ++    /* Populate the xattr block for the file at path */
> ++    if (ret = xattr_build_block (path, &header, fs->blocksize)) {
> ++            goto out;
> ++    }
> ++    if (header == NULL) {
> ++            XATTR_STDERR ("set_inode_xattrs: no xattrs for %s\n", path);
> ++            goto out;
> ++    }
> ++    if (ret = ext2fs_read_inode (fs, ino, &inode)) {
> ++            com_err(__func__, ret, "ext2fs_read_inode");
> ++            goto out;
> ++    }
> ++    if (ret = ext2fs_alloc_block (fs, 0, NULL, &block)) {
> ++            com_err(__func__, ret, "ext2fs_alloc_block: returned %d", ret);
> ++            goto out;
> ++    }
> ++    ext2fs_mark_block_bitmap2 (fs->block_map, block);
> ++    XATTR_STDERR ("writing xattr block 0x%x to disk:\n", block);
> ++    if (ret = ext2fs_write_ext_attr (fs, block, header)) {
> ++            com_err(__func__, ret, "ext2fs_write_ext_attr: returned %d", 
> ret);
> ++            goto out;
> ++    }
> ++    /* point inode for current file to xattr block, update block count and
> ++     * write inode to disk
> ++     */
> ++    inode.i_file_acl = block;
> ++    if (ret = ext2fs_adjust_ea_refcount2(fs,
> ++                                    block,
> ++                                    (char*)header,
> ++                                    1,
> ++                                    &newcount))
> ++    {
> ++            com_err(__func__, ret, "ext2fs_adjust_ea_refcount");
> ++            goto out;
> ++    }
> ++    if (ret = ext2fs_iblk_add_blocks (fs, &inode, 1)) {
> ++            com_err(__func__, ret, "ext2fs_iblk_add_blocks failed");
> ++            goto out;
> ++    }
> ++    if (ret = ext2fs_write_inode (fs, ino, &inode))
> ++            com_err(__func__, ret, "ext2fs_write_inode: returned %d", ret);
> ++out:
> ++    if (header)
> ++            free (header);
> +     return ret;
> + }
> 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 += " \
>      file://misc-xattr-add-xattr-module-stub.patch \
>      file://mke2fs.c-create_inode.c-copy-xattrs.patch \
>      file://lib-ext2fs-ext2_ext_attr.h-add-xattr-index.patch \
> +    file://misc-xattr-create-xattr-block.patch \
>  "
> --
> 2.1.4
> 
> --
> _______________________________________________
> yocto mailing list
> yocto@yoctoproject.org
> https://lists.yoctoproject.org/listinfo/yocto
-- 
_______________________________________________
yocto mailing list
yocto@yoctoproject.org
https://lists.yoctoproject.org/listinfo/yocto

Reply via email to