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