From 8631879536243ded98d6c9579852f27b7a9c5174 Mon Sep 17 00:00:00 2001 From: Li Dongyang Date: Wed, 21 Apr 2021 22:43:09 +1000 Subject: [PATCH] LU-11604 debugfs: add support for printing ACL decode and print Access Control Lists in debugfs stat/ea_list Change-Id: I3ee35ddb02582ab66d4e25ff76fae35935b54508 Signed-off-by: Li Dongyang Reviewed-on: https://review.whamcloud.com/43384 Reviewed-by: Andreas Dilger Tested-by: Maloo --- debugfs/xattrs.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++ lib/ext2fs/ext4_acl.h | 6 ++++ tests/d_print_acl/expect | 13 ++++++++ tests/d_print_acl/script | 51 ++++++++++++++++++++++++++++++ tests/m_rootdir_acl/expect | 21 ++++++++++-- 5 files changed, 167 insertions(+), 3 deletions(-) create mode 100644 tests/d_print_acl/expect create mode 100644 tests/d_print_acl/script diff --git a/debugfs/xattrs.c b/debugfs/xattrs.c index bab09f0..3ad368e 100644 --- a/debugfs/xattrs.c +++ b/debugfs/xattrs.c @@ -17,6 +17,7 @@ extern char *optarg; #include "support/cstring.h" #include "debugfs.h" +#include "ext2fs/ext4_acl.h" #include "ext2fs/lfsck.h" #define PRINT_XATTR_HEX 0x01 @@ -84,6 +85,76 @@ static void print_xattr(FILE *f, char *name, char *value, size_t value_len, fputc('\n', f); } +static int print_acl(FILE *f, void *name, void *value, size_t value_len) +{ + const ext4_acl_header *ext_acl = (const ext4_acl_header *)value; + const char *cp; + + if (!value || + (value_len < sizeof(ext4_acl_header)) || + (ext_acl->a_version != ext2fs_cpu_to_le32(EXT4_ACL_VERSION))) + return -EINVAL; + + cp = (const char *)value + sizeof(ext4_acl_header); + value_len -= sizeof(ext4_acl_header); + + fprintf(f, "%s:\n", name); + + while (value_len > 0) { + const ext4_acl_entry *disk_entry = (const ext4_acl_entry *)cp; + posix_acl_xattr_entry entry; + entry.e_tag = ext2fs_le16_to_cpu(disk_entry->e_tag); + entry.e_perm = ext2fs_le16_to_cpu(disk_entry->e_perm); + + switch(entry.e_tag) { + case ACL_USER_OBJ: + case ACL_USER: + fprintf(f, " user:"); + if (entry.e_tag == ACL_USER) + fprintf(f, "%u", + ext2fs_le32_to_cpu(disk_entry->e_id)); + break; + + case ACL_GROUP_OBJ: + case ACL_GROUP: + fprintf(f, " group:"); + if (entry.e_tag == ACL_GROUP) + fprintf(f, "%u", + ext2fs_le32_to_cpu(disk_entry->e_id)); + break; + + case ACL_MASK: + fprintf(f, " mask:"); + break; + + case ACL_OTHER: + fprintf(f, " other:"); + break; + + default: + fprintf(stderr, + "%s: error: invalid tag %x in ACL\n", + debug_prog_name, entry.e_tag); + return -EINVAL; + } + fprintf(f, ":"); + fprintf(f, (entry.e_perm & ACL_READ) ? "r" : "-"); + fprintf(f, (entry.e_perm & ACL_WRITE) ? "w" : "-"); + fprintf(f, (entry.e_perm & ACL_EXECUTE) ? "x" : "-"); + fprintf(f, "\n"); + + if (entry.e_tag == ACL_USER || entry.e_tag == ACL_GROUP) { + cp += sizeof(ext4_acl_entry); + value_len -= sizeof(ext4_acl_entry); + } else { + cp += sizeof(ext4_acl_entry_short); + value_len -= sizeof(ext4_acl_entry_short); + } + } + + return 0; +} + static int print_fidstr(FILE *f, void *name, void *value, size_t value_len) { struct filter_fid_old *ff = value; @@ -221,6 +292,14 @@ struct dump_attr_pretty { int (*dap_print)(FILE *f, void *name, void *value, size_t value_len); } dumpers[] = { { + .dap_name = "system.posix_acl_access", + .dap_print = print_acl, + }, + { + .dap_name = "system.posix_acl_default", + .dap_print = print_acl, + }, + { .dap_name = "trusted.fid", .dap_print = print_fidstr, }, diff --git a/lib/ext2fs/ext4_acl.h b/lib/ext2fs/ext4_acl.h index 8d4d974..8343086 100644 --- a/lib/ext2fs/ext4_acl.h +++ b/lib/ext2fs/ext4_acl.h @@ -4,6 +4,12 @@ #define EXT4_ACL_VERSION 0x0001 +/* 23.2.2 acl_perm_t values */ + +#define ACL_READ (0x04) +#define ACL_WRITE (0x02) +#define ACL_EXECUTE (0x01) + /* 23.2.5 acl_tag_t values */ #define ACL_UNDEFINED_TAG (0x00) diff --git a/tests/d_print_acl/expect b/tests/d_print_acl/expect new file mode 100644 index 0000000..03dea43 --- /dev/null +++ b/tests/d_print_acl/expect @@ -0,0 +1,13 @@ +Extended attributes: + system.posix_acl_access: + user::rwx + group::r-x + group:42:r-x + mask::r-x + other::r-x + system.posix_acl_default: + user::rwx + group::r-x + group:4:r-x + mask::r-x + other::r-x diff --git a/tests/d_print_acl/script b/tests/d_print_acl/script new file mode 100644 index 0000000..481003b --- /dev/null +++ b/tests/d_print_acl/script @@ -0,0 +1,51 @@ +test_description="decode and print Access Control Lists in debugfs" +if ! test -x $DEBUGFS_EXE; then + echo "$test_name: $test_description: skipped (no debugfs)" + return 0 +fi + +if ! setfacl --help > /dev/null 2>&1 ; then + echo "$test_name: $test_description: skipped (no setfacl)" + return 0 +fi + +MKFS_DIR=$TMPFILE.dir +OUT=$test_name.log +EXP=$test_dir/expect + +rm -rf $MKFS_DIR +mkdir -p $MKFS_DIR +mkdir $MKFS_DIR/acl_dir + +setfacl --restore=- < $OUT.new 2>&1 + +$DEBUGFS -w -R "ea_list /acl_dir" $TMPFILE >> $OUT.new 2>&1 +sed -f $cmd_dir/filter.sed $OUT.new > $OUT +rm -rf $MKFS_DIR $TMPFILE $OUT.new + +cmp -s $OUT $EXP +status=$? + +if [ "$status" = 0 ] ; then + echo "$test_name: $test_description: ok" + touch $test_name.ok +else + echo "$test_name: $test_description: failed" + diff $DIFF_OPTS $EXP $OUT > $test_name.failed +fi + +unset MKFS_DIR OUT EXP diff --git a/tests/m_rootdir_acl/expect b/tests/m_rootdir_acl/expect index 951e4bd..50f32a9 100644 --- a/tests/m_rootdir_acl/expect +++ b/tests/m_rootdir_acl/expect @@ -105,12 +105,27 @@ Extended attributes: debugfs: ea_list acl_dir Extended attributes: system.data (0) - system.posix_acl_access (28) = 01 00 00 00 01 00 07 00 04 00 05 00 08 00 05 00 2a 00 00 00 10 00 05 00 20 00 05 00 - system.posix_acl_default (28) = 01 00 00 00 01 00 07 00 04 00 05 00 08 00 05 00 04 00 00 00 10 00 05 00 20 00 05 00 + system.posix_acl_access: + user::rwx + group::r-x + group:42:r-x + mask::r-x + other::r-x + system.posix_acl_default: + user::rwx + group::r-x + group:4:r-x + mask::r-x + other::r-x debugfs: ea_list acl_dir/file Extended attributes: system.data (0) - system.posix_acl_access (28) = 01 00 00 00 01 00 07 00 04 00 05 00 08 00 05 00 2a 00 00 00 10 00 05 00 20 00 05 00 + system.posix_acl_access: + user::rwx + group::r-x + group:42:r-x + mask::r-x + other::r-x Pass 1: Checking inodes, blocks, and sizes Pass 2: Checking directory structure Pass 3: Checking directory connectivity -- 1.8.3.1