blob: cae1f7f6626e42fba7f97b31e63bba11a00eb796 [file] [log] [blame]
Elliott Hughesee296862015-03-28 10:39:46 -07001#define TAG "ext4_utils"
2
Paul Lawrencebc2eb8c2015-04-28 22:13:04 +00003#include "ext4_crypt_init_extensions.h"
Paul Lawrence92da49d2015-02-25 15:11:13 -08004
5#include <string>
Paul Lawrence92da49d2015-02-25 15:11:13 -08006
Paul Lawrencebc2eb8c2015-04-28 22:13:04 +00007#include <dirent.h>
Paul Lawrence92da49d2015-02-25 15:11:13 -08008#include <errno.h>
Elliott Hughesee296862015-03-28 10:39:46 -07009#include <sys/mount.h>
Paul Lawrence92da49d2015-02-25 15:11:13 -080010#include <sys/stat.h>
Elliott Hughesee296862015-03-28 10:39:46 -070011
12#include <cutils/klog.h>
Paul Lawrence92da49d2015-02-25 15:11:13 -080013#include <cutils/properties.h>
14#include <cutils/sockets.h>
Paul Crowley36d056c2015-04-09 10:18:54 +010015#include <poll.h>
Paul Lawrence92da49d2015-02-25 15:11:13 -080016
Paul Lawrencebc2eb8c2015-04-28 22:13:04 +000017#include "key_control.h"
Paul Lawrence61980262015-03-16 15:35:55 -070018#include "unencrypted_properties.h"
19
Paul Lawrence92da49d2015-02-25 15:11:13 -080020static const std::string arbitrary_sequence_number = "42";
Paul Lawrencebc2eb8c2015-04-28 22:13:04 +000021static const int vold_command_timeout_ms = 60 * 1000;
Paul Lawrence92da49d2015-02-25 15:11:13 -080022
23static std::string vold_command(std::string const& command)
24{
Elliott Hughesee296862015-03-28 10:39:46 -070025 KLOG_INFO(TAG, "Running command %s\n", command.c_str());
Paul Lawrencebc2eb8c2015-04-28 22:13:04 +000026 int sock = -1;
27
28 while (true) {
29 sock = socket_local_client("vold",
Paul Lawrence92da49d2015-02-25 15:11:13 -080030 ANDROID_SOCKET_NAMESPACE_RESERVED,
31 SOCK_STREAM);
Paul Lawrencebc2eb8c2015-04-28 22:13:04 +000032 if (sock >= 0) {
33 break;
34 }
35 usleep(10000);
36 }
Paul Lawrence92da49d2015-02-25 15:11:13 -080037
38 if (sock < 0) {
Elliott Hughesee296862015-03-28 10:39:46 -070039 KLOG_INFO(TAG, "Cannot open vold, failing command\n");
Paul Lawrence92da49d2015-02-25 15:11:13 -080040 return "";
41 }
42
43 class CloseSocket
44 {
45 int sock_;
46 public:
47 CloseSocket(int sock) : sock_(sock) {}
48 ~CloseSocket() { close(sock_); }
49 };
50
51 CloseSocket cs(sock);
52
53 // Use arbitrary sequence number. This should only be used when the
54 // framework is down, so this is (mostly) OK.
55 std::string actual_command = arbitrary_sequence_number + " " + command;
56 if (write(sock, actual_command.c_str(), actual_command.size() + 1) < 0) {
Elliott Hughesee296862015-03-28 10:39:46 -070057 KLOG_ERROR(TAG, "Cannot write command\n");
Paul Lawrence92da49d2015-02-25 15:11:13 -080058 return "";
59 }
60
Paul Crowley36d056c2015-04-09 10:18:54 +010061 struct pollfd poll_sock = {sock, POLLIN, 0};
Paul Lawrence92da49d2015-02-25 15:11:13 -080062
Paul Crowley36d056c2015-04-09 10:18:54 +010063 int rc = poll(&poll_sock, 1, vold_command_timeout_ms);
64 if (rc < 0) {
65 KLOG_ERROR(TAG, "Error in poll %s\n", strerror(errno));
66 return "";
Paul Lawrence92da49d2015-02-25 15:11:13 -080067 }
Paul Crowley36d056c2015-04-09 10:18:54 +010068 if (!(poll_sock.revents & POLLIN)) {
69 KLOG_ERROR(TAG, "Timeout\n");
70 return "";
71 }
72 char buffer[4096];
73 memset(buffer, 0, sizeof(buffer));
74 rc = read(sock, buffer, sizeof(buffer));
75 if (rc <= 0) {
76 if (rc == 0) {
77 KLOG_ERROR(TAG, "Lost connection to Vold - did it crash?\n");
78 } else {
79 KLOG_ERROR(TAG, "Error reading data (%s)\n", strerror(errno));
80 }
81 return "";
82 }
83
84 // We don't truly know that this is the correct result. However,
85 // since this will only be used when the framework is down,
86 // it should be OK unless someone is running vdc at the same time.
87 // Worst case we force a reboot in the very rare synchronization
88 // error
89 return std::string(buffer, rc);
Paul Lawrence92da49d2015-02-25 15:11:13 -080090}
91
Paul Lawrencef9768752015-03-30 09:16:09 -070092int e4crypt_create_device_key(const char* dir,
93 int ensure_dir_exists(const char*))
Paul Lawrence92da49d2015-02-25 15:11:13 -080094{
Paul Lawrencebc2eb8c2015-04-28 22:13:04 +000095 // Already encrypted with password? If so bail
96 std::string temp_folder = std::string() + dir + "/tmp_mnt";
97 DIR* temp_dir = opendir(temp_folder.c_str());
98 if (temp_dir) {
99 closedir(temp_dir);
100 return 0;
101 }
102
Paul Lawrence92da49d2015-02-25 15:11:13 -0800103 // Make sure folder exists. Use make_dir to set selinux permissions.
Paul Lawrencebc2eb8c2015-04-28 22:13:04 +0000104 if (ensure_dir_exists(UnencryptedProperties::GetPath(dir).c_str())) {
Elliott Hughesee296862015-03-28 10:39:46 -0700105 KLOG_ERROR(TAG, "Failed to create %s with error %s\n",
Paul Lawrencebc2eb8c2015-04-28 22:13:04 +0000106 UnencryptedProperties::GetPath(dir).c_str(),
107 strerror(errno));
Paul Lawrence92da49d2015-02-25 15:11:13 -0800108 return -1;
109 }
110
Paul Lawrencebc2eb8c2015-04-28 22:13:04 +0000111 auto result = vold_command("cryptfs enablefilecrypto");
112 // ext4enc:TODO proper error handling
113 KLOG_INFO(TAG, "enablefilecrypto returned with result %s\n",
114 result.c_str());
Paul Lawrence61980262015-03-16 15:35:55 -0700115
Paul Lawrence92da49d2015-02-25 15:11:13 -0800116 return 0;
117}
118
119int e4crypt_install_keyring()
120{
Paul Lawrencebc2eb8c2015-04-28 22:13:04 +0000121 key_serial_t device_keyring = add_key("keyring", "e4crypt", 0, 0,
122 KEY_SPEC_SESSION_KEYRING);
Paul Lawrence92da49d2015-02-25 15:11:13 -0800123
124 if (device_keyring == -1) {
Elliott Hughesee296862015-03-28 10:39:46 -0700125 KLOG_ERROR(TAG, "Failed to create keyring\n");
Paul Lawrence92da49d2015-02-25 15:11:13 -0800126 return -1;
127 }
128
Paul Lawrence61980262015-03-16 15:35:55 -0700129 KLOG_INFO(TAG, "Keyring created wth id %d in process %d\n",
130 device_keyring, getpid());
Paul Lawrence92da49d2015-02-25 15:11:13 -0800131
Paul Lawrence92da49d2015-02-25 15:11:13 -0800132 return 0;
133}
134
Paul Lawrence92da49d2015-02-25 15:11:13 -0800135int e4crypt_set_directory_policy(const char* dir)
136{
137 // Only set policy on first level /data directories
Paul Lawrence61980262015-03-16 15:35:55 -0700138 // To make this less restrictive, consider using a policy file.
139 // However this is overkill for as long as the policy is simply
140 // to apply a global policy to all /data folders created via makedir
Paul Lawrence92da49d2015-02-25 15:11:13 -0800141 if (!dir || strncmp(dir, "/data/", 6) || strchr(dir + 6, '/')) {
142 return 0;
143 }
144
Paul Lawrence61980262015-03-16 15:35:55 -0700145 UnencryptedProperties props("/data");
Paul Lawrencebc2eb8c2015-04-28 22:13:04 +0000146 std::string policy = props.Get<std::string>(properties::ref);
Paul Lawrencedb1d49c2015-04-10 07:47:30 -0700147 if (policy.empty()) {
148 return 0;
149 }
150
Paul Lawrenceaf02e8a2015-05-01 05:24:04 -0700151 KLOG_INFO(TAG, "Setting policy on %s\n", dir);
Paul Lawrencedb1d49c2015-04-10 07:47:30 -0700152 int result = do_policy_set(dir, policy.c_str(), policy.size());
Paul Lawrence61980262015-03-16 15:35:55 -0700153 if (result) {
Paul Lawrencebc2eb8c2015-04-28 22:13:04 +0000154 KLOG_ERROR(TAG, "Setting %s policy on %s failed!\n",
155 policy.c_str(), dir);
Paul Lawrence92da49d2015-02-25 15:11:13 -0800156 return -1;
157 }
158
159 return 0;
160}