Fix logical bugs in adu-shell script execution (issue #766) - #895
Merged
Conversation
In adu-shell Script::Execute(): - Do not execute a script that does not exist; log a FileNotFound error and return the new ADUSHELL_EXIT_FILE_NOT_FOUND instead of launching a missing file. - Set filePermissionsChanged only after a successful chmod (it was previously set only on chmod failure, so changed permissions were never restored). - Restore the original permissions (not the new exec mode) after execution, and restore the original ownership as well (before permissions, since chown clears setuid/setgid bits). Translate adu-shell's reserved exit codes into meaningful extended result codes in the script step handler (new ADUC_ERC_SCRIPT_HANDLER_EXECUTE_* codes), keeping the generic child-process wrapper for a script's own exit codes. Add Catch2 unit tests for the missing-file, permission-restore, and ownership-unchanged behaviors. Tests use a unique scratch directory under the build's configurable work folder (ADU_SHELL_TEST_TMP_DIR derived from ADUC_TMP_DIR_PATH) with RAII cleanup instead of a hardcoded /tmp path.
chgennar
approved these changes
Jun 23, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes the logical bugs in
adu-shell'sScript::Execute()reported in #766, additionally restores file ownership after execution, and surfaces the resulting failures to IoT Hub as meaningful extended result codes.Bug fixes (
src/adu-shell/src/script_tasks.cpp)Issue #766 identified three logical mistakes in
Execute():stat()only skipped the permission/ownership block, but the child process was launched unconditionally afterward. It now logs a "file not found" error and returns the newADUSHELL_EXIT_FILE_NOT_FOUNDwithout executing.filePermissionsChangedwas set in the wrong branch. It was set totrueonly whenchmodfailed, so successfully-changed permissions were never restored. It is now set after a successfulchmod.chmod(path, mode)with the new exec mode rather than the original. The original mode (captured up front) is now restored.In addition, the original ownership is now restored after execution (previously the code permanently changed ownership and never restored it). Ownership is restored before permissions, because
chown()clears the set-user-ID/set-group-ID bits.Meaningful extended result codes
Previously any non-zero
adu-shellexit code was reported to IoT Hub through the genericADUC_ERC_SCRIPT_HANDLER_CHILD_PROCESS_FAILURE_EXITCODE(exitCode)wrapper, so e.g. a missing script surfaced as an opaque0x3050100xvalue.The script step handler now maps
adu-shell's reserved sentinel exit codes to dedicated, documented ERCs:ADUSHELL_EXIT_FILE_NOT_FOUND(6)ADUC_ERC_SCRIPT_HANDLER_EXECUTE_PRIMARY_FILE_NOT_FOUND0x3050044CADUSHELL_EXIT_BAD_FILE_PERMS(4)ADUC_ERC_SCRIPT_HANDLER_EXECUTE_SET_PERMISSIONS_FAILURE0x3050044DADUSHELL_EXIT_BAD_FILE_OWNERSHIP(5)ADUC_ERC_SCRIPT_HANDLER_EXECUTE_SET_OWNERSHIP_FAILURE0x3050044EADUSHELL_EXIT_UNSUPPORTED(3)ADUC_ERC_SCRIPT_HANDLER_EXECUTE_UNSUPPORTED_ACTION0x3050044FA script's own (non-sentinel) exit code still uses the generic child-process wrapper. The new codes are defined in
scripts/error_code_generator_defs/result_codes.json(the source of truth) and the generatedsrc/inc/aduc/result.h.Tests
Added Catch2 unit tests in
src/adu-shell/tests/adushell_ut.cppcovering:The new tests and the pre-existing script-execute test now write to a unique per-run scratch directory under the build's configurable work folder (
ADU_SHELL_TEST_TMP_DIR, derived fromADUC_TMP_DIR_PATH/--work-folder) with RAII cleanup, instead of a hardcoded/tmppath that may be unavailable.Notes
adu-shell's process exit code is overloaded: it is either one of the reserved sentinel codes above or the customer script's own exit code. A script that genuinely exits with 3–6 will therefore be labeled with the corresponding sentinel ERC. This ambiguity is pre-existing and is documented in a code comment alongside the translation.Fixes #766