platform_Cryptohome, cryptohome.py: kill c-homed on dbus silence
Move platform_Cryptohome over to using the CryptohomeProxy and
ensure that any unreplied DBus call results in cryptohomed being
ABRT'd with the hope that we'll get a crash dump on daisy flake.
As we discover blocking operations, we can move them off the main
thread.
TEST=passes; kills -ABRT if cryptohomed gets a SIGSTOP during the test (as a proof of hang detection)
BUG=chromium:303677
Change-Id: Ia40b0120f4f7a918c8288bf65b5c251fb0671223
Reviewed-on: https://chromium-review.googlesource.com/178881
Reviewed-by: Kees Cook <keescook@chromium.org>
Commit-Queue: Will Drewry <wad@chromium.org>
Tested-by: Will Drewry <wad@chromium.org>
diff --git a/client/cros/cryptohome.py b/client/cros/cryptohome.py
index 8948827..bd4c0c6 100644
--- a/client/cros/cryptohome.py
+++ b/client/cros/cryptohome.py
@@ -2,7 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import dbus, logging, os, random, re, shutil, string
+import dbus, logging, os, random, re, shutil, string, time
import common, constants
from autotest_lib.client.bin import utils
@@ -15,12 +15,10 @@
"""Generic error for ChromiumOS-specific exceptions."""
pass
-
def __run_cmd(cmd):
return utils.system_output(cmd + ' 2>&1', retain_output=True,
ignore_status=True).strip()
-
def get_user_hash(user):
"""Get the user hash for the given user."""
return utils.system_output(['cryptohome', '--action=obfuscate_user',
@@ -268,6 +266,11 @@
return '@'.join([name, domain]).lower()
+def crash_cryptohomed():
+ # Try to kill cryptohomed so we get something to work with.
+ utils.system('pkill -ABRT cryptohomed')
+ time.sleep(2) # Give it 2 seconds to dump
+
class CryptohomeProxy:
def __init__(self):
BUSNAME = 'org.chromium.Cryptohome'
@@ -277,6 +280,17 @@
obj = bus.get_object(BUSNAME, PATH)
self.iface = dbus.Interface(obj, INTERFACE)
+ # Wrap all proxied calls to catch cryptohomed failures.
+ def __call(self, method, *args):
+ try:
+ return method(*args)
+ except dbus.exceptions.DBusException, e:
+ if e.get_dbus_name() == 'org.freedesktop.DBus.Error.NoReply':
+ logging.error('Cryptohome is not responding. Sending ABRT')
+ crash_cryptohomed()
+ raise ChromiumOSError('cryptohomed aborted. Check crashes!')
+ raise e
+
def mount(self, user, password, create=False):
"""Mounts a cryptohome.
@@ -284,7 +298,10 @@
TODO(ellyjones): Migrate mount_vault() to use a multi-user-safe
heuristic, then remove this method. See <crosbug.com/20778>.
"""
- return self.iface.Mount(user, password, create, False, [])[1]
+ out = self.__call(self.iface.Mount, user, password, create, False, [])
+ if not out:
+ return out
+ return out[1]
def unmount(self, user):
"""Unmounts a cryptohome.
@@ -293,7 +310,7 @@
TODO(ellyjones): Once there's a per-user unmount method, use it. See
<crosbug.com/20778>.
"""
- return self.iface.Unmount()
+ return self.__call(self.iface.Unmount)
def is_mounted(self, user):
"""Tests whether a user's cryptohome is mounted."""
@@ -307,7 +324,7 @@
def migrate(self, user, oldkey, newkey):
"""Migrates the specified user's cryptohome from one key to another."""
- return self.iface.MigrateKey(user, oldkey, newkey)
+ return self.__call(self.iface.MigrateKey, user, oldkey, newkey)
def remove(self, user):
- return self.iface.Remove(user)
+ return self.__call(self.iface.Remove, user)