| From 204527c73663a2b78cede04f6328ed14a4bdffa5 Mon Sep 17 00:00:00 2001 |
| From: Gwendal Grignou <gwendal@google.com> |
| Date: Fri, 30 Apr 2021 13:34:23 -0700 |
| Subject: [PATCH] squashfs-tools: Allow setting selinux xattrs through |
| file_context |
| |
| Add a context-file flag that allows passing an selinux security context |
| file to set security.selinux xattrs rather than reading xattrs from |
| filesystem's source directory. |
| |
| Based on the original change to allow the use of SELinux file_contexts |
| directly from the source file which was committed to Android's copy |
| of squashfs-tools and written by Mohamad Ayyash <mkayyash@google.com> |
| --- |
| --- |
| squashfs-tools/Makefile | 26 ++++++- |
| squashfs-tools/mksquashfs.c | 34 ++++++++- |
| squashfs-tools/selinux.c | 62 ++++++++++++++++ |
| squashfs-tools/selinux.h | 27 +++++++ |
| squashfs-tools/xattr.c | 140 ++++++++++++++++++++++++++---------- |
| squashfs-tools/xattr.h | 10 ++- |
| 6 files changed, 258 insertions(+), 41 deletions(-) |
| create mode 100644 squashfs-tools/selinux.c |
| create mode 100644 squashfs-tools/selinux.h |
| |
| diff --git a/squashfs-tools/Makefile b/squashfs-tools/Makefile |
| index 9aa4381..4cf2425 100755 |
| --- a/squashfs-tools/Makefile |
| +++ b/squashfs-tools/Makefile |
| @@ -114,6 +114,22 @@ XATTR_SUPPORT = 1 |
| # default. Users can enable xattrs by using the -xattrs option. |
| XATTR_DEFAULT = 1 |
| |
| +############################################### |
| +# SELinux labelling support build options # |
| +############################################### |
| +# |
| +# Building SELinux labelling support for Mksquashfs. This provides an |
| +# alternative to reading SELinux labels from the filesystem with XATTR |
| +# support. It is possible to label the files in the Squashfs filesystem |
| +# differently than the source filesystem with this option. |
| +# |
| +# Note that SELinux labelling support requries that XATTR is also |
| +# supported. |
| +# |
| +# If your build/target environment does not have support for SELinux then |
| +# comment out the next line to build Mksquashfs without SELinux labelling |
| +# support. |
| +SELINUX_SUPPORT = 1 |
| |
| ############################################### |
| # Reproducible Image options # |
| @@ -214,7 +230,7 @@ UNSQUASHFS_OBJS = unsquashfs.o unsquash-1.o unsquash-2.o unsquash-3.o \ |
| unsquash-4.o unsquash-123.o unsquash-34.o unsquash-1234.o unsquash-12.o \ |
| swap.o compressor.o unsquashfs_info.o date.o |
| |
| -CFLAGS ?= -O2 |
| +CFLAGS ?= -O2 -ggdb |
| CFLAGS += $(EXTRA_CFLAGS) $(INCLUDEDIR) -D_FILE_OFFSET_BITS=64 \ |
| -D_LARGEFILE_SOURCE -D_GNU_SOURCE -DCOMP_DEFAULT=\"$(COMP_DEFAULT)\" \ |
| -Wall |
| @@ -286,6 +302,14 @@ CFLAGS += -DXATTR_SUPPORT |
| endif |
| MKSQUASHFS_OBJS += xattr.o read_xattrs.o tar_xattr.o pseudo_xattr.o |
| UNSQUASHFS_OBJS += read_xattrs.o unsquashfs_xattr.o |
| + |
| +# SELinux support is only available if XATTR support is available |
| +ifeq ($(SELINUX_SUPPORT),1) |
| +CFLAGS += -DSELINUX_SUPPORT |
| +MKSQUASHFS_OBJS += selinux.o |
| +LIBS += -lselinux |
| +endif |
| + |
| endif |
| |
| ifeq ($(REPRODUCIBLE_DEFAULT),1) |
| diff --git a/squashfs-tools/mksquashfs.c b/squashfs-tools/mksquashfs.c |
| index a6f3bcb..985eb26 100644 |
| --- a/squashfs-tools/mksquashfs.c |
| +++ b/squashfs-tools/mksquashfs.c |
| @@ -75,6 +75,7 @@ |
| #include "fnmatch_compat.h" |
| #include "tar.h" |
| #include "merge_sort.h" |
| +#include "selinux.h" |
| |
| /* Compression options */ |
| int noF = FALSE; |
| @@ -352,6 +353,11 @@ char *sqfstar_option_table[] = { "comp", "b", "mkfs-time", "fstime", "all-time", |
| "default-mode", "default-uid", "default-gid", "mem-percent", NULL |
| }; |
| |
| +/* selinux label */ |
| +squashfs_selinux_handle *sehnd = NULL; |
| +char *context_file = NULL; |
| +char *mount_point = NULL; |
| + |
| static char *read_from_disk(long long start, unsigned int avail_bytes); |
| static void add_old_root_entry(char *name, squashfs_inode inode, |
| unsigned int inode_number, int type); |
| @@ -6171,6 +6177,9 @@ static void print_options(FILE *stream, char *name, int total_mem) |
| fprintf(stream, "-comp <comp>\t\tselect <comp> compression\n"); |
| fprintf(stream, "\t\t\tCompressors available:\n"); |
| display_compressors(stream, "\t\t\t", COMP_DEFAULT); |
| + fprintf(stream, "-context-file <file>\tApply SELinux context "); |
| + fprintf(stream, "xattr from <file> instead\n\t\t\t"); |
| + fprintf(stream, "of reading xattr from filesystem\n"); |
| fprintf(stream, "-noI\t\t\tdo not compress inode table\n"); |
| fprintf(stream, "-noId\t\t\tdo not compress the uid/gid table (implied by "); |
| fprintf(stream, "-noI)\n"); |
| @@ -6249,6 +6258,9 @@ static void print_options(FILE *stream, char *name, int total_mem) |
| fprintf(stream, "create a root\n"); |
| fprintf(stream, "\t\t\tdirectory containing that directory, rather than the\n"); |
| fprintf(stream, "\t\t\tcontents of the directory\n"); |
| + fprintf(stream, "-mount-point <name>\tWhen applying attributes such "); |
| + fprintf(stream, "as SELinux context, treat\n\t\t\t"); |
| + fprintf(stream, "the filesystem as mounted at <name>\n"); |
| fprintf(stream, "-4k-align\t\tenables 4k alignment of all files\n"); |
| fprintf(stream, "\nFilesystem filter options:\n"); |
| fprintf(stream, "-p <pseudo-definition>\tadd pseudo file "); |
| @@ -6460,6 +6472,9 @@ static void print_sqfstar_options(FILE *stream, char *name, int total_mem) |
| fprintf(stream, "-comp <comp>\t\tselect <comp> compression\n"); |
| fprintf(stream, "\t\t\tCompressors available:\n"); |
| display_compressors(stream, "\t\t\t", COMP_DEFAULT); |
| + fprintf(stream, "-context-file <file>\tApply SELinux context "); |
| + fprintf(stream, "xattr from <file> instead\n\t\t\t"); |
| + fprintf(stream, "of reading xattr from filesystem\n"); |
| fprintf(stream, "-noI\t\t\tdo not compress inode table\n"); |
| fprintf(stream, "-noId\t\t\tdo not compress the uid/gid table (implied by "); |
| fprintf(stream, "-noI)\n"); |
| @@ -8392,7 +8407,15 @@ print_compressor_options: |
| xattrs_add(argv[i]); |
| no_xattrs = FALSE; |
| } |
| - } else if(strcmp(argv[i], "-nopad") == 0) |
| + } else if(strcmp(argv[i], "-context-file") == 0) { |
| + if(++i == argc) { |
| + ERROR("%s: -context-file: missing filename\n", |
| + argv[0]); |
| + exit(1); |
| + } |
| + context_file = argv[i]; |
| + } |
| + else if(strcmp(argv[i], "-nopad") == 0) |
| nopad = TRUE; |
| |
| else if(strcmp(argv[i], "-info") == 0) |
| @@ -8410,6 +8433,15 @@ print_compressor_options: |
| else if(strcmp(argv[i], "-keep-as-directory") == 0) |
| keep_as_directory = TRUE; |
| |
| + else if(strcmp(argv[i], "-mount-point") == 0) { |
| + if(++i == argc) { |
| + ERROR("%s: -mount-point: missing mount point name\n", |
| + argv[0]); |
| + exit(1); |
| + } |
| + mount_point = argv[i]; |
| + } |
| + |
| else if(strcmp(argv[i], "-exit-on-error") == 0) |
| exit_on_error = TRUE; |
| |
| diff --git a/squashfs-tools/selinux.c b/squashfs-tools/selinux.c |
| new file mode 100644 |
| index 0000000..e28c44c |
| --- /dev/null |
| +++ b/squashfs-tools/selinux.c |
| @@ -0,0 +1,62 @@ |
| +/* Copyright 2015 The Android Open Source Project */ |
| + |
| +#include <errno.h> |
| +#include <stdlib.h> |
| +#include <string.h> |
| +#include <selinux/label.h> |
| + |
| +#include "error.h" |
| +#include "mksquashfs_error.h" |
| +#include "selinux.h" |
| +#include "xattr.h" |
| + |
| + |
| +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) |
| + |
| + |
| +squashfs_selinux_handle *get_sehnd(const char *context_file) { |
| + struct selinux_opt seopts[] = { |
| + { |
| + .type = SELABEL_OPT_PATH, |
| + .value = context_file |
| + } |
| + }; |
| + struct selabel_handle *sehnd = |
| + selabel_open(SELABEL_CTX_FILE, seopts, ARRAY_SIZE(seopts)); |
| + |
| + if(sehnd == NULL) |
| + BAD_ERROR("Failure calling selabel_open: %s\n", strerror(errno)); |
| + |
| + return sehnd; |
| +} |
| + |
| +static char *set_selabel(const char *path, unsigned int mode, struct selabel_handle *sehnd) { |
| + char *secontext; |
| + if(sehnd == NULL) |
| + BAD_ERROR("selabel handle is NULL\n"); |
| + |
| + int full_name_size = strlen(path) + 2; |
| + char* full_name = (char*) malloc(full_name_size); |
| + if(full_name == NULL) |
| + MEM_ERROR(); |
| + |
| + full_name[0] = '/'; |
| + strncpy(full_name + 1, path, full_name_size - 1); |
| + |
| + if(selabel_lookup(sehnd, &secontext, full_name, mode)) |
| + secontext = strdup("u:object_r:unlabeled:s0"); |
| + |
| + free(full_name); |
| + return secontext; |
| +} |
| + |
| +void read_selinux_xattr_from_context_file(char *filename, int mode, |
| + squashfs_selinux_handle *sehnd, struct xattr_list *xattrs) { |
| + char *attr_val; |
| + |
| + xattrs->type = xattr_get_prefix(xattrs, "security.selinux"); |
| + attr_val = set_selabel(filename, mode, sehnd); |
| + xattrs->value = (void *)attr_val; |
| + xattrs->vsize = strlen(attr_val); |
| +} |
| + |
| diff --git a/squashfs-tools/selinux.h b/squashfs-tools/selinux.h |
| new file mode 100644 |
| index 0000000..f29b679 |
| --- /dev/null |
| +++ b/squashfs-tools/selinux.h |
| @@ -0,0 +1,27 @@ |
| +/* Copyright 2015 The Android Open Source Project */ |
| + |
| +#ifndef SELINUX_H |
| +#define SELINUX_H |
| + |
| +#include "xattr.h" |
| + |
| +#ifdef SELINUX_SUPPORT |
| +typedef struct selabel_handle squashfs_selinux_handle; |
| +extern squashfs_selinux_handle *get_sehnd(const char *context_file); |
| +extern void read_selinux_xattr_from_context_file(char *filename, int mode, |
| + struct selabel_handle *sehnd, struct xattr_list *xattrs); |
| +#else |
| +typedef void squashfs_selinux_handle; |
| + |
| + |
| +static squashfs_selinux_handle *get_sehnd(const char *context_file) { |
| + return NULL; |
| +} |
| + |
| + |
| +static void read_selinux_xattr_from_context_file(char *filename, int mode, |
| + squashfs_selinux_handle *sehnd, struct xattr_list *xattrs) { |
| +} |
| +#endif |
| + |
| +#endif |
| diff --git a/squashfs-tools/xattr.c b/squashfs-tools/xattr.c |
| index f9f4cc3..5b46942 100644 |
| --- a/squashfs-tools/xattr.c |
| +++ b/squashfs-tools/xattr.c |
| @@ -35,6 +35,7 @@ |
| #include <errno.h> |
| #include <dirent.h> |
| #include <string.h> |
| +#include <stdint.h> |
| #include <stdlib.h> |
| #include <sys/xattr.h> |
| #include <regex.h> |
| @@ -43,6 +44,7 @@ |
| #include "squashfs_swap.h" |
| #include "mksquashfs.h" |
| #include "xattr.h" |
| +#include "selinux.h" |
| #include "mksquashfs_error.h" |
| #include "progressbar.h" |
| #include "pseudo.h" |
| @@ -60,6 +62,8 @@ |
| /* compressed xattr table */ |
| static char *xattr_table = NULL; |
| static unsigned int xattr_size = 0; |
| +extern char *context_file; |
| +extern char *mount_point; |
| |
| /* cached uncompressed xattr data */ |
| static char *data_cache = NULL; |
| @@ -103,12 +107,71 @@ extern void write_destination(int, long long, long long, void *); |
| extern long long generic_write_table(long long, void *, int, void *, int); |
| extern int mangle(char *, char *, int, int, int, int); |
| extern char *pathname(struct dir_ent *); |
| +extern char *subpathname(struct dir_ent *); |
| |
| /* helper functions and definitions from read_xattrs.c */ |
| extern unsigned int read_xattrs_from_disk(int, struct squashfs_super_block *, int, long long *); |
| extern struct xattr_list *get_xattr(int, unsigned int *, int *); |
| extern struct prefix prefix_table[]; |
| |
| +/* selinux label */ |
| +extern squashfs_selinux_handle *sehnd; |
| + |
| +void alloc_mounted_path(const char *mount_point, const char *subpath, char **new_path) { |
| + size_t mount_point_len = strlen(mount_point); |
| + size_t subpath_len = strlen(subpath); |
| + size_t new_path_len = mount_point_len + subpath_len + 1; |
| + |
| + if(new_path_len < mount_point_len || new_path_len < subpath_len) |
| + BAD_ERROR("Cannot allocate mounted path length; it is over %d\n", |
| + SIZE_MAX); |
| + |
| + *new_path = malloc(new_path_len); |
| + if (*new_path == NULL) |
| + MEM_ERROR(); |
| + |
| + strcpy(*new_path, mount_point); |
| + strcat(*new_path, subpath); |
| +} |
| + |
| +static struct xattr_list *xattr_list_add(int *xattr_count, struct xattr_list **xattrs) { |
| + struct xattr_list *x, *next_xattr; |
| + |
| + x = realloc(*xattrs, ++*xattr_count * sizeof(struct xattr_list)); |
| + if(x == NULL) |
| + MEM_ERROR(); |
| + |
| + next_xattr = &x[*xattr_count - 1]; |
| + memset(next_xattr, 0, sizeof(struct xattr_list)); |
| + |
| + *xattrs = x; |
| + return next_xattr; |
| +} |
| + |
| +static struct xattr_list *xattr_list_trim(int *xattr_count, struct xattr_list **xattrs) { |
| + struct xattr_list *x, *last_xattr; |
| + |
| + if (*xattr_count == 0 || *xattrs == NULL) |
| + return NULL; |
| + x = *xattrs; |
| + |
| + last_xattr = &x[*xattr_count - 1]; |
| + free(last_xattr->full_name); |
| + free(last_xattr->value); |
| + |
| + if (--*xattr_count == 0) { |
| + free(*xattrs); |
| + *xattrs = NULL; |
| + return NULL; |
| + } |
| + |
| + x = realloc(*xattrs, *xattr_count * sizeof(struct xattr_list)); |
| + if(x == NULL) |
| + MEM_ERROR(); |
| + |
| + *xattrs = x; |
| + return &x[*xattr_count - 1]; |
| +} |
| |
| static int xattr_get_type(char *name) |
| { |
| @@ -144,12 +207,10 @@ int xattr_get_prefix(struct xattr_list *xattr, char *name) |
| |
| |
| static int read_xattrs_from_system(struct dir_ent *dir_ent, char *filename, |
| - struct xattr_list **xattrs) |
| + int* xattr_count, struct xattr_list **xattrs) |
| { |
| ssize_t size, vsize; |
| char *xattr_names, *p; |
| - int i = 0; |
| - struct xattr_list *xattr_list = NULL; |
| struct xattr_data *xattr_exc_list; |
| struct xattr_data *xattr_inc_list; |
| |
| @@ -191,7 +252,6 @@ static int read_xattrs_from_system(struct dir_ent *dir_ent, char *filename, |
| xattr_inc_list = eval_xattr_inc_actions(root_dir, dir_ent); |
| |
| for(p = xattr_names; p < xattr_names + size;) { |
| - struct xattr_list *x; |
| int res; |
| |
| res = match_xattr_exc_actions(xattr_exc_list, p); |
| @@ -222,14 +282,10 @@ static int read_xattrs_from_system(struct dir_ent *dir_ent, char *filename, |
| } |
| } |
| |
| - x = realloc(xattr_list, (i + 1) * sizeof(struct xattr_list)); |
| - if(x == NULL) |
| - MEM_ERROR(); |
| - xattr_list = x; |
| - |
| - xattr_list[i].type = xattr_get_prefix(&xattr_list[i], p); |
| + struct xattr_list *next_xattr = xattr_list_add(xattr_count, xattrs); |
| + next_xattr->type = xattr_get_prefix(next_xattr, p); |
| |
| - if(xattr_list[i].type == -1) { |
| + if(next_xattr->type == -1) { |
| ERROR("Unrecognised xattr prefix %s\n", p); |
| p += strlen(p) + 1; |
| continue; |
| @@ -238,25 +294,25 @@ static int read_xattrs_from_system(struct dir_ent *dir_ent, char *filename, |
| p += strlen(p) + 1; |
| |
| while(1) { |
| - vsize = lgetxattr(filename, xattr_list[i].full_name, |
| + vsize = lgetxattr(filename, next_xattr->full_name, |
| NULL, 0); |
| if(vsize < 0) { |
| ERROR_START("lgetxattr failed for %s in " |
| "read_attrs, because %s", filename, |
| strerror(errno)); |
| ERROR_EXIT(". Ignoring\n"); |
| - free(xattr_list[i].full_name); |
| + xattr_list_trim(xattr_count, xattrs); |
| goto failed; |
| } |
| |
| - xattr_list[i].value = malloc(vsize); |
| - if(xattr_list[i].value == NULL) |
| + next_xattr->value = malloc(vsize); |
| + if(next_xattr->value == NULL) |
| MEM_ERROR(); |
| |
| - vsize = lgetxattr(filename, xattr_list[i].full_name, |
| - xattr_list[i].value, vsize); |
| + vsize = lgetxattr(filename, next_xattr->full_name, |
| + next_xattr->value, vsize); |
| if(vsize < 0) { |
| - free(xattr_list[i].value); |
| + free(next_xattr->value); |
| if(errno == ERANGE) |
| /* xattr grew? Try again */ |
| continue; |
| @@ -265,7 +321,7 @@ static int read_xattrs_from_system(struct dir_ent *dir_ent, char *filename, |
| "in read_attrs, because %s", |
| filename, strerror(errno)); |
| ERROR_EXIT(". Ignoring\n"); |
| - free(xattr_list[i].full_name); |
| + xattr_list_trim(xattr_count, xattrs); |
| goto failed; |
| } |
| } |
| @@ -273,28 +329,18 @@ static int read_xattrs_from_system(struct dir_ent *dir_ent, char *filename, |
| break; |
| } |
| |
| - xattr_list[i].vsize = vsize; |
| + next_xattr->vsize = vsize; |
| |
| TRACE("read_xattrs_from_system: filename %s, xattr name %s," |
| - " vsize %d\n", filename, xattr_list[i].full_name, |
| - xattr_list[i].vsize); |
| - i++; |
| + " vsize %d\n", filename, next_xattr->full_name, |
| + next_xattr->vsize); |
| } |
| |
| free(xattr_names); |
| - |
| - if(i > 0) |
| - *xattrs = xattr_list; |
| - else |
| - free(xattr_list); |
| - return i; |
| + return 1; |
| |
| failed: |
| - while(--i >= 0) { |
| - free(xattr_list[i].full_name); |
| - free(xattr_list[i].value); |
| - } |
| - free(xattr_list); |
| + while(xattr_list_trim(xattr_count, xattrs) != NULL); |
| free(xattr_names); |
| return 0; |
| } |
| @@ -708,7 +754,7 @@ int read_xattrs(void *d, int type) |
| struct dir_ent *dir_ent = d; |
| struct inode_info *inode = dir_ent->inode; |
| char *filename = pathname(dir_ent); |
| - struct xattr_list *xattr_list = NULL, *head; |
| + struct xattr_list *xattr_list = NULL, *head, *next_xattr = NULL; |
| int count, i = 0, j; |
| struct xattr_add *l1 = xattr_add_list, *l2 = NULL, *l3 = NULL; |
| struct xattr_add *action_add_list; |
| @@ -719,7 +765,24 @@ int read_xattrs(void *d, int type) |
| if(IS_TARFILE(inode)) |
| i = read_xattrs_from_tarfile(inode, &xattr_list); |
| else if(!inode->dummy_root_dir && !IS_PSEUDO(inode)) |
| - i = read_xattrs_from_system(dir_ent, filename, &xattr_list); |
| + read_xattrs_from_system(dir_ent, filename, &i, &xattr_list); |
| + |
| + if(context_file) { |
| + if(sehnd == NULL) |
| + sehnd = get_sehnd(context_file); |
| + if(mount_point) { |
| + char *mounted_path; |
| + alloc_mounted_path(mount_point, subpathname(dir_ent), &mounted_path); |
| + next_xattr = xattr_list_add(&i, &xattr_list); |
| + read_selinux_xattr_from_context_file(mounted_path, inode->buf.st_mode, |
| + sehnd, next_xattr); |
| + free(mounted_path); |
| + } else { |
| + next_xattr = xattr_list_add(&i, &xattr_list); |
| + read_selinux_xattr_from_context_file(filename, inode->buf.st_mode, |
| + sehnd, next_xattr); |
| + } |
| + } |
| |
| action_add_list = eval_xattr_add_actions(root_dir, dir_ent, &count); |
| |
| @@ -838,7 +901,7 @@ int read_xattrs(void *d, int type) |
| |
| if(i == 0) |
| return SQUASHFS_INVALID_XATTR; |
| - else if(i == 1) |
| + else if(i == 1 || context_file) |
| goto skip_dup_check; |
| |
| /* |
| @@ -854,10 +917,11 @@ int read_xattrs(void *d, int type) |
| |
| for(j = 0; j < i - 1; head=head->vnext, j++) |
| if(strcmp(head->full_name, head->vnext->full_name) == 0) |
| - BAD_ERROR("Duplicate xattr name %s in file %s\n", |
| + BAD_ERROR("Duplicate xattr name %s in file %s\n", |
| head->full_name, filename); |
| |
| skip_dup_check: |
| + |
| return generate_xattrs(i, xattr_list); |
| } |
| |
| diff --git a/squashfs-tools/xattr.h b/squashfs-tools/xattr.h |
| index 0697f83..ba43d46 100644 |
| --- a/squashfs-tools/xattr.h |
| +++ b/squashfs-tools/xattr.h |
| @@ -24,6 +24,8 @@ |
| * xattr.h |
| */ |
| |
| +#include "squashfs_fs.h" |
| + |
| #define XATTR_VALUE_OOL SQUASHFS_XATTR_VALUE_OOL |
| #define XATTR_PREFIX_MASK SQUASHFS_XATTR_PREFIX_MASK |
| |
| @@ -83,6 +85,8 @@ struct xattr_add { |
| extern int generate_xattrs(int, struct xattr_list *); |
| |
| #ifdef XATTR_SUPPORT |
| +#include <regex.h> |
| +extern int xattr_get_prefix(struct xattr_list *xattr, char *name); |
| extern int get_xattrs(int, struct squashfs_super_block *); |
| extern int read_xattrs(void *, int type); |
| extern long long write_xattrs(); |
| @@ -103,7 +107,11 @@ extern int read_pseudo_xattr(char *orig_def, char *filename, char *name, char *d |
| extern void print_xattr(char *, unsigned int, int); |
| extern int has_xattrs(unsigned int); |
| #else |
| -#include "squashfs_swap.h" |
| + |
| +static inline int xattr_get_prefix(struct xattr_list *xattr, char *name) |
| +{ |
| + return -1; |
| +} |
| |
| static inline int get_xattrs(int fd, struct squashfs_super_block *sBlk) |
| { |
| -- |
| 2.43.0.381.gb435a96ce8-goog |
| |