KeyUtil: use static local variable in isFsKeyringSupported()
Use C++'s built-in mechanism for one-time initialization rather than
implement it ourselves in a way that isn't thread-safe.
(It doesn't *actually* need to be thread-safe, since all callers of this
run under ACQUIRE_CRYPT_LOCK. But that's not easy to verify.)
Test: booted Cuttlefish and checked log for the one-time message
"Detected support for FS_IOC_ADD_ENCRYPTION_KEY"
Change-Id: I6ca5b143ca305fa95144e388efc9657e3507bf05
diff --git a/KeyUtil.cpp b/KeyUtil.cpp
index acc42db..582eea2 100644
--- a/KeyUtil.cpp
+++ b/KeyUtil.cpp
@@ -64,40 +64,37 @@
}
}
+static bool isFsKeyringSupportedImpl() {
+ android::base::unique_fd fd(open("/data", O_RDONLY | O_DIRECTORY | O_CLOEXEC));
+
+ // FS_IOC_ADD_ENCRYPTION_KEY with a NULL argument will fail with ENOTTY if
+ // the ioctl isn't supported. Otherwise it will fail with another error
+ // code such as EFAULT.
+ //
+ // Note that there's no need to check for FS_IOC_REMOVE_ENCRYPTION_KEY,
+ // since it's guaranteed to be available if FS_IOC_ADD_ENCRYPTION_KEY is.
+ // There's also no need to check for support on external volumes separately
+ // from /data, since either the kernel supports the ioctls on all
+ // fscrypt-capable filesystems or it doesn't.
+ errno = 0;
+ (void)ioctl(fd, FS_IOC_ADD_ENCRYPTION_KEY, NULL);
+ if (errno == ENOTTY) {
+ LOG(INFO) << "Kernel doesn't support FS_IOC_ADD_ENCRYPTION_KEY. Falling back to "
+ "session keyring";
+ return false;
+ }
+ if (errno != EFAULT) {
+ PLOG(WARNING) << "Unexpected error from FS_IOC_ADD_ENCRYPTION_KEY";
+ }
+ LOG(DEBUG) << "Detected support for FS_IOC_ADD_ENCRYPTION_KEY";
+ android::base::SetProperty("ro.crypto.uses_fs_ioc_add_encryption_key", "true");
+ return true;
+}
+
// Return true if the kernel supports the ioctls to add/remove fscrypt keys
// directly to/from the filesystem.
bool isFsKeyringSupported(void) {
- static bool initialized = false;
- static bool supported;
-
- if (!initialized) {
- android::base::unique_fd fd(open("/data", O_RDONLY | O_DIRECTORY | O_CLOEXEC));
-
- // FS_IOC_ADD_ENCRYPTION_KEY with a NULL argument will fail with ENOTTY
- // if the ioctl isn't supported. Otherwise it will fail with another
- // error code such as EFAULT.
- errno = 0;
- (void)ioctl(fd, FS_IOC_ADD_ENCRYPTION_KEY, NULL);
- if (errno == ENOTTY) {
- LOG(INFO) << "Kernel doesn't support FS_IOC_ADD_ENCRYPTION_KEY. Falling back to "
- "session keyring";
- supported = false;
- } else {
- if (errno != EFAULT) {
- PLOG(WARNING) << "Unexpected error from FS_IOC_ADD_ENCRYPTION_KEY";
- }
- LOG(DEBUG) << "Detected support for FS_IOC_ADD_ENCRYPTION_KEY";
- supported = true;
- android::base::SetProperty("ro.crypto.uses_fs_ioc_add_encryption_key", "true");
- }
- // There's no need to check for FS_IOC_REMOVE_ENCRYPTION_KEY, since it's
- // guaranteed to be available if FS_IOC_ADD_ENCRYPTION_KEY is. There's
- // also no need to check for support on external volumes separately from
- // /data, since either the kernel supports the ioctls on all
- // fscrypt-capable filesystems or it doesn't.
-
- initialized = true;
- }
+ static bool supported = isFsKeyringSupportedImpl();
return supported;
}