OSDN Git Service

f2fs_utils: Update for f2fs-tools 1.6.1
[android-x86/system-extras.git] / ext4_utils / ext4_crypt_init_extensions.cpp
1 #define TAG "ext4_utils"
2
3 #include "ext4_crypt_init_extensions.h"
4
5 #include <string>
6
7 #include <dirent.h>
8 #include <errno.h>
9 #include <sys/mount.h>
10 #include <sys/stat.h>
11
12 #include <cutils/klog.h>
13 #include <cutils/properties.h>
14 #include <cutils/sockets.h>
15 #include <poll.h>
16
17 #include "key_control.h"
18 #include "unencrypted_properties.h"
19
20 static const std::string arbitrary_sequence_number = "42";
21 static const int vold_command_timeout_ms = 60 * 1000;
22
23 static std::string vold_command(std::string const& command)
24 {
25     KLOG_INFO(TAG, "Running command %s\n", command.c_str());
26     int sock = -1;
27
28 #ifdef TARGET_USES_LOGD
29     while (true) {
30         sock = socket_local_client("cryptd",
31                                    ANDROID_SOCKET_NAMESPACE_RESERVED,
32                                    SOCK_STREAM);
33         if (sock >= 0) {
34             break;
35         }
36         usleep(10000);
37     }
38 #endif
39
40     if (sock < 0) {
41         KLOG_INFO(TAG, "Cannot open vold, failing command (%s)\n", strerror(errno));
42         return "";
43     }
44
45     class CloseSocket
46     {
47         int sock_;
48     public:
49         CloseSocket(int sock) : sock_(sock) {}
50         ~CloseSocket() { close(sock_); }
51     };
52
53     CloseSocket cs(sock);
54
55     // Use arbitrary sequence number. This should only be used when the
56     // framework is down, so this is (mostly) OK.
57     std::string actual_command = arbitrary_sequence_number + " " + command;
58     if (write(sock, actual_command.c_str(), actual_command.size() + 1) < 0) {
59         KLOG_ERROR(TAG, "Cannot write command (%s)\n", strerror(errno));
60         return "";
61     }
62
63     struct pollfd poll_sock = {sock, POLLIN, 0};
64
65     int rc = TEMP_FAILURE_RETRY(poll(&poll_sock, 1, vold_command_timeout_ms));
66     if (rc < 0) {
67         KLOG_ERROR(TAG, "Error in poll (%s)\n", strerror(errno));
68         return "";
69     }
70
71     if (!(poll_sock.revents & POLLIN)) {
72         KLOG_ERROR(TAG, "Timeout\n");
73         return "";
74     }
75     char buffer[4096];
76     memset(buffer, 0, sizeof(buffer));
77     rc = TEMP_FAILURE_RETRY(read(sock, buffer, sizeof(buffer)));
78     if (rc <= 0) {
79         if (rc == 0) {
80             KLOG_ERROR(TAG, "Lost connection to Vold - did it crash?\n");
81         } else {
82             KLOG_ERROR(TAG, "Error reading data (%s)\n", strerror(errno));
83         }
84         return "";
85     }
86
87     // We don't truly know that this is the correct result. However,
88     // since this will only be used when the framework is down,
89     // it should be OK unless someone is running vdc at the same time.
90     // Worst case we force a reboot in the very rare synchronization
91     // error
92     return std::string(buffer, rc);
93 }
94
95 int e4crypt_create_device_key(const char* dir,
96                               int ensure_dir_exists(const char*))
97 {
98     // Already encrypted with password? If so bail
99     std::string temp_folder = std::string() + dir + "/tmp_mnt";
100     DIR* temp_dir = opendir(temp_folder.c_str());
101     if (temp_dir) {
102         closedir(temp_dir);
103         return 0;
104     }
105
106     // Make sure folder exists. Use make_dir to set selinux permissions.
107     if (ensure_dir_exists(UnencryptedProperties::GetPath(dir).c_str())) {
108         KLOG_ERROR(TAG, "Failed to create %s (%s)\n",
109                    UnencryptedProperties::GetPath(dir).c_str(),
110                    strerror(errno));
111         return -1;
112     }
113
114     auto result = vold_command("cryptfs enablefilecrypto");
115     // ext4enc:TODO proper error handling
116     KLOG_INFO(TAG, "enablefilecrypto returned with result %s\n",
117               result.c_str());
118
119     return 0;
120 }
121
122 int e4crypt_install_keyring()
123 {
124     key_serial_t device_keyring = add_key("keyring", "e4crypt", 0, 0,
125                                           KEY_SPEC_SESSION_KEYRING);
126
127     if (device_keyring == -1) {
128         KLOG_ERROR(TAG, "Failed to create keyring (%s)\n", strerror(errno));
129         return -1;
130     }
131
132     KLOG_INFO(TAG, "Keyring created wth id %d in process %d\n",
133               device_keyring, getpid());
134
135     return 0;
136 }
137
138 int e4crypt_set_directory_policy(const char* dir)
139 {
140     // Only set policy on first level /data directories
141     // To make this less restrictive, consider using a policy file.
142     // However this is overkill for as long as the policy is simply
143     // to apply a global policy to all /data folders created via makedir
144     if (!dir || strncmp(dir, "/data/", 6) || strchr(dir + 6, '/')) {
145         return 0;
146     }
147
148     // Don't encrypt lost+found - ext4 doesn't like it
149     if (!strcmp(dir, "/data/lost+found")) {
150         return 0;
151     }
152
153     // ext4enc:TODO exclude /data/user with a horrible special case.
154     if (!strcmp(dir, "/data/user")) {
155         return 0;
156     }
157
158     UnencryptedProperties props("/data");
159     std::string policy = props.Get<std::string>(properties::ref);
160     if (policy.empty()) {
161         // ext4enc:TODO why is this OK?
162         return 0;
163     }
164
165     KLOG_INFO(TAG, "Setting policy on %s\n", dir);
166     int result = do_policy_set(dir, policy.c_str(), policy.size());
167     if (result) {
168         KLOG_ERROR(TAG, "Setting %02x%02x%02x%02x policy on %s failed!\n",
169                    policy[0], policy[1], policy[2], policy[3], dir);
170         return -1;
171     }
172
173     return 0;
174 }
175
176 int e4crypt_set_user_crypto_policies(const char* dir)
177 {
178     auto command = std::string() + "cryptfs setusercryptopolicies " + dir;
179     auto result = vold_command(command);
180     // ext4enc:TODO proper error handling
181     KLOG_INFO(TAG, "setusercryptopolicies returned with result %s\n",
182               result.c_str());
183     return 0;
184 }