diff --git a/shared/templates/rsyslog_logfiles_attributes_modify/bash.template b/shared/templates/rsyslog_logfiles_attributes_modify/bash.template index 7a9e88247078..2a144b3edc51 100644 --- a/shared/templates/rsyslog_logfiles_attributes_modify/bash.template +++ b/shared/templates/rsyslog_logfiles_attributes_modify/bash.template @@ -6,8 +6,10 @@ RSYSLOG_ETC_CONFIG="/etc/rsyslog.conf" # * And also the log file paths listed after rsyslog's $IncludeConfig directive # (store the result into array for the case there's shell glob used as value of IncludeConfig) readarray -t OLD_INC < <(grep -e "\$IncludeConfig[[:space:]]\+[^[:space:];]\+" /etc/rsyslog.conf | cut -d ' ' -f 2) +# eval is safe here: input comes from root-owned /etc/rsyslog.conf. readarray -t RSYSLOG_INCLUDE_CONFIG < <(for INCPATH in "${OLD_INC[@]}"; do eval printf '%s\\n' "${INCPATH}"; done) readarray -t NEW_INC < <(sed -n '/^\s*include(/,/)/Ip' /etc/rsyslog.conf | sed -n 's@.*file\s*=\s*"\([/[:alnum:][:punct:]]*\)".*@\1@Ip') +# eval is safe here: input comes from root-owned /etc/rsyslog.conf. readarray -t RSYSLOG_INCLUDE < <(for INCPATH in "${NEW_INC[@]}"; do eval printf '%s\\n' "${INCPATH}"; done) # Declare an array to hold the final list of different log file paths @@ -34,7 +36,23 @@ do then RSYSLOG_CONFIG_FILES+=("${ENTRY}") else - echo "Invalid include object: ${ENTRY}" + # ENTRY may be a glob such as /etc/rsyslog.d/*.conf (not a single path). + # nullglob runs only inside process substitution (subshell), so shopt cannot + # affect the caller if this script were ever sourced. + mapfile -t _glob_paths < <( + shopt -s nullglob + for _maybe in ${ENTRY} + do + [[ -f "${_maybe}" ]] && printf '%s\n' "${_maybe}" + done + ) + if ((${#_glob_paths[@]})) + then + RSYSLOG_CONFIG_FILES+=("${_glob_paths[@]}") + else + echo "Invalid include object: ${ENTRY}" + fi + unset _glob_paths fi done @@ -80,9 +98,17 @@ done # exclude /dev/* paths (e.g., /dev/console) for LOG_FILE in "${RSYSLOG_CONFIG_FILES[@]}" do - ACTION_OMFILE_LINES=$(grep -iozP "action\s*\(\s*type\s*=\s*\"omfile\"[^\)]*\)" "${LOG_FILE}") - OMFILE_LINES=$(echo "${ACTION_OMFILE_LINES}"| grep -iaoP "\bFile\s*=\s*\"([/[:alnum:][:punct:]]*)\"\s*\)") - LOG_FILE_PATHS+=("$(echo "${OMFILE_LINES}"| grep -oE "\"([/[:alnum:][:punct:]]*)\""|tr -d "\"" | grep -v "^/dev/")") + [[ -f "${LOG_FILE}" ]] || continue + # NUL-separated matches from grep -z; normalize before further grep to avoid a single + # newline-concatenated string being appended as one bogus array element (breaks chmod). + ACTION_OMFILE_LINES=$(LC_ALL=C grep -iozP "action\s*\(\s*type\s*=\s*\"omfile\"[^\)]*\)" "${LOG_FILE}" 2>/dev/null || true) + [[ -n "${ACTION_OMFILE_LINES}" ]] || continue + _ACTION_NL=$(printf '%s' "${ACTION_OMFILE_LINES}" | tr '\0' '\n') + OMFILE_LINES=$(printf '%s' "${_ACTION_NL}" | grep -iaoP "\bFile\s*=\s*\"([/[:alnum:][:punct:]]*)\"\s*\)" || true) + [[ -n "${OMFILE_LINES}" ]] || continue + readarray -t _RSYSLOG_OMFILE_PATHS < <(printf '%s\n' "${OMFILE_LINES}" | grep -oE "\"([/[:alnum:][:punct:]]*)\"" | tr -d "\"" | grep -v "^/dev/" | grep -v '^$' || true) + LOG_FILE_PATHS+=("${_RSYSLOG_OMFILE_PATHS[@]}") + unset _ACTION_NL _RSYSLOG_OMFILE_PATHS OMFILE_LINES ACTION_OMFILE_LINES done # Ensure the correct attribute if file exists @@ -96,5 +122,10 @@ do then continue fi - $FILE_CMD "{{{ VALUE }}}" "$LOG_FILE_PATH" + # Skip non-files (mis-parsed paths, directories); chmod on missing paths must not abort. + if [[ ! -f "${LOG_FILE_PATH}" ]] + then + continue + fi + $FILE_CMD "{{{ VALUE }}}" "${LOG_FILE_PATH}" done