From 1504070cadf122c8d3de0d15a0e2fd35f81eb576 Mon Sep 17 00:00:00 2001 From: Michael Orlitzky Date: Wed, 9 Jan 2013 15:45:15 -0500 Subject: [PATCH] Add a new command-line option, --no-exec-mask, that disables the exec bit masking heuristics. Add tests for the new command-line option. --- run-tests.sh | 54 +++++++++++++++++++++++++++++++++++++++++ src/apply-default-acl.c | 38 ++++++++++++++++++++++------- 2 files changed, 83 insertions(+), 9 deletions(-) diff --git a/run-tests.sh b/run-tests.sh index f218a8f..4186b38 100755 --- a/run-tests.sh +++ b/run-tests.sh @@ -498,3 +498,57 @@ EOF ACTUAL=`getfacl --omit-header "${TARGET}"` compare + + + +# Test #16's setup repeated with the --no-exec-mask flag. +# +TESTNUM=20 +TARGET="${TESTDIR}"/foo +touch "${TARGET}" +chmod 644 "${TARGET}" +# The directory allows execute for user, group, and other, so the file +# should actually inherit them regardless of its initial mode when the +# --no-exec-mask flag is passed. +setfacl -d -m user:mail:rwx "${TESTDIR}" + +$BIN --no-exec-mask "${TARGET}" + +EXPECTED=$(cat < +/* Command-line options */ +static bool no_exec_mask = false; + + mode_t get_mode(const char* path) { /* * Get the mode bits from path. @@ -474,6 +478,7 @@ int apply_default_acl(const char* path) { /* Really apply the default ACL by looping through it. Returns one * for success, zero for failure (i.e. no ACL), and -1 on unexpected * errors. + */ if (path == NULL) { return 0; @@ -494,13 +499,20 @@ int apply_default_acl(const char* path) { return 0; } - int ace_result = any_can_execute_or_dir(path); - if (ace_result == -1) { + /* Default to not masking the exec bit; i.e. applying the default + ACL literally. If --no-exec-mask was not specified, then we try + to "guess" whether or not to mask the exec bit. */ + bool allow_exec = true; + + if (!no_exec_mask) { + int ace_result = any_can_execute_or_dir(path); + + if (ace_result == -1) { perror("apply_default_acl (any_can_execute_or_dir)"); return -1; } - - bool allow_exec = (bool)ace_result; + allow_exec = (bool)ace_result; + } acl_t defacl = acl_get_file(parent, ACL_TYPE_DEFAULT); @@ -563,6 +575,7 @@ int apply_default_acl(const char* path) { tag == ACL_USER_OBJ || tag == ACL_GROUP_OBJ || tag == ACL_OTHER) { + if (!allow_exec) { /* The mask doesn't affect acl_user_obj, acl_group_obj (in minimal ACLs) or acl_other entries, so if execute should be @@ -626,13 +639,16 @@ void usage(char* program_name) { printf("Flags:\n"); printf(" -h, --help Print this help message\n"); printf(" -r, --recursive Act on any given directories recursively\n"); + printf(" -x, --no-exec-mask Apply execute permissions unconditionally\n"); + + return; } int apply_default_acl_nftw(const char *target, - const struct stat *s, - int info, - struct FTW *ftw) { + const struct stat *s, + int info, + struct FTW *ftw) { /* A wrapper around the apply_default_acl() function for use with * nftw(). We need to adjust the return value so that nftw() doesn't * think we've failed. @@ -693,19 +709,20 @@ int main(int argc, char* argv[]) { return EXIT_FAILURE; } - bool recursive = false; + /* bool no_exec_mask is declared static/global */ struct option long_options[] = { /* These options set a flag. */ {"help", no_argument, NULL, 'h'}, {"recursive", no_argument, NULL, 'r'}, + {"no-exec-mask", no_argument, NULL, 'x'}, {NULL, 0, NULL, 0} }; int opt = 0; - while ((opt = getopt_long(argc, argv, "hr", long_options, NULL)) != -1) { + while ((opt = getopt_long(argc, argv, "hrx", long_options, NULL)) != -1) { switch (opt) { case 'h': usage(argv[0]); @@ -713,6 +730,9 @@ int main(int argc, char* argv[]) { case 'r': recursive = true; break; + case 'x': + no_exec_mask = true; + break; default: usage(argv[0]); return EXIT_FAILURE; -- 2.43.2