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