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 #include <stdlib.h>
18 #include <stdio.h>
19 #include <string.h>
20
21 #include <sys/stat.h>
22 #include <sys/types.h>
23 #include <dirent.h>
24 #include <utime.h>
25 #include <unistd.h>
26
27 #include <errno.h>
28 #include <private/android_filesystem_config.h>
29 #include <selinux/android.h>
30 #include "sysdeps.h"
31
32 #define TRACE_TAG TRACE_SYNC
33 #include "adb.h"
34 #include "file_sync_service.h"
35
36 /* TODO: use fs_config to configure permissions on /data */
is_on_system(const char * name)37 static bool is_on_system(const char *name) {
38 const char *SYSTEM = "/system/";
39 return (strncmp(SYSTEM, name, strlen(SYSTEM)) == 0);
40 }
41
is_on_vendor(const char * name)42 static bool is_on_vendor(const char *name) {
43 const char *VENDOR = "/vendor/";
44 return (strncmp(VENDOR, name, strlen(VENDOR)) == 0);
45 }
46
mkdirs(char * name)47 static int mkdirs(char *name)
48 {
49 int ret;
50 char *x = name + 1;
51 uid_t uid = -1;
52 gid_t gid = -1;
53 unsigned int mode = 0775;
54 uint64_t cap = 0;
55
56 if(name[0] != '/') return -1;
57
58 for(;;) {
59 x = adb_dirstart(x);
60 if(x == 0) return 0;
61 *x = 0;
62 if (is_on_system(name) || is_on_vendor(name)) {
63 fs_config(name, 1, &uid, &gid, &mode, &cap);
64 }
65 ret = adb_mkdir(name, mode);
66 if((ret < 0) && (errno != EEXIST)) {
67 D("mkdir(\"%s\") -> %s\n", name, strerror(errno));
68 *x = '/';
69 return ret;
70 } else if(ret == 0) {
71 ret = chown(name, uid, gid);
72 if (ret < 0) {
73 *x = '/';
74 return ret;
75 }
76 selinux_android_restorecon(name, 0);
77 }
78 *x++ = '/';
79 }
80 return 0;
81 }
82
do_stat(int s,const char * path)83 static int do_stat(int s, const char *path)
84 {
85 syncmsg msg;
86 struct stat st;
87
88 msg.stat.id = ID_STAT;
89
90 if(lstat(path, &st)) {
91 msg.stat.mode = 0;
92 msg.stat.size = 0;
93 msg.stat.time = 0;
94 } else {
95 msg.stat.mode = htoll(st.st_mode);
96 msg.stat.size = htoll(st.st_size);
97 msg.stat.time = htoll(st.st_mtime);
98 }
99
100 return writex(s, &msg.stat, sizeof(msg.stat));
101 }
102
do_list(int s,const char * path)103 static int do_list(int s, const char *path)
104 {
105 DIR *d;
106 struct dirent *de;
107 struct stat st;
108 syncmsg msg;
109 int len;
110
111 char tmp[1024 + 256 + 1];
112 char *fname;
113
114 len = strlen(path);
115 memcpy(tmp, path, len);
116 tmp[len] = '/';
117 fname = tmp + len + 1;
118
119 msg.dent.id = ID_DENT;
120
121 d = opendir(path);
122 if(d == 0) goto done;
123
124 while((de = readdir(d))) {
125 int len = strlen(de->d_name);
126
127 /* not supposed to be possible, but
128 if it does happen, let's not buffer overrun */
129 if(len > 256) continue;
130
131 strcpy(fname, de->d_name);
132 if(lstat(tmp, &st) == 0) {
133 msg.dent.mode = htoll(st.st_mode);
134 msg.dent.size = htoll(st.st_size);
135 msg.dent.time = htoll(st.st_mtime);
136 msg.dent.namelen = htoll(len);
137
138 if(writex(s, &msg.dent, sizeof(msg.dent)) ||
139 writex(s, de->d_name, len)) {
140 closedir(d);
141 return -1;
142 }
143 }
144 }
145
146 closedir(d);
147
148 done:
149 msg.dent.id = ID_DONE;
150 msg.dent.mode = 0;
151 msg.dent.size = 0;
152 msg.dent.time = 0;
153 msg.dent.namelen = 0;
154 return writex(s, &msg.dent, sizeof(msg.dent));
155 }
156
fail_message(int s,const char * reason)157 static int fail_message(int s, const char *reason)
158 {
159 syncmsg msg;
160 int len = strlen(reason);
161
162 D("sync: failure: %s\n", reason);
163
164 msg.data.id = ID_FAIL;
165 msg.data.size = htoll(len);
166 if(writex(s, &msg.data, sizeof(msg.data)) ||
167 writex(s, reason, len)) {
168 return -1;
169 } else {
170 return 0;
171 }
172 }
173
fail_errno(int s)174 static int fail_errno(int s)
175 {
176 return fail_message(s, strerror(errno));
177 }
178
handle_send_file(int s,char * path,uid_t uid,gid_t gid,mode_t mode,char * buffer,bool do_unlink)179 static int handle_send_file(int s, char *path, uid_t uid,
180 gid_t gid, mode_t mode, char *buffer, bool do_unlink)
181 {
182 syncmsg msg;
183 unsigned int timestamp = 0;
184 int fd;
185
186 fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, mode);
187 if(fd < 0 && errno == ENOENT) {
188 if(mkdirs(path) != 0) {
189 if(fail_errno(s))
190 return -1;
191 fd = -1;
192 } else {
193 fd = adb_open_mode(path, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, mode);
194 }
195 }
196 if(fd < 0 && errno == EEXIST) {
197 fd = adb_open_mode(path, O_WRONLY | O_CLOEXEC, mode);
198 }
199 if(fd < 0) {
200 if(fail_errno(s))
201 return -1;
202 fd = -1;
203 } else {
204 if(fchown(fd, uid, gid) != 0) {
205 fail_errno(s);
206 errno = 0;
207 }
208
209 /*
210 * fchown clears the setuid bit - restore it if present.
211 * Ignore the result of calling fchmod. It's not supported
212 * by all filesystems. b/12441485
213 */
214 fchmod(fd, mode);
215 }
216
217 for(;;) {
218 unsigned int len;
219
220 if(readx(s, &msg.data, sizeof(msg.data)))
221 goto fail;
222
223 if(msg.data.id != ID_DATA) {
224 if(msg.data.id == ID_DONE) {
225 timestamp = ltohl(msg.data.size);
226 break;
227 }
228 fail_message(s, "invalid data message");
229 goto fail;
230 }
231 len = ltohl(msg.data.size);
232 if(len > SYNC_DATA_MAX) {
233 fail_message(s, "oversize data message");
234 goto fail;
235 }
236 if(readx(s, buffer, len))
237 goto fail;
238
239 if(fd < 0)
240 continue;
241 if(writex(fd, buffer, len)) {
242 int saved_errno = errno;
243 adb_close(fd);
244 if (do_unlink) adb_unlink(path);
245 fd = -1;
246 errno = saved_errno;
247 if(fail_errno(s)) return -1;
248 }
249 }
250
251 if(fd >= 0) {
252 struct utimbuf u;
253 adb_close(fd);
254 selinux_android_restorecon(path, 0);
255 u.actime = timestamp;
256 u.modtime = timestamp;
257 utime(path, &u);
258
259 msg.status.id = ID_OKAY;
260 msg.status.msglen = 0;
261 if(writex(s, &msg.status, sizeof(msg.status)))
262 return -1;
263 }
264 return 0;
265
266 fail:
267 if(fd >= 0)
268 adb_close(fd);
269 if (do_unlink) adb_unlink(path);
270 return -1;
271 }
272
273 #ifdef HAVE_SYMLINKS
handle_send_link(int s,char * path,char * buffer)274 static int handle_send_link(int s, char *path, char *buffer)
275 {
276 syncmsg msg;
277 unsigned int len;
278 int ret;
279
280 if(readx(s, &msg.data, sizeof(msg.data)))
281 return -1;
282
283 if(msg.data.id != ID_DATA) {
284 fail_message(s, "invalid data message: expected ID_DATA");
285 return -1;
286 }
287
288 len = ltohl(msg.data.size);
289 if(len > SYNC_DATA_MAX) {
290 fail_message(s, "oversize data message");
291 return -1;
292 }
293 if(readx(s, buffer, len))
294 return -1;
295
296 ret = symlink(buffer, path);
297 if(ret && errno == ENOENT) {
298 if(mkdirs(path) != 0) {
299 fail_errno(s);
300 return -1;
301 }
302 ret = symlink(buffer, path);
303 }
304 if(ret) {
305 fail_errno(s);
306 return -1;
307 }
308
309 if(readx(s, &msg.data, sizeof(msg.data)))
310 return -1;
311
312 if(msg.data.id == ID_DONE) {
313 msg.status.id = ID_OKAY;
314 msg.status.msglen = 0;
315 if(writex(s, &msg.status, sizeof(msg.status)))
316 return -1;
317 } else {
318 fail_message(s, "invalid data message: expected ID_DONE");
319 return -1;
320 }
321
322 return 0;
323 }
324 #endif /* HAVE_SYMLINKS */
325
do_send(int s,char * path,char * buffer)326 static int do_send(int s, char *path, char *buffer)
327 {
328 char *tmp;
329 unsigned int mode;
330 int is_link, ret;
331 bool do_unlink;
332
333 tmp = strrchr(path,',');
334 if(tmp) {
335 *tmp = 0;
336 errno = 0;
337 mode = strtoul(tmp + 1, NULL, 0);
338 #ifndef HAVE_SYMLINKS
339 is_link = 0;
340 #else
341 is_link = S_ISLNK((mode_t) mode);
342 #endif
343 mode &= 0777;
344 }
345 if(!tmp || errno) {
346 mode = 0644;
347 is_link = 0;
348 do_unlink = true;
349 } else {
350 struct stat st;
351 /* Don't delete files before copying if they are not "regular" */
352 do_unlink = lstat(path, &st) || S_ISREG(st.st_mode) || S_ISLNK(st.st_mode);
353 if (do_unlink) {
354 adb_unlink(path);
355 }
356 }
357
358 #ifdef HAVE_SYMLINKS
359 if(is_link)
360 ret = handle_send_link(s, path, buffer);
361 else {
362 #else
363 {
364 #endif
365 uid_t uid = -1;
366 gid_t gid = -1;
367 uint64_t cap = 0;
368
369 /* copy user permission bits to "group" and "other" permissions */
370 mode |= ((mode >> 3) & 0070);
371 mode |= ((mode >> 3) & 0007);
372
373 tmp = path;
374 if(*tmp == '/') {
375 tmp++;
376 }
377 if (is_on_system(path) || is_on_vendor(path)) {
378 fs_config(tmp, 0, &uid, &gid, &mode, &cap);
379 }
380 ret = handle_send_file(s, path, uid, gid, mode, buffer, do_unlink);
381 }
382
383 return ret;
384 }
385
386 static int do_recv(int s, const char *path, char *buffer)
387 {
388 syncmsg msg;
389 int fd, r;
390
391 fd = adb_open(path, O_RDONLY | O_CLOEXEC);
392 if(fd < 0) {
393 if(fail_errno(s)) return -1;
394 return 0;
395 }
396
397 msg.data.id = ID_DATA;
398 for(;;) {
399 r = adb_read(fd, buffer, SYNC_DATA_MAX);
400 if(r <= 0) {
401 if(r == 0) break;
402 if(errno == EINTR) continue;
403 r = fail_errno(s);
404 adb_close(fd);
405 return r;
406 }
407 msg.data.size = htoll(r);
408 if(writex(s, &msg.data, sizeof(msg.data)) ||
409 writex(s, buffer, r)) {
410 adb_close(fd);
411 return -1;
412 }
413 }
414
415 adb_close(fd);
416
417 msg.data.id = ID_DONE;
418 msg.data.size = 0;
419 if(writex(s, &msg.data, sizeof(msg.data))) {
420 return -1;
421 }
422
423 return 0;
424 }
425
426 void file_sync_service(int fd, void *cookie)
427 {
428 syncmsg msg;
429 char name[1025];
430 unsigned namelen;
431
432 char *buffer = malloc(SYNC_DATA_MAX);
433 if(buffer == 0) goto fail;
434
435 for(;;) {
436 D("sync: waiting for command\n");
437
438 if(readx(fd, &msg.req, sizeof(msg.req))) {
439 fail_message(fd, "command read failure");
440 break;
441 }
442 namelen = ltohl(msg.req.namelen);
443 if(namelen > 1024) {
444 fail_message(fd, "invalid namelen");
445 break;
446 }
447 if(readx(fd, name, namelen)) {
448 fail_message(fd, "filename read failure");
449 break;
450 }
451 name[namelen] = 0;
452
453 msg.req.namelen = 0;
454 D("sync: '%s' '%s'\n", (char*) &msg.req, name);
455
456 switch(msg.req.id) {
457 case ID_STAT:
458 if(do_stat(fd, name)) goto fail;
459 break;
460 case ID_LIST:
461 if(do_list(fd, name)) goto fail;
462 break;
463 case ID_SEND:
464 if(do_send(fd, name, buffer)) goto fail;
465 break;
466 case ID_RECV:
467 if(do_recv(fd, name, buffer)) goto fail;
468 break;
469 case ID_QUIT:
470 goto fail;
471 default:
472 fail_message(fd, "unknown command");
473 goto fail;
474 }
475 }
476
477 fail:
478 if(buffer != 0) free(buffer);
479 D("sync: done\n");
480 adb_close(fd);
481 }
482