"Permission denied" error does not cause hard failure, but rather turns operation successful #486

Closed
opened 2021-12-30 22:27:45 +00:00 by Alexander-Shukaev · 4 comments

What I'm trying to do and why

Running borgmatic with exclude_from.

Steps to reproduce (if a bug)

Run borgmatic with exclude_from option, where a file would have such permissions that borgmatic would not be able to read it.

Actual behavior (if a bug)

borgmatic.service[186908]: ...: Creating archive
borgmatic.service[186908]: Traceback (most recent call last):
borgmatic.service[186908]:   File "/usr/bin/borg", line 33, in <module>
borgmatic.service[186908]:     sys.exit(load_entry_point('borgbackup==1.1.17', 'console_scripts', 'borg')())
borgmatic.service[186908]:   File "/usr/lib/python3.10/site-packages/borg/archiver.py", line 4692, in main
borgmatic.service[186908]:     args = archiver.get_args(sys.argv, os.environ.get('SSH_ORIGINAL_COMMAND'))
borgmatic.service[186908]:   File "/usr/lib/python3.10/site-packages/borg/archiver.py", line 4489, in get_args
borgmatic.service[186908]:     result = self.parse_args(argv[1:])
borgmatic.service[186908]:   File "/usr/lib/python3.10/site-packages/borg/archiver.py", line 4535, in parse_args
borgmatic.service[186908]:     args = parser.parse_args(args or ['-h'])
borgmatic.service[186908]:   File "/usr/lib/python3.10/argparse.py", line 1821, in parse_args
borgmatic.service[186908]:     args, argv = self.parse_known_args(args, namespace)
borgmatic.service[186908]:   File "/usr/lib/python3.10/argparse.py", line 1854, in parse_known_args
borgmatic.service[186908]:     namespace, args = self._parse_known_args(args, namespace)
borgmatic.service[186908]:   File "/usr/lib/python3.10/argparse.py", line 2045, in _parse_known_args
borgmatic.service[186908]:     positionals_end_index = consume_positionals(start_index)
borgmatic.service[186908]:   File "/usr/lib/python3.10/argparse.py", line 2022, in consume_positionals
borgmatic.service[186908]:     take_action(action, args)
borgmatic.service[186908]:   File "/usr/lib/python3.10/argparse.py", line 1931, in take_action
borgmatic.service[186908]:     action(self, namespace, argument_values, option_string)
borgmatic.service[186908]:   File "/usr/lib/python3.10/argparse.py", line 1210, in __call__
borgmatic.service[186908]:     subnamespace, arg_strings = parser.parse_known_args(arg_strings, None)
borgmatic.service[186908]:   File "/usr/lib/python3.10/argparse.py", line 1854, in parse_known_args
borgmatic.service[186908]:     namespace, args = self._parse_known_args(args, namespace)
borgmatic.service[186908]:   File "/usr/lib/python3.10/argparse.py", line 2063, in _parse_known_args
borgmatic.service[186908]:     start_index = consume_optional(start_index)
borgmatic.service[186908]:   File "/usr/lib/python3.10/argparse.py", line 2003, in consume_optional
borgmatic.service[186908]:     take_action(action, args, option_string)
borgmatic.service[186908]:   File "/usr/lib/python3.10/argparse.py", line 1931, in take_action
borgmatic.service[186908]:     action(self, namespace, argument_values, option_string)
borgmatic.service[186908]:   File "/usr/lib/python3.10/site-packages/borg/patterns.py", line 56, in __call__
borgmatic.service[186908]:     with open(filename) as f:
borgmatic.service[186908]: PermissionError: [Errno 13] Permission denied: '/.../excludes'

After that, it would go ahead and treat create operation successful and even run after_backup hook instead of on_error one. I actually had failing backups going unnoticed for a while because of that. I have corresponding email notifications set up on both hooks, and in this case it was fooling me to believe that everything is OK, since the emails would reflect success rather than failure. I only realized that something is wrong when I accidentally noticed security not being incremented anymore for a while.

Expected behavior (if a bug)

All fatal errors should unconditinally fail the backup process, report proper exit status, and run corresponding hook. I guess some review of other code paths, not just this one, might be needed.

Environment

borgmatic version: 1.5.21

Borg version: 1.1.17

Python version: 3.10.1

#### What I'm trying to do and why Running `borgmatic` with `exclude_from`. #### Steps to reproduce (if a bug) Run `borgmatic` with `exclude_from` option, where a file would have such permissions that `borgmatic` would not be able to read it. #### Actual behavior (if a bug) ``` borgmatic.service[186908]: ...: Creating archive borgmatic.service[186908]: Traceback (most recent call last): borgmatic.service[186908]: File "/usr/bin/borg", line 33, in <module> borgmatic.service[186908]: sys.exit(load_entry_point('borgbackup==1.1.17', 'console_scripts', 'borg')()) borgmatic.service[186908]: File "/usr/lib/python3.10/site-packages/borg/archiver.py", line 4692, in main borgmatic.service[186908]: args = archiver.get_args(sys.argv, os.environ.get('SSH_ORIGINAL_COMMAND')) borgmatic.service[186908]: File "/usr/lib/python3.10/site-packages/borg/archiver.py", line 4489, in get_args borgmatic.service[186908]: result = self.parse_args(argv[1:]) borgmatic.service[186908]: File "/usr/lib/python3.10/site-packages/borg/archiver.py", line 4535, in parse_args borgmatic.service[186908]: args = parser.parse_args(args or ['-h']) borgmatic.service[186908]: File "/usr/lib/python3.10/argparse.py", line 1821, in parse_args borgmatic.service[186908]: args, argv = self.parse_known_args(args, namespace) borgmatic.service[186908]: File "/usr/lib/python3.10/argparse.py", line 1854, in parse_known_args borgmatic.service[186908]: namespace, args = self._parse_known_args(args, namespace) borgmatic.service[186908]: File "/usr/lib/python3.10/argparse.py", line 2045, in _parse_known_args borgmatic.service[186908]: positionals_end_index = consume_positionals(start_index) borgmatic.service[186908]: File "/usr/lib/python3.10/argparse.py", line 2022, in consume_positionals borgmatic.service[186908]: take_action(action, args) borgmatic.service[186908]: File "/usr/lib/python3.10/argparse.py", line 1931, in take_action borgmatic.service[186908]: action(self, namespace, argument_values, option_string) borgmatic.service[186908]: File "/usr/lib/python3.10/argparse.py", line 1210, in __call__ borgmatic.service[186908]: subnamespace, arg_strings = parser.parse_known_args(arg_strings, None) borgmatic.service[186908]: File "/usr/lib/python3.10/argparse.py", line 1854, in parse_known_args borgmatic.service[186908]: namespace, args = self._parse_known_args(args, namespace) borgmatic.service[186908]: File "/usr/lib/python3.10/argparse.py", line 2063, in _parse_known_args borgmatic.service[186908]: start_index = consume_optional(start_index) borgmatic.service[186908]: File "/usr/lib/python3.10/argparse.py", line 2003, in consume_optional borgmatic.service[186908]: take_action(action, args, option_string) borgmatic.service[186908]: File "/usr/lib/python3.10/argparse.py", line 1931, in take_action borgmatic.service[186908]: action(self, namespace, argument_values, option_string) borgmatic.service[186908]: File "/usr/lib/python3.10/site-packages/borg/patterns.py", line 56, in __call__ borgmatic.service[186908]: with open(filename) as f: borgmatic.service[186908]: PermissionError: [Errno 13] Permission denied: '/.../excludes' ``` After that, it would go ahead and treat `create` operation successful and even run `after_backup` hook instead of `on_error` one. I actually had failing backups going unnoticed for a while because of that. I have corresponding email notifications set up on both hooks, and in this case it was fooling me to believe that everything is OK, since the emails would reflect success rather than failure. I only realized that something is wrong when I accidentally noticed `security` not being incremented anymore for a while. #### Expected behavior (if a bug) All fatal errors should unconditinally fail the backup process, report proper exit status, and run corresponding hook. I guess some review of other code paths, not just this one, might be needed. #### Environment **borgmatic version:** 1.5.21 **Borg version:** 1.1.17 **Python version:** 3.10.1
Owner

I've reproduced this problem locally. Thank you for reporting it!

I've reproduced this problem locally. Thank you for reporting it!
witten added the
bug
label 2022-03-07 19:31:56 +00:00
Owner

So I think what's going on here is Borg is returning a "warning" exit code instead of an "error" exit code, which borgmatic intentionally does not error on. One fix for this specific issue could be for borgmatic to try to read the file before handing it off to Borg.. and error if there is a permission denied error.

So I think what's going on here is Borg is returning a "warning" exit code instead of an "error" exit code, which borgmatic intentionally does not error on. One fix for this specific issue could be for borgmatic to try to read the file before handing it off to Borg.. and error if there is a permission denied error.
Owner

I implemented this fix for both exclude_from and patterns_from in borgmatic master. This will be part of the next release. Thanks for reporting it!

I implemented this fix for both `exclude_from` and `patterns_from` in borgmatic master. This will be part of the next release. Thanks for reporting it!
Owner

Released in borgmatic 1.5.24.

Released in borgmatic 1.5.24.
Sign in to join this conversation.
No Milestone
No Assignees
2 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: borgmatic-collective/borgmatic#486
No description provided.