vold: remove session keyring workaround for old kernels

The android-4.14-stable and later kernels support the
FS_IOC_ADD_ENCRYPTION_KEY and FS_IOC_REMOVE_ENCRYPTION_KEY ioctls.  This
has superseded the old way of adding fscrypt keys to the kernel, which
was to use the add_key() syscall to add keys to the "session" keyring.
On kernels that support the ioctls, Android doesn't use the obsolete
way.  Since upgrading even just to Android 14 requires at minimum a
android-4.14-stable kernel (according to
https://source.android.com/docs/core/architecture/kernel/android-common#compatibility-matrix),
there is no need to support the obsolete way anymore.

Therefore, this commit removes the code that added and removed keys
to/from the session keyring.  Now the ioctls are used unconditionally.

Flag: N/A for the following reasons:
      - Removing obsolete code, which is fairly safe
      - Very early code, so runtime flag cannot be used
      - This topic also removes code from init, which cannot use aconfig
        libraries because they do not support recovery_available

Bug: 311736104
Test: Build and boot Cuttlefish
Change-Id: I0d9abbda77b1ac838ea6f014dbe22ab032c0e5ae
diff --git a/Android.bp b/Android.bp
index 6d70d4d..00d1382 100644
--- a/Android.bp
+++ b/Android.bp
@@ -62,7 +62,6 @@
         "libincfs",
         "libhidlbase",
         "libkeymint_support",
-        "libkeyutils",
         "liblog",
         "liblogwrap",
         "libselinux",
diff --git a/FsCrypt.cpp b/FsCrypt.cpp
index 9f6403c..4f1f5b2 100644
--- a/FsCrypt.cpp
+++ b/FsCrypt.cpp
@@ -50,7 +50,6 @@
 #include <cutils/properties.h>
 
 #include <fscrypt/fscrypt.h>
-#include <keyutils.h>
 #include <libdm/dm.h>
 
 #include <android-base/file.h>
@@ -76,7 +75,6 @@
 using android::vold::SetDefaultAcl;
 using android::vold::SetQuotaInherit;
 using android::vold::SetQuotaProjectId;
-using android::vold::writeStringToFile;
 using namespace android::fscrypt;
 using namespace android::dm;
 
@@ -632,27 +630,6 @@
     return true;
 }
 
-// "Lock" all encrypted directories whose key has been removed.  This is needed
-// in the case where the keys are being put in the session keyring (rather in
-// the newer filesystem-level keyrings), because removing a key from the session
-// keyring doesn't affect inodes in the kernel's inode cache whose per-file key
-// was already set up.  So to remove the per-file keys and make the files
-// "appear encrypted", these inodes must be evicted.
-//
-// To do this, sync() to clean all dirty inodes, then drop all reclaimable slab
-// objects systemwide.  This is overkill, but it's the best available method
-// currently.  Don't use drop_caches mode "3" because that also evicts pagecache
-// for in-use files; all files relevant here are already closed and sync'ed.
-static void drop_caches_if_needed() {
-    if (android::vold::isFsKeyringSupported()) {
-        return;
-    }
-    sync();
-    if (!writeStringToFile("2", "/proc/sys/vm/drop_caches")) {
-        PLOG(ERROR) << "Failed to drop caches during key eviction";
-    }
-}
-
 // Evicts all the user's keys of one type from all volumes (internal and adoptable).
 // This evicts either CE keys or DE keys, depending on which map is passed.
 static bool evict_user_keys(std::map<userid_t, UserPolicies>& policy_map, userid_t user_id) {
@@ -665,7 +642,6 @@
             success &= android::vold::evictKey(BuildDataPath(volume_uuid), policy);
         }
         policy_map.erase(it);
-        drop_caches_if_needed();
     }
     return success;
 }
diff --git a/KeyUtil.cpp b/KeyUtil.cpp
index 9e8920d..bd2ccdd 100644
--- a/KeyUtil.cpp
+++ b/KeyUtil.cpp
@@ -28,7 +28,6 @@
 
 #include <android-base/file.h>
 #include <android-base/logging.h>
-#include <keyutils.h>
 
 #include "KeyStorage.h"
 #include "Utils.h"
@@ -75,39 +74,6 @@
     }
 }
 
-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";
-    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 supported = isFsKeyringSupportedImpl();
-    return supported;
-}
-
 // Get raw keyref - used to make keyname and to pass to ioctl
 static std::string generateKeyRef(const uint8_t* key, int length) {
     SHA512_CTX c;
@@ -127,20 +93,6 @@
     return std::string((char*)key_ref2, FSCRYPT_KEY_DESCRIPTOR_SIZE);
 }
 
-static bool fillKey(const KeyBuffer& key, fscrypt_key* fs_key) {
-    if (key.size() != FSCRYPT_MAX_KEY_SIZE) {
-        LOG(ERROR) << "Wrong size key " << key.size();
-        return false;
-    }
-    static_assert(FSCRYPT_MAX_KEY_SIZE == sizeof(fs_key->raw), "Mismatch of max key sizes");
-    fs_key->mode = 0;  // unused by kernel
-    memcpy(fs_key->raw, key.data(), key.size());
-    fs_key->size = key.size();
-    return true;
-}
-
-static char const* const NAME_PREFIXES[] = {"ext4", "f2fs", "fscrypt", nullptr};
-
 static std::string keyrefstring(const std::string& raw_ref) {
     std::ostringstream o;
     for (unsigned char i : raw_ref) {
@@ -149,44 +101,6 @@
     return o.str();
 }
 
-static std::string buildLegacyKeyName(const std::string& prefix, const std::string& raw_ref) {
-    return prefix + ":" + keyrefstring(raw_ref);
-}
-
-// Get the ID of the keyring we store all fscrypt keys in when the kernel is too
-// old to support FS_IOC_ADD_ENCRYPTION_KEY and FS_IOC_REMOVE_ENCRYPTION_KEY.
-static bool fscryptKeyring(key_serial_t* device_keyring) {
-    *device_keyring = keyctl_search(KEY_SPEC_SESSION_KEYRING, "keyring", "fscrypt", 0);
-    if (*device_keyring == -1) {
-        PLOG(ERROR) << "Unable to find device keyring";
-        return false;
-    }
-    return true;
-}
-
-// Add an encryption key to the legacy global session keyring.
-static bool installKeyLegacy(const KeyBuffer& key, const std::string& raw_ref) {
-    // Place fscrypt_key into automatically zeroing buffer.
-    KeyBuffer fsKeyBuffer(sizeof(fscrypt_key));
-    fscrypt_key& fs_key = *reinterpret_cast<fscrypt_key*>(fsKeyBuffer.data());
-
-    if (!fillKey(key, &fs_key)) return false;
-    key_serial_t device_keyring;
-    if (!fscryptKeyring(&device_keyring)) return false;
-    for (char const* const* name_prefix = NAME_PREFIXES; *name_prefix != nullptr; name_prefix++) {
-        auto ref = buildLegacyKeyName(*name_prefix, raw_ref);
-        key_serial_t key_id =
-            add_key("logon", ref.c_str(), (void*)&fs_key, sizeof(fs_key), device_keyring);
-        if (key_id == -1) {
-            PLOG(ERROR) << "Failed to insert key into keyring " << device_keyring;
-            return false;
-        }
-        LOG(DEBUG) << "Added key " << key_id << " (" << ref << ") to keyring " << device_keyring
-                   << " in process " << getpid();
-    }
-    return true;
-}
-
 // Build a struct fscrypt_key_specifier for use in the key management ioctls.
 static bool buildKeySpecifier(fscrypt_key_specifier* spec, const EncryptionPolicy& policy) {
     switch (policy.options.version) {
@@ -230,9 +144,6 @@
             // "descriptor", which must be provided by userspace.  We use the
             // first 8 bytes from the double SHA-512 of the key itself.
             policy->key_raw_ref = generateKeyRef((const uint8_t*)key.data(), key.size());
-            if (!isFsKeyringSupported()) {
-                return installKeyLegacy(key, policy->key_raw_ref);
-            }
             if (!buildKeySpecifier(&arg->key_spec, *policy)) {
                 return false;
             }
@@ -276,29 +187,6 @@
     return true;
 }
 
-// Remove an encryption key from the legacy global session keyring.
-static bool evictKeyLegacy(const std::string& raw_ref) {
-    key_serial_t device_keyring;
-    if (!fscryptKeyring(&device_keyring)) return false;
-    bool success = true;
-    for (char const* const* name_prefix = NAME_PREFIXES; *name_prefix != nullptr; name_prefix++) {
-        auto ref = buildLegacyKeyName(*name_prefix, raw_ref);
-        auto key_serial = keyctl_search(device_keyring, "logon", ref.c_str(), 0);
-
-        // Unlink the key from the keyring.  Prefer unlinking to revoking or
-        // invalidating, since unlinking is actually no less secure currently, and
-        // it avoids bugs in certain kernel versions where the keyring key is
-        // referenced from places it shouldn't be.
-        if (keyctl_unlink(key_serial, device_keyring) != 0) {
-            PLOG(ERROR) << "Failed to unlink key with serial " << key_serial << " ref " << ref;
-            success = false;
-        } else {
-            LOG(DEBUG) << "Unlinked key with serial " << key_serial << " ref " << ref;
-        }
-    }
-    return success;
-}
-
 static void waitForBusyFiles(const struct fscrypt_key_specifier key_spec, const std::string ref,
                              const std::string mountpoint) {
     android::base::unique_fd fd(open(mountpoint.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC));
@@ -359,9 +247,6 @@
 
 bool evictKey(const std::string& mountpoint, const EncryptionPolicy& policy) {
     const std::lock_guard<std::mutex> lock(fscrypt_keyring_mutex);
-    if (policy.options.version == 1 && !isFsKeyringSupported()) {
-        return evictKeyLegacy(policy.key_raw_ref);
-    }
 
     android::base::unique_fd fd(open(mountpoint.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC));
     if (fd == -1) {
diff --git a/KeyUtil.h b/KeyUtil.h
index 17a234e..cc1a1f9 100644
--- a/KeyUtil.h
+++ b/KeyUtil.h
@@ -43,28 +43,15 @@
 // be generated.
 const KeyGeneration neverGen();
 
-bool isFsKeyringSupported(void);
-
 // Install a file-based encryption key to the kernel, for use by encrypted files
 // on the specified filesystem using the specified encryption policy version.
 //
-// For v1 policies, we use FS_IOC_ADD_ENCRYPTION_KEY if the kernel supports it.
-// Otherwise we add the key to the legacy global session keyring.
-//
-// For v2 policies, we always use FS_IOC_ADD_ENCRYPTION_KEY; it's the only way
-// the kernel supports.
-//
 // Returns %true on success, %false on failure.  On success also sets *policy
 // to the EncryptionPolicy used to refer to this key.
 bool installKey(const std::string& mountpoint, const android::fscrypt::EncryptionOptions& options,
                 const KeyBuffer& key, android::fscrypt::EncryptionPolicy* policy);
 
 // Evict a file-based encryption key from the kernel.
-//
-// We use FS_IOC_REMOVE_ENCRYPTION_KEY if the kernel supports it.  Otherwise we
-// remove the key from the legacy global session keyring.
-//
-// In the latter case, the caller is responsible for dropping caches.
 bool evictKey(const std::string& mountpoint, const android::fscrypt::EncryptionPolicy& policy);
 
 // Retrieves the key from the named directory, or generates it if it doesn't