• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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