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 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 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 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 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 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 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 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 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 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 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 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 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