New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add exception handling around fapd handle is_active() call #560
Conversation
After merging master into this branch, on a clean FC34 VM (installed emacs, fapolicyd, the generated fapolicy-analyzer rpm), w/fapd running in
|
…fect start() call
With the monitoring thread not running,
we still observe the full assortment of errors wrt restarting the daemon after stopping it.
Also occurs on rollback, but the DBus error message does not always get displayed in the logging.debug() messages. They will show up in the journal though.
The issue is always the daemon start operation however there is no service start entry in the journal so possibly the fapolicyd start request is not being delivered to systemd or it's delivered in a format that is inconsistent/nonsensical from systemd's perspective based on the |
From the perspective of systemd, bringing down fapolicyd takes
|
Installed and tested over FC34 and Rhel 8.6, both ancillary trust changeset deployments and rollbacks. Tested with fapd in online and permissive modes. Good to go. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using context blocks on the locks would be nice.
I can also make this fail by
- Start analyzer
- Stop daemon
- Remove the fapolicyd.service file
- Start daemon from System menu
- Observe the GUI is locked
The stack trace from the above steps
Traceback (most recent call last):
File "/usr/lib/python3.6/site-packages/fapolicy_analyzer/ui/main_window.py", line 417, in on_fapdStartMenu_activate
self._fapd_mgr.start()
File "/usr/lib/python3.6/site-packages/fapolicy_analyzer/ui/fapd_manager.py", line 103, in start
pid = self._start(instance)
File "/usr/lib/python3.6/site-packages/fapolicy_analyzer/ui/fapd_manager.py", line 138, in _start
self._fapd_ref.start()
RuntimeError: DbusFailure(D-Bus error: Failed to get file context on /usr/lib/systemd/system/fapolicyd.service. (org.freedesktop.DBus.Error.AccessDenied))
@@ -209,15 +210,16 @@ def _status(self): | |||
logging.debug("fapd is currently DISABLED") | |||
return ServiceStatus.UNKNOWN | |||
elif self.mode == FapdMode.ONLINE: | |||
try: | |||
if self._fapd_lock.acquire(blocking=False): | |||
if self._fapd_lock.acquire(blocking=False): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you use a with
block here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I looked into that approach originally. The fly/ointment thing is the blocking=False argument, i.e. if the lock is not available then don't wait and return False. Fapd control operations (start/stop) are given priority over the never-ending periodic status requests.
Still digging around. I would still prefer to have locking somewhere given the status requests and stop/start requests originate on differing threads. I don't care if it's under the hood in rust-land or not.
fapolicy_analyzer/ui/fapd_manager.py
Outdated
self._fapd_prior_online_state = updated_online_state | ||
self._fapd_cur_online_state = updated_online_state | ||
logging.debug("capture_online_state(): Capturing current online status") | ||
if self._fapd_lock.acquire(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here, with
would be ideal on these locked blocks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, with
context management is Ok here. Will do.
self._fapd_status = ServiceStatus(self._fapd_ref.is_active()) | ||
else: | ||
self._fapd_status = ServiceStatus.UNKNOWN | ||
try: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
... and again.
@tparchambault There are a few other spots that lock release needs to be ensured, looks like five spots total. I think that using Letting the lock be managed may eliminate the need for try-catch in some of these scenarios. I didn't review, just saying it's possible. |
I'll try and research this more... I didn't go with the Context Manager approach because I did not see clear documentation when try/exception blocks were involved. We may be able to get rid of one or the other. |
Added context manager blocks to manage Lock acquire()/release() ops. Non-blocking Lock.acquire() left as originally coded. |
Looks improved. I can't make it fail by moving the unit file around while the app is up. Only issue I see is that caught exceptions do not send any notification to the UI. Is it possible to use a toaster message on these failures? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The toasters would be nice, but not blocking.
Sure I'll look at that tomorrow AM. SD did a nice job with the toaster messaging, so it's pretty easy to add them. He said; Probably no easy way to get a handle that's in scope... In any event I'll look at it tomorrow. I think it will be relatively easy. |
Let's add the toaster for the start/stop controls in this PR. For the status checks let's have a separate issue that instead of a toaster we get a third icon on the status display. For this PR however lets just log the failure to stderr. |
No description provided.