1 /*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #define TRACE_TAG SYNC
18
19 #include "sysdeps.h"
20 #include "file_sync_service.h"
21
22 #include <dirent.h>
23 #include <errno.h>
24 #include <log/log.h>
25 #include <selinux/android.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <sys/stat.h>
30 #include <sys/types.h>
31 #include <unistd.h>
32 #include <utime.h>
33
34 #include "adb.h"
35 #include "adb_io.h"
36 #include "adb_utils.h"
37 #include "private/android_filesystem_config.h"
38 #include "security_log_tags.h"
39
40 #include <android-base/stringprintf.h>
41 #include <android-base/strings.h>
42
should_use_fs_config(const std::string & path)43 static bool should_use_fs_config(const std::string& path) {
44 // TODO: use fs_config to configure permissions on /data.
45 return android::base::StartsWith(path, "/system/") ||
46 android::base::StartsWith(path, "/vendor/") ||
47 android::base::StartsWith(path, "/oem/");
48 }
49
secure_mkdirs(const std::string & path)50 static bool secure_mkdirs(const std::string& path) {
51 uid_t uid = -1;
52 gid_t gid = -1;
53 unsigned int mode = 0775;
54 uint64_t cap = 0;
55
56 if (path[0] != '/') return false;
57
58 std::vector<std::string> path_components = android::base::Split(path, "/");
59 std::string partial_path;
60 for (const auto& path_component : path_components) {
61 if (partial_path.back() != OS_PATH_SEPARATOR) partial_path += OS_PATH_SEPARATOR;
62 partial_path += path_component;
63
64 if (should_use_fs_config(partial_path)) {
65 fs_config(partial_path.c_str(), 1, nullptr, &uid, &gid, &mode, &cap);
66 }
67 if (adb_mkdir(partial_path.c_str(), mode) == -1) {
68 if (errno != EEXIST) {
69 return false;
70 }
71 } else {
72 if (chown(partial_path.c_str(), uid, gid) == -1) {
73 return false;
74 }
75 // Not all filesystems support setting SELinux labels. http://b/23530370.
76 selinux_android_restorecon(partial_path.c_str(), 0);
77 }
78 }
79 return true;
80 }
81
do_stat(int s,const char * path)82 static bool do_stat(int s, const char* path) {
83 syncmsg msg;
84 msg.stat.id = ID_STAT;
85
86 struct stat st;
87 memset(&st, 0, sizeof(st));
88 // TODO: add a way to report that the stat failed!
89 lstat(path, &st);
90 msg.stat.mode = st.st_mode;
91 msg.stat.size = st.st_size;
92 msg.stat.time = st.st_mtime;
93
94 return WriteFdExactly(s, &msg.stat, sizeof(msg.stat));
95 }
96
do_list(int s,const char * path)97 static bool do_list(int s, const char* path) {
98 dirent* de;
99
100 syncmsg msg;
101 msg.dent.id = ID_DENT;
102
103 std::unique_ptr<DIR, int(*)(DIR*)> d(opendir(path), closedir);
104 if (!d) goto done;
105
106 while ((de = readdir(d.get()))) {
107 std::string filename(android::base::StringPrintf("%s/%s", path, de->d_name));
108
109 struct stat st;
110 if (lstat(filename.c_str(), &st) == 0) {
111 size_t d_name_length = strlen(de->d_name);
112 msg.dent.mode = st.st_mode;
113 msg.dent.size = st.st_size;
114 msg.dent.time = st.st_mtime;
115 msg.dent.namelen = d_name_length;
116
117 if (!WriteFdExactly(s, &msg.dent, sizeof(msg.dent)) ||
118 !WriteFdExactly(s, de->d_name, d_name_length)) {
119 return false;
120 }
121 }
122 }
123
124 done:
125 msg.dent.id = ID_DONE;
126 msg.dent.mode = 0;
127 msg.dent.size = 0;
128 msg.dent.time = 0;
129 msg.dent.namelen = 0;
130 return WriteFdExactly(s, &msg.dent, sizeof(msg.dent));
131 }
132
133 // Make sure that SendFail from adb_io.cpp isn't accidentally used in this file.
134 #pragma GCC poison SendFail
135
SendSyncFail(int fd,const std::string & reason)136 static bool SendSyncFail(int fd, const std::string& reason) {
137 D("sync: failure: %s", reason.c_str());
138
139 syncmsg msg;
140 msg.data.id = ID_FAIL;
141 msg.data.size = reason.size();
142 return WriteFdExactly(fd, &msg.data, sizeof(msg.data)) && WriteFdExactly(fd, reason);
143 }
144
SendSyncFailErrno(int fd,const std::string & reason)145 static bool SendSyncFailErrno(int fd, const std::string& reason) {
146 return SendSyncFail(fd, android::base::StringPrintf("%s: %s", reason.c_str(), strerror(errno)));
147 }
148
handle_send_file(int s,const char * path,uid_t uid,gid_t gid,mode_t mode,std::vector<char> & buffer,bool do_unlink)149 static bool handle_send_file(int s, const char* path, uid_t uid,
150 gid_t gid, mode_t mode, std::vector<char>& buffer, bool do_unlink) {
151 syncmsg msg;
152 unsigned int timestamp = 0;
153
154 __android_log_security_bswrite(SEC_TAG_ADB_SEND_FILE, path);
155
156 int fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, mode);
157 if (fd < 0 && errno == ENOENT) {
158 if (!secure_mkdirs(adb_dirname(path))) {
159 SendSyncFailErrno(s, "secure_mkdirs failed");
160 goto fail;
161 }
162 fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, mode);
163 }
164 if (fd < 0 && errno == EEXIST) {
165 fd = adb_open_mode(path, O_WRONLY | O_CLOEXEC, mode);
166 }
167 if (fd < 0) {
168 SendSyncFailErrno(s, "couldn't create file");
169 goto fail;
170 } else {
171 if (fchown(fd, uid, gid) == -1) {
172 SendSyncFailErrno(s, "fchown failed");
173 goto fail;
174 }
175
176 // Not all filesystems support setting SELinux labels. http://b/23530370.
177 selinux_android_restorecon(path, 0);
178
179 // fchown clears the setuid bit - restore it if present.
180 // Ignore the result of calling fchmod. It's not supported
181 // by all filesystems. b/12441485
182 fchmod(fd, mode);
183 }
184
185 while (true) {
186 if (!ReadFdExactly(s, &msg.data, sizeof(msg.data))) goto fail;
187
188 if (msg.data.id != ID_DATA) {
189 if (msg.data.id == ID_DONE) {
190 timestamp = msg.data.size;
191 break;
192 }
193 SendSyncFail(s, "invalid data message");
194 goto abort;
195 }
196
197 if (msg.data.size > buffer.size()) { // TODO: resize buffer?
198 SendSyncFail(s, "oversize data message");
199 goto abort;
200 }
201
202 if (!ReadFdExactly(s, &buffer[0], msg.data.size)) goto abort;
203
204 if (!WriteFdExactly(fd, &buffer[0], msg.data.size)) {
205 SendSyncFailErrno(s, "write failed");
206 goto fail;
207 }
208 }
209
210 adb_close(fd);
211
212 utimbuf u;
213 u.actime = timestamp;
214 u.modtime = timestamp;
215 utime(path, &u);
216
217 msg.status.id = ID_OKAY;
218 msg.status.msglen = 0;
219 return WriteFdExactly(s, &msg.status, sizeof(msg.status));
220
221 fail:
222 // If there's a problem on the device, we'll send an ID_FAIL message and
223 // close the socket. Unfortunately the kernel will sometimes throw that
224 // data away if the other end keeps writing without reading (which is
225 // the case with old versions of adb). To maintain compatibility, keep
226 // reading and throwing away ID_DATA packets until the other side notices
227 // that we've reported an error.
228 while (true) {
229 if (!ReadFdExactly(s, &msg.data, sizeof(msg.data))) goto fail;
230
231 if (msg.data.id == ID_DONE) {
232 goto abort;
233 } else if (msg.data.id != ID_DATA) {
234 char id[5];
235 memcpy(id, &msg.data.id, sizeof(msg.data.id));
236 id[4] = '\0';
237 D("handle_send_fail received unexpected id '%s' during failure", id);
238 goto abort;
239 }
240
241 if (msg.data.size > buffer.size()) {
242 D("handle_send_fail received oversized packet of length '%u' during failure",
243 msg.data.size);
244 goto abort;
245 }
246
247 if (!ReadFdExactly(s, &buffer[0], msg.data.size)) goto abort;
248 }
249
250 abort:
251 if (fd >= 0) adb_close(fd);
252 if (do_unlink) adb_unlink(path);
253 return false;
254 }
255
256 #if defined(_WIN32)
257 extern bool handle_send_link(int s, const std::string& path, std::vector<char>& buffer) __attribute__((error("no symlinks on Windows")));
258 #else
handle_send_link(int s,const std::string & path,std::vector<char> & buffer)259 static bool handle_send_link(int s, const std::string& path, std::vector<char>& buffer) {
260 syncmsg msg;
261 unsigned int len;
262 int ret;
263
264 if (!ReadFdExactly(s, &msg.data, sizeof(msg.data))) return false;
265
266 if (msg.data.id != ID_DATA) {
267 SendSyncFail(s, "invalid data message: expected ID_DATA");
268 return false;
269 }
270
271 len = msg.data.size;
272 if (len > buffer.size()) { // TODO: resize buffer?
273 SendSyncFail(s, "oversize data message");
274 return false;
275 }
276 if (!ReadFdExactly(s, &buffer[0], len)) return false;
277
278 ret = symlink(&buffer[0], path.c_str());
279 if (ret && errno == ENOENT) {
280 if (!secure_mkdirs(adb_dirname(path))) {
281 SendSyncFailErrno(s, "secure_mkdirs failed");
282 return false;
283 }
284 ret = symlink(&buffer[0], path.c_str());
285 }
286 if (ret) {
287 SendSyncFailErrno(s, "symlink failed");
288 return false;
289 }
290
291 if (!ReadFdExactly(s, &msg.data, sizeof(msg.data))) return false;
292
293 if (msg.data.id == ID_DONE) {
294 msg.status.id = ID_OKAY;
295 msg.status.msglen = 0;
296 if (!WriteFdExactly(s, &msg.status, sizeof(msg.status))) return false;
297 } else {
298 SendSyncFail(s, "invalid data message: expected ID_DONE");
299 return false;
300 }
301
302 return true;
303 }
304 #endif
305
do_send(int s,const std::string & spec,std::vector<char> & buffer)306 static bool do_send(int s, const std::string& spec, std::vector<char>& buffer) {
307 // 'spec' is of the form "/some/path,0755". Break it up.
308 size_t comma = spec.find_last_of(',');
309 if (comma == std::string::npos) {
310 SendSyncFail(s, "missing , in ID_SEND");
311 return false;
312 }
313
314 std::string path = spec.substr(0, comma);
315
316 errno = 0;
317 mode_t mode = strtoul(spec.substr(comma + 1).c_str(), nullptr, 0);
318 if (errno != 0) {
319 SendSyncFail(s, "bad mode");
320 return false;
321 }
322
323 // Don't delete files before copying if they are not "regular" or symlinks.
324 struct stat st;
325 bool do_unlink = (lstat(path.c_str(), &st) == -1) || S_ISREG(st.st_mode) || S_ISLNK(st.st_mode);
326 if (do_unlink) {
327 adb_unlink(path.c_str());
328 }
329
330 if (S_ISLNK(mode)) {
331 return handle_send_link(s, path.c_str(), buffer);
332 }
333
334 // Copy user permission bits to "group" and "other" permissions.
335 mode &= 0777;
336 mode |= ((mode >> 3) & 0070);
337 mode |= ((mode >> 3) & 0007);
338
339 uid_t uid = -1;
340 gid_t gid = -1;
341 uint64_t cap = 0;
342 if (should_use_fs_config(path)) {
343 unsigned int broken_api_hack = mode;
344 fs_config(path.c_str(), 0, nullptr, &uid, &gid, &broken_api_hack, &cap);
345 mode = broken_api_hack;
346 }
347 return handle_send_file(s, path.c_str(), uid, gid, mode, buffer, do_unlink);
348 }
349
do_recv(int s,const char * path,std::vector<char> & buffer)350 static bool do_recv(int s, const char* path, std::vector<char>& buffer) {
351 __android_log_security_bswrite(SEC_TAG_ADB_RECV_FILE, path);
352
353 int fd = adb_open(path, O_RDONLY | O_CLOEXEC);
354 if (fd < 0) {
355 SendSyncFailErrno(s, "open failed");
356 return false;
357 }
358
359 syncmsg msg;
360 msg.data.id = ID_DATA;
361 while (true) {
362 int r = adb_read(fd, &buffer[0], buffer.size());
363 if (r <= 0) {
364 if (r == 0) break;
365 SendSyncFailErrno(s, "read failed");
366 adb_close(fd);
367 return false;
368 }
369 msg.data.size = r;
370 if (!WriteFdExactly(s, &msg.data, sizeof(msg.data)) || !WriteFdExactly(s, &buffer[0], r)) {
371 adb_close(fd);
372 return false;
373 }
374 }
375
376 adb_close(fd);
377
378 msg.data.id = ID_DONE;
379 msg.data.size = 0;
380 return WriteFdExactly(s, &msg.data, sizeof(msg.data));
381 }
382
handle_sync_command(int fd,std::vector<char> & buffer)383 static bool handle_sync_command(int fd, std::vector<char>& buffer) {
384 D("sync: waiting for request");
385
386 SyncRequest request;
387 if (!ReadFdExactly(fd, &request, sizeof(request))) {
388 SendSyncFail(fd, "command read failure");
389 return false;
390 }
391 size_t path_length = request.path_length;
392 if (path_length > 1024) {
393 SendSyncFail(fd, "path too long");
394 return false;
395 }
396 char name[1025];
397 if (!ReadFdExactly(fd, name, path_length)) {
398 SendSyncFail(fd, "filename read failure");
399 return false;
400 }
401 name[path_length] = 0;
402
403 const char* id = reinterpret_cast<const char*>(&request.id);
404 D("sync: '%.4s' '%s'", id, name);
405
406 switch (request.id) {
407 case ID_STAT:
408 if (!do_stat(fd, name)) return false;
409 break;
410 case ID_LIST:
411 if (!do_list(fd, name)) return false;
412 break;
413 case ID_SEND:
414 if (!do_send(fd, name, buffer)) return false;
415 break;
416 case ID_RECV:
417 if (!do_recv(fd, name, buffer)) return false;
418 break;
419 case ID_QUIT:
420 return false;
421 default:
422 SendSyncFail(fd, android::base::StringPrintf("unknown command '%.4s' (%08x)",
423 id, request.id));
424 return false;
425 }
426
427 return true;
428 }
429
file_sync_service(int fd,void * cookie)430 void file_sync_service(int fd, void* cookie) {
431 std::vector<char> buffer(SYNC_DATA_MAX);
432
433 while (handle_sync_command(fd, buffer)) {
434 }
435
436 D("sync: done");
437 adb_close(fd);
438 }
439