1 /*
2  * Copyright (C) 2014 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 <ctype.h>
18 #include <errno.h>
19 #include <dirent.h>
20 #include <fcntl.h>
21 #include <inttypes.h>
22 #include <libgen.h>
23 #include <pthread.h>
24 #include <stdarg.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 <sys/wait.h>
31 #include <sys/ioctl.h>
32 #include <time.h>
33 #include <unistd.h>
34 
35 #include "applypatch/applypatch.h"
36 #include "edify/expr.h"
37 #include "mincrypt/sha.h"
38 #include "minzip/Hash.h"
39 #include "updater.h"
40 
41 #define BLOCKSIZE 4096
42 
43 // Set this to 0 to interpret 'erase' transfers to mean do a
44 // BLKDISCARD ioctl (the normal behavior).  Set to 1 to interpret
45 // erase to mean fill the region with zeroes.
46 #define DEBUG_ERASE  0
47 
48 #ifndef BLKDISCARD
49 #define BLKDISCARD _IO(0x12,119)
50 #endif
51 
52 #define STASH_DIRECTORY_BASE "/cache/recovery"
53 #define STASH_DIRECTORY_MODE 0700
54 #define STASH_FILE_MODE 0600
55 
56 char* PrintSha1(const uint8_t* digest);
57 
58 typedef struct {
59     int count;
60     int size;
61     int pos[0];
62 } RangeSet;
63 
parse_range(char * text)64 static RangeSet* parse_range(char* text) {
65     char* save;
66     int num;
67     num = strtol(strtok_r(text, ",", &save), NULL, 0);
68 
69     RangeSet* out = malloc(sizeof(RangeSet) + num * sizeof(int));
70     if (out == NULL) {
71         fprintf(stderr, "failed to allocate range of %zu bytes\n",
72                 sizeof(RangeSet) + num * sizeof(int));
73         exit(1);
74     }
75     out->count = num / 2;
76     out->size = 0;
77     int i;
78     for (i = 0; i < num; ++i) {
79         out->pos[i] = strtol(strtok_r(NULL, ",", &save), NULL, 0);
80         if (i%2) {
81             out->size += out->pos[i];
82         } else {
83             out->size -= out->pos[i];
84         }
85     }
86 
87     return out;
88 }
89 
range_overlaps(RangeSet * r1,RangeSet * r2)90 static int range_overlaps(RangeSet* r1, RangeSet* r2) {
91     int i, j, r1_0, r1_1, r2_0, r2_1;
92 
93     if (!r1 || !r2) {
94         return 0;
95     }
96 
97     for (i = 0; i < r1->count; ++i) {
98         r1_0 = r1->pos[i * 2];
99         r1_1 = r1->pos[i * 2 + 1];
100 
101         for (j = 0; j < r2->count; ++j) {
102             r2_0 = r2->pos[j * 2];
103             r2_1 = r2->pos[j * 2 + 1];
104 
105             if (!(r2_0 >= r1_1 || r1_0 >= r2_1)) {
106                 return 1;
107             }
108         }
109     }
110 
111     return 0;
112 }
113 
read_all(int fd,uint8_t * data,size_t size)114 static int read_all(int fd, uint8_t* data, size_t size) {
115     size_t so_far = 0;
116     while (so_far < size) {
117         ssize_t r = TEMP_FAILURE_RETRY(read(fd, data+so_far, size-so_far));
118         if (r == -1) {
119             fprintf(stderr, "read failed: %s\n", strerror(errno));
120             return -1;
121         }
122         so_far += r;
123     }
124     return 0;
125 }
126 
write_all(int fd,const uint8_t * data,size_t size)127 static int write_all(int fd, const uint8_t* data, size_t size) {
128     size_t written = 0;
129     while (written < size) {
130         ssize_t w = TEMP_FAILURE_RETRY(write(fd, data+written, size-written));
131         if (w == -1) {
132             fprintf(stderr, "write failed: %s\n", strerror(errno));
133             return -1;
134         }
135         written += w;
136     }
137 
138     if (fsync(fd) == -1) {
139         fprintf(stderr, "fsync failed: %s\n", strerror(errno));
140         return -1;
141     }
142 
143     return 0;
144 }
145 
check_lseek(int fd,off64_t offset,int whence)146 static bool check_lseek(int fd, off64_t offset, int whence) {
147     off64_t rc = TEMP_FAILURE_RETRY(lseek64(fd, offset, whence));
148     if (rc == -1) {
149         fprintf(stderr, "lseek64 failed: %s\n", strerror(errno));
150         return false;
151     }
152     return true;
153 }
154 
allocate(size_t size,uint8_t ** buffer,size_t * buffer_alloc)155 static void allocate(size_t size, uint8_t** buffer, size_t* buffer_alloc) {
156     // if the buffer's big enough, reuse it.
157     if (size <= *buffer_alloc) return;
158 
159     free(*buffer);
160 
161     *buffer = (uint8_t*) malloc(size);
162     if (*buffer == NULL) {
163         fprintf(stderr, "failed to allocate %zu bytes\n", size);
164         exit(1);
165     }
166     *buffer_alloc = size;
167 }
168 
169 typedef struct {
170     int fd;
171     RangeSet* tgt;
172     int p_block;
173     size_t p_remain;
174 } RangeSinkState;
175 
RangeSinkWrite(const uint8_t * data,ssize_t size,void * token)176 static ssize_t RangeSinkWrite(const uint8_t* data, ssize_t size, void* token) {
177     RangeSinkState* rss = (RangeSinkState*) token;
178 
179     if (rss->p_remain <= 0) {
180         fprintf(stderr, "range sink write overrun");
181         return 0;
182     }
183 
184     ssize_t written = 0;
185     while (size > 0) {
186         size_t write_now = size;
187 
188         if (rss->p_remain < write_now) {
189             write_now = rss->p_remain;
190         }
191 
192         if (write_all(rss->fd, data, write_now) == -1) {
193             break;
194         }
195 
196         data += write_now;
197         size -= write_now;
198 
199         rss->p_remain -= write_now;
200         written += write_now;
201 
202         if (rss->p_remain == 0) {
203             // move to the next block
204             ++rss->p_block;
205             if (rss->p_block < rss->tgt->count) {
206                 rss->p_remain = (rss->tgt->pos[rss->p_block * 2 + 1] -
207                                  rss->tgt->pos[rss->p_block * 2]) * BLOCKSIZE;
208 
209                 if (!check_lseek(rss->fd, (off64_t)rss->tgt->pos[rss->p_block*2] * BLOCKSIZE,
210                                  SEEK_SET)) {
211                     break;
212                 }
213             } else {
214                 // we can't write any more; return how many bytes have
215                 // been written so far.
216                 break;
217             }
218         }
219     }
220 
221     return written;
222 }
223 
224 // All of the data for all the 'new' transfers is contained in one
225 // file in the update package, concatenated together in the order in
226 // which transfers.list will need it.  We want to stream it out of the
227 // archive (it's compressed) without writing it to a temp file, but we
228 // can't write each section until it's that transfer's turn to go.
229 //
230 // To achieve this, we expand the new data from the archive in a
231 // background thread, and block that threads 'receive uncompressed
232 // data' function until the main thread has reached a point where we
233 // want some new data to be written.  We signal the background thread
234 // with the destination for the data and block the main thread,
235 // waiting for the background thread to complete writing that section.
236 // Then it signals the main thread to wake up and goes back to
237 // blocking waiting for a transfer.
238 //
239 // NewThreadInfo is the struct used to pass information back and forth
240 // between the two threads.  When the main thread wants some data
241 // written, it sets rss to the destination location and signals the
242 // condition.  When the background thread is done writing, it clears
243 // rss and signals the condition again.
244 
245 typedef struct {
246     ZipArchive* za;
247     const ZipEntry* entry;
248 
249     RangeSinkState* rss;
250 
251     pthread_mutex_t mu;
252     pthread_cond_t cv;
253 } NewThreadInfo;
254 
receive_new_data(const unsigned char * data,int size,void * cookie)255 static bool receive_new_data(const unsigned char* data, int size, void* cookie) {
256     NewThreadInfo* nti = (NewThreadInfo*) cookie;
257 
258     while (size > 0) {
259         // Wait for nti->rss to be non-NULL, indicating some of this
260         // data is wanted.
261         pthread_mutex_lock(&nti->mu);
262         while (nti->rss == NULL) {
263             pthread_cond_wait(&nti->cv, &nti->mu);
264         }
265         pthread_mutex_unlock(&nti->mu);
266 
267         // At this point nti->rss is set, and we own it.  The main
268         // thread is waiting for it to disappear from nti.
269         ssize_t written = RangeSinkWrite(data, size, nti->rss);
270         data += written;
271         size -= written;
272 
273         if (nti->rss->p_block == nti->rss->tgt->count) {
274             // we have written all the bytes desired by this rss.
275 
276             pthread_mutex_lock(&nti->mu);
277             nti->rss = NULL;
278             pthread_cond_broadcast(&nti->cv);
279             pthread_mutex_unlock(&nti->mu);
280         }
281     }
282 
283     return true;
284 }
285 
unzip_new_data(void * cookie)286 static void* unzip_new_data(void* cookie) {
287     NewThreadInfo* nti = (NewThreadInfo*) cookie;
288     mzProcessZipEntryContents(nti->za, nti->entry, receive_new_data, nti);
289     return NULL;
290 }
291 
ReadBlocks(RangeSet * src,uint8_t * buffer,int fd)292 static int ReadBlocks(RangeSet* src, uint8_t* buffer, int fd) {
293     int i;
294     size_t p = 0;
295     size_t size;
296 
297     if (!src || !buffer) {
298         return -1;
299     }
300 
301     for (i = 0; i < src->count; ++i) {
302         if (!check_lseek(fd, (off64_t) src->pos[i * 2] * BLOCKSIZE, SEEK_SET)) {
303             return -1;
304         }
305 
306         size = (src->pos[i * 2 + 1] - src->pos[i * 2]) * BLOCKSIZE;
307 
308         if (read_all(fd, buffer + p, size) == -1) {
309             return -1;
310         }
311 
312         p += size;
313     }
314 
315     return 0;
316 }
317 
WriteBlocks(RangeSet * tgt,uint8_t * buffer,int fd)318 static int WriteBlocks(RangeSet* tgt, uint8_t* buffer, int fd) {
319     int i;
320     size_t p = 0;
321     size_t size;
322 
323     if (!tgt || !buffer) {
324         return -1;
325     }
326 
327     for (i = 0; i < tgt->count; ++i) {
328         if (!check_lseek(fd, (off64_t) tgt->pos[i * 2] * BLOCKSIZE, SEEK_SET)) {
329             return -1;
330         }
331 
332         size = (tgt->pos[i * 2 + 1] - tgt->pos[i * 2]) * BLOCKSIZE;
333 
334         if (write_all(fd, buffer + p, size) == -1) {
335             return -1;
336         }
337 
338         p += size;
339     }
340 
341     return 0;
342 }
343 
344 // Do a source/target load for move/bsdiff/imgdiff in version 1.
345 // 'wordsave' is the save_ptr of a strtok_r()-in-progress.  We expect
346 // to parse the remainder of the string as:
347 //
348 //    <src_range> <tgt_range>
349 //
350 // The source range is loaded into the provided buffer, reallocating
351 // it to make it larger if necessary.  The target ranges are returned
352 // in *tgt, if tgt is non-NULL.
353 
LoadSrcTgtVersion1(char ** wordsave,RangeSet ** tgt,int * src_blocks,uint8_t ** buffer,size_t * buffer_alloc,int fd)354 static int LoadSrcTgtVersion1(char** wordsave, RangeSet** tgt, int* src_blocks,
355                                uint8_t** buffer, size_t* buffer_alloc, int fd) {
356     char* word;
357     int rc;
358 
359     word = strtok_r(NULL, " ", wordsave);
360     RangeSet* src = parse_range(word);
361 
362     if (tgt != NULL) {
363         word = strtok_r(NULL, " ", wordsave);
364         *tgt = parse_range(word);
365     }
366 
367     allocate(src->size * BLOCKSIZE, buffer, buffer_alloc);
368     rc = ReadBlocks(src, *buffer, fd);
369     *src_blocks = src->size;
370 
371     free(src);
372     return rc;
373 }
374 
VerifyBlocks(const char * expected,const uint8_t * buffer,size_t blocks,int printerror)375 static int VerifyBlocks(const char *expected, const uint8_t *buffer,
376                         size_t blocks, int printerror) {
377     char* hexdigest = NULL;
378     int rc = -1;
379     uint8_t digest[SHA_DIGEST_SIZE];
380 
381     if (!expected || !buffer) {
382         return rc;
383     }
384 
385     SHA_hash(buffer, blocks * BLOCKSIZE, digest);
386     hexdigest = PrintSha1(digest);
387 
388     if (hexdigest != NULL) {
389         rc = strcmp(expected, hexdigest);
390 
391         if (rc != 0 && printerror) {
392             fprintf(stderr, "failed to verify blocks (expected %s, read %s)\n",
393                 expected, hexdigest);
394         }
395 
396         free(hexdigest);
397     }
398 
399     return rc;
400 }
401 
GetStashFileName(const char * base,const char * id,const char * postfix)402 static char* GetStashFileName(const char* base, const char* id, const char* postfix) {
403     char* fn;
404     int len;
405     int res;
406 
407     if (base == NULL) {
408         return NULL;
409     }
410 
411     if (id == NULL) {
412         id = "";
413     }
414 
415     if (postfix == NULL) {
416         postfix = "";
417     }
418 
419     len = strlen(STASH_DIRECTORY_BASE) + 1 + strlen(base) + 1 + strlen(id) + strlen(postfix) + 1;
420     fn = malloc(len);
421 
422     if (fn == NULL) {
423         fprintf(stderr, "failed to malloc %d bytes for fn\n", len);
424         return NULL;
425     }
426 
427     res = snprintf(fn, len, STASH_DIRECTORY_BASE "/%s/%s%s", base, id, postfix);
428 
429     if (res < 0 || res >= len) {
430         fprintf(stderr, "failed to format file name (return value %d)\n", res);
431         free(fn);
432         return NULL;
433     }
434 
435     return fn;
436 }
437 
438 typedef void (*StashCallback)(const char*, void*);
439 
440 // Does a best effort enumeration of stash files. Ignores possible non-file
441 // items in the stash directory and continues despite of errors. Calls the
442 // 'callback' function for each file and passes 'data' to the function as a
443 // parameter.
444 
EnumerateStash(const char * dirname,StashCallback callback,void * data)445 static void EnumerateStash(const char* dirname, StashCallback callback, void* data) {
446     char* fn;
447     DIR* directory;
448     int len;
449     int res;
450     struct dirent* item;
451 
452     if (dirname == NULL || callback == NULL) {
453         return;
454     }
455 
456     directory = opendir(dirname);
457 
458     if (directory == NULL) {
459         if (errno != ENOENT) {
460             fprintf(stderr, "opendir \"%s\" failed: %s\n", dirname, strerror(errno));
461         }
462         return;
463     }
464 
465     while ((item = readdir(directory)) != NULL) {
466         if (item->d_type != DT_REG) {
467             continue;
468         }
469 
470         len = strlen(dirname) + 1 + strlen(item->d_name) + 1;
471         fn = malloc(len);
472 
473         if (fn == NULL) {
474             fprintf(stderr, "failed to malloc %d bytes for fn\n", len);
475             continue;
476         }
477 
478         res = snprintf(fn, len, "%s/%s", dirname, item->d_name);
479 
480         if (res < 0 || res >= len) {
481             fprintf(stderr, "failed to format file name (return value %d)\n", res);
482             free(fn);
483             continue;
484         }
485 
486         callback(fn, data);
487         free(fn);
488     }
489 
490     if (closedir(directory) == -1) {
491         fprintf(stderr, "closedir \"%s\" failed: %s\n", dirname, strerror(errno));
492     }
493 }
494 
UpdateFileSize(const char * fn,void * data)495 static void UpdateFileSize(const char* fn, void* data) {
496     int* size = (int*) data;
497     struct stat st;
498 
499     if (!fn || !data) {
500         return;
501     }
502 
503     if (stat(fn, &st) == -1) {
504         fprintf(stderr, "stat \"%s\" failed: %s\n", fn, strerror(errno));
505         return;
506     }
507 
508     *size += st.st_size;
509 }
510 
511 // Deletes the stash directory and all files in it. Assumes that it only
512 // contains files. There is nothing we can do about unlikely, but possible
513 // errors, so they are merely logged.
514 
DeleteFile(const char * fn,void * data)515 static void DeleteFile(const char* fn, void* data) {
516     if (fn) {
517         fprintf(stderr, "deleting %s\n", fn);
518 
519         if (unlink(fn) == -1 && errno != ENOENT) {
520             fprintf(stderr, "unlink \"%s\" failed: %s\n", fn, strerror(errno));
521         }
522     }
523 }
524 
DeletePartial(const char * fn,void * data)525 static void DeletePartial(const char* fn, void* data) {
526     if (fn && strstr(fn, ".partial") != NULL) {
527         DeleteFile(fn, data);
528     }
529 }
530 
DeleteStash(const char * base)531 static void DeleteStash(const char* base) {
532     char* dirname;
533 
534     if (base == NULL) {
535         return;
536     }
537 
538     dirname = GetStashFileName(base, NULL, NULL);
539 
540     if (dirname == NULL) {
541         return;
542     }
543 
544     fprintf(stderr, "deleting stash %s\n", base);
545     EnumerateStash(dirname, DeleteFile, NULL);
546 
547     if (rmdir(dirname) == -1) {
548         if (errno != ENOENT && errno != ENOTDIR) {
549             fprintf(stderr, "rmdir \"%s\" failed: %s\n", dirname, strerror(errno));
550         }
551     }
552 
553     free(dirname);
554 }
555 
LoadStash(const char * base,const char * id,int verify,int * blocks,uint8_t ** buffer,size_t * buffer_alloc,int printnoent)556 static int LoadStash(const char* base, const char* id, int verify, int* blocks, uint8_t** buffer,
557         size_t* buffer_alloc, int printnoent) {
558     char *fn = NULL;
559     int blockcount = 0;
560     int fd = -1;
561     int rc = -1;
562     int res;
563     struct stat st;
564 
565     if (!base || !id || !buffer || !buffer_alloc) {
566         goto lsout;
567     }
568 
569     if (!blocks) {
570         blocks = &blockcount;
571     }
572 
573     fn = GetStashFileName(base, id, NULL);
574 
575     if (fn == NULL) {
576         goto lsout;
577     }
578 
579     res = stat(fn, &st);
580 
581     if (res == -1) {
582         if (errno != ENOENT || printnoent) {
583             fprintf(stderr, "stat \"%s\" failed: %s\n", fn, strerror(errno));
584         }
585         goto lsout;
586     }
587 
588     fprintf(stderr, " loading %s\n", fn);
589 
590     if ((st.st_size % BLOCKSIZE) != 0) {
591         fprintf(stderr, "%s size %zd not multiple of block size %d", fn, st.st_size, BLOCKSIZE);
592         goto lsout;
593     }
594 
595     fd = TEMP_FAILURE_RETRY(open(fn, O_RDONLY));
596 
597     if (fd == -1) {
598         fprintf(stderr, "open \"%s\" failed: %s\n", fn, strerror(errno));
599         goto lsout;
600     }
601 
602     allocate(st.st_size, buffer, buffer_alloc);
603 
604     if (read_all(fd, *buffer, st.st_size) == -1) {
605         goto lsout;
606     }
607 
608     *blocks = st.st_size / BLOCKSIZE;
609 
610     if (verify && VerifyBlocks(id, *buffer, *blocks, 1) != 0) {
611         fprintf(stderr, "unexpected contents in %s\n", fn);
612         DeleteFile(fn, NULL);
613         goto lsout;
614     }
615 
616     rc = 0;
617 
618 lsout:
619     if (fd != -1) {
620         close(fd);
621     }
622 
623     if (fn) {
624         free(fn);
625     }
626 
627     return rc;
628 }
629 
WriteStash(const char * base,const char * id,int blocks,uint8_t * buffer,int checkspace,int * exists)630 static int WriteStash(const char* base, const char* id, int blocks, uint8_t* buffer,
631         int checkspace, int *exists) {
632     char *fn = NULL;
633     char *cn = NULL;
634     int fd = -1;
635     int rc = -1;
636     int dfd = -1;
637     int res;
638     struct stat st;
639 
640     if (base == NULL || buffer == NULL) {
641         goto wsout;
642     }
643 
644     if (checkspace && CacheSizeCheck(blocks * BLOCKSIZE) != 0) {
645         fprintf(stderr, "not enough space to write stash\n");
646         goto wsout;
647     }
648 
649     fn = GetStashFileName(base, id, ".partial");
650     cn = GetStashFileName(base, id, NULL);
651 
652     if (fn == NULL || cn == NULL) {
653         goto wsout;
654     }
655 
656     if (exists) {
657         res = stat(cn, &st);
658 
659         if (res == 0) {
660             // The file already exists and since the name is the hash of the contents,
661             // it's safe to assume the contents are identical (accidental hash collisions
662             // are unlikely)
663             fprintf(stderr, " skipping %d existing blocks in %s\n", blocks, cn);
664             *exists = 1;
665             rc = 0;
666             goto wsout;
667         }
668 
669         *exists = 0;
670     }
671 
672     fprintf(stderr, " writing %d blocks to %s\n", blocks, cn);
673 
674     fd = TEMP_FAILURE_RETRY(open(fn, O_WRONLY | O_CREAT | O_TRUNC | O_SYNC, STASH_FILE_MODE));
675 
676     if (fd == -1) {
677         fprintf(stderr, "failed to create \"%s\": %s\n", fn, strerror(errno));
678         goto wsout;
679     }
680 
681     if (write_all(fd, buffer, blocks * BLOCKSIZE) == -1) {
682         goto wsout;
683     }
684 
685     if (fsync(fd) == -1) {
686         fprintf(stderr, "fsync \"%s\" failed: %s\n", fn, strerror(errno));
687         goto wsout;
688     }
689 
690     if (rename(fn, cn) == -1) {
691         fprintf(stderr, "rename(\"%s\", \"%s\") failed: %s\n", fn, cn, strerror(errno));
692         goto wsout;
693     }
694 
695     const char* dname;
696     dname = dirname(cn);
697     dfd = TEMP_FAILURE_RETRY(open(dname, O_RDONLY | O_DIRECTORY));
698 
699     if (dfd == -1) {
700         fprintf(stderr, "failed to open \"%s\" failed: %s\n", dname, strerror(errno));
701         goto wsout;
702     }
703 
704     if (fsync(dfd) == -1) {
705         fprintf(stderr, "fsync \"%s\" failed: %s\n", dname, strerror(errno));
706         goto wsout;
707     }
708 
709     rc = 0;
710 
711 wsout:
712     if (fd != -1) {
713         close(fd);
714     }
715 
716     if (dfd != -1) {
717         close(dfd);
718     }
719 
720     if (fn) {
721         free(fn);
722     }
723 
724     if (cn) {
725         free(cn);
726     }
727 
728     return rc;
729 }
730 
731 // Creates a directory for storing stash files and checks if the /cache partition
732 // hash enough space for the expected amount of blocks we need to store. Returns
733 // >0 if we created the directory, zero if it existed already, and <0 of failure.
734 
CreateStash(State * state,int maxblocks,const char * blockdev,char ** base)735 static int CreateStash(State* state, int maxblocks, const char* blockdev, char** base) {
736     char* dirname = NULL;
737     const uint8_t* digest;
738     int rc = -1;
739     int res;
740     int size = 0;
741     SHA_CTX ctx;
742     struct stat st;
743 
744     if (blockdev == NULL || base == NULL) {
745         goto csout;
746     }
747 
748     // Stash directory should be different for each partition to avoid conflicts
749     // when updating multiple partitions at the same time, so we use the hash of
750     // the block device name as the base directory
751     SHA_init(&ctx);
752     SHA_update(&ctx, blockdev, strlen(blockdev));
753     digest = SHA_final(&ctx);
754     *base = PrintSha1(digest);
755 
756     if (*base == NULL) {
757         goto csout;
758     }
759 
760     dirname = GetStashFileName(*base, NULL, NULL);
761 
762     if (dirname == NULL) {
763         goto csout;
764     }
765 
766     res = stat(dirname, &st);
767 
768     if (res == -1 && errno != ENOENT) {
769         ErrorAbort(state, "stat \"%s\" failed: %s\n", dirname, strerror(errno));
770         goto csout;
771     } else if (res != 0) {
772         fprintf(stderr, "creating stash %s\n", dirname);
773         res = mkdir(dirname, STASH_DIRECTORY_MODE);
774 
775         if (res != 0) {
776             ErrorAbort(state, "mkdir \"%s\" failed: %s\n", dirname, strerror(errno));
777             goto csout;
778         }
779 
780         if (CacheSizeCheck(maxblocks * BLOCKSIZE) != 0) {
781             ErrorAbort(state, "not enough space for stash\n");
782             goto csout;
783         }
784 
785         rc = 1; // Created directory
786         goto csout;
787     }
788 
789     fprintf(stderr, "using existing stash %s\n", dirname);
790 
791     // If the directory already exists, calculate the space already allocated to
792     // stash files and check if there's enough for all required blocks. Delete any
793     // partially completed stash files first.
794 
795     EnumerateStash(dirname, DeletePartial, NULL);
796     EnumerateStash(dirname, UpdateFileSize, &size);
797 
798     size = (maxblocks * BLOCKSIZE) - size;
799 
800     if (size > 0 && CacheSizeCheck(size) != 0) {
801         ErrorAbort(state, "not enough space for stash (%d more needed)\n", size);
802         goto csout;
803     }
804 
805     rc = 0; // Using existing directory
806 
807 csout:
808     if (dirname) {
809         free(dirname);
810     }
811 
812     return rc;
813 }
814 
SaveStash(const char * base,char ** wordsave,uint8_t ** buffer,size_t * buffer_alloc,int fd,int usehash,int * isunresumable)815 static int SaveStash(const char* base, char** wordsave, uint8_t** buffer, size_t* buffer_alloc,
816                       int fd, int usehash, int* isunresumable) {
817     char *id = NULL;
818     int res = -1;
819     int blocks = 0;
820 
821     if (!wordsave || !buffer || !buffer_alloc || !isunresumable) {
822         return -1;
823     }
824 
825     id = strtok_r(NULL, " ", wordsave);
826 
827     if (id == NULL) {
828         fprintf(stderr, "missing id field in stash command\n");
829         return -1;
830     }
831 
832     if (usehash && LoadStash(base, id, 1, &blocks, buffer, buffer_alloc, 0) == 0) {
833         // Stash file already exists and has expected contents. Do not
834         // read from source again, as the source may have been already
835         // overwritten during a previous attempt.
836         return 0;
837     }
838 
839     if (LoadSrcTgtVersion1(wordsave, NULL, &blocks, buffer, buffer_alloc, fd) == -1) {
840         return -1;
841     }
842 
843     if (usehash && VerifyBlocks(id, *buffer, blocks, 1) != 0) {
844         // Source blocks have unexpected contents. If we actually need this
845         // data later, this is an unrecoverable error. However, the command
846         // that uses the data may have already completed previously, so the
847         // possible failure will occur during source block verification.
848         fprintf(stderr, "failed to load source blocks for stash %s\n", id);
849         return 0;
850     }
851 
852     fprintf(stderr, "stashing %d blocks to %s\n", blocks, id);
853     return WriteStash(base, id, blocks, *buffer, 0, NULL);
854 }
855 
FreeStash(const char * base,const char * id)856 static int FreeStash(const char* base, const char* id) {
857     char *fn = NULL;
858 
859     if (base == NULL || id == NULL) {
860         return -1;
861     }
862 
863     fn = GetStashFileName(base, id, NULL);
864 
865     if (fn == NULL) {
866         return -1;
867     }
868 
869     DeleteFile(fn, NULL);
870     free(fn);
871 
872     return 0;
873 }
874 
MoveRange(uint8_t * dest,RangeSet * locs,const uint8_t * source)875 static void MoveRange(uint8_t* dest, RangeSet* locs, const uint8_t* source) {
876     // source contains packed data, which we want to move to the
877     // locations given in *locs in the dest buffer.  source and dest
878     // may be the same buffer.
879 
880     int start = locs->size;
881     int i;
882     for (i = locs->count-1; i >= 0; --i) {
883         int blocks = locs->pos[i*2+1] - locs->pos[i*2];
884         start -= blocks;
885         memmove(dest + (locs->pos[i*2] * BLOCKSIZE), source + (start * BLOCKSIZE),
886                 blocks * BLOCKSIZE);
887     }
888 }
889 
890 // Do a source/target load for move/bsdiff/imgdiff in version 2.
891 // 'wordsave' is the save_ptr of a strtok_r()-in-progress.  We expect
892 // to parse the remainder of the string as one of:
893 //
894 //    <tgt_range> <src_block_count> <src_range>
895 //        (loads data from source image only)
896 //
897 //    <tgt_range> <src_block_count> - <[stash_id:stash_range] ...>
898 //        (loads data from stashes only)
899 //
900 //    <tgt_range> <src_block_count> <src_range> <src_loc> <[stash_id:stash_range] ...>
901 //        (loads data from both source image and stashes)
902 //
903 // On return, buffer is filled with the loaded source data (rearranged
904 // and combined with stashed data as necessary).  buffer may be
905 // reallocated if needed to accommodate the source data.  *tgt is the
906 // target RangeSet.  Any stashes required are loaded using LoadStash.
907 
LoadSrcTgtVersion2(char ** wordsave,RangeSet ** tgt,int * src_blocks,uint8_t ** buffer,size_t * buffer_alloc,int fd,const char * stashbase,int * overlap)908 static int LoadSrcTgtVersion2(char** wordsave, RangeSet** tgt, int* src_blocks,
909                                uint8_t** buffer, size_t* buffer_alloc, int fd,
910                                const char* stashbase, int* overlap) {
911     char* word;
912     char* colonsave;
913     char* colon;
914     int id;
915     int res;
916     RangeSet* locs;
917     size_t stashalloc = 0;
918     uint8_t* stash = NULL;
919 
920     if (tgt != NULL) {
921         word = strtok_r(NULL, " ", wordsave);
922         *tgt = parse_range(word);
923     }
924 
925     word = strtok_r(NULL, " ", wordsave);
926     *src_blocks = strtol(word, NULL, 0);
927 
928     allocate(*src_blocks * BLOCKSIZE, buffer, buffer_alloc);
929 
930     word = strtok_r(NULL, " ", wordsave);
931     if (word[0] == '-' && word[1] == '\0') {
932         // no source ranges, only stashes
933     } else {
934         RangeSet* src = parse_range(word);
935         res = ReadBlocks(src, *buffer, fd);
936 
937         if (overlap && tgt) {
938             *overlap = range_overlaps(src, *tgt);
939         }
940 
941         free(src);
942 
943         if (res == -1) {
944             return -1;
945         }
946 
947         word = strtok_r(NULL, " ", wordsave);
948         if (word == NULL) {
949             // no stashes, only source range
950             return 0;
951         }
952 
953         locs = parse_range(word);
954         MoveRange(*buffer, locs, *buffer);
955         free(locs);
956     }
957 
958     while ((word = strtok_r(NULL, " ", wordsave)) != NULL) {
959         // Each word is a an index into the stash table, a colon, and
960         // then a rangeset describing where in the source block that
961         // stashed data should go.
962         colonsave = NULL;
963         colon = strtok_r(word, ":", &colonsave);
964 
965         res = LoadStash(stashbase, colon, 0, NULL, &stash, &stashalloc, 1);
966 
967         if (res == -1) {
968             // These source blocks will fail verification if used later, but we
969             // will let the caller decide if this is a fatal failure
970             fprintf(stderr, "failed to load stash %s\n", colon);
971             continue;
972         }
973 
974         colon = strtok_r(NULL, ":", &colonsave);
975         locs = parse_range(colon);
976 
977         MoveRange(*buffer, locs, stash);
978         free(locs);
979     }
980 
981     if (stash) {
982         free(stash);
983     }
984 
985     return 0;
986 }
987 
988 // Parameters for transfer list command functions
989 typedef struct {
990     char* cmdname;
991     char* cpos;
992     char* freestash;
993     char* stashbase;
994     int canwrite;
995     int createdstash;
996     int fd;
997     int foundwrites;
998     int isunresumable;
999     int version;
1000     int written;
1001     NewThreadInfo nti;
1002     pthread_t thread;
1003     size_t bufsize;
1004     uint8_t* buffer;
1005     uint8_t* patch_start;
1006 } CommandParameters;
1007 
1008 // Do a source/target load for move/bsdiff/imgdiff in version 3.
1009 //
1010 // Parameters are the same as for LoadSrcTgtVersion2, except for 'onehash', which
1011 // tells the function whether to expect separate source and targe block hashes, or
1012 // if they are both the same and only one hash should be expected, and
1013 // 'isunresumable', which receives a non-zero value if block verification fails in
1014 // a way that the update cannot be resumed anymore.
1015 //
1016 // If the function is unable to load the necessary blocks or their contents don't
1017 // match the hashes, the return value is -1 and the command should be aborted.
1018 //
1019 // If the return value is 1, the command has already been completed according to
1020 // the contents of the target blocks, and should not be performed again.
1021 //
1022 // If the return value is 0, source blocks have expected content and the command
1023 // can be performed.
1024 
LoadSrcTgtVersion3(CommandParameters * params,RangeSet ** tgt,int * src_blocks,int onehash,int * overlap)1025 static int LoadSrcTgtVersion3(CommandParameters* params, RangeSet** tgt, int* src_blocks,
1026                               int onehash, int* overlap) {
1027     char* srchash = NULL;
1028     char* tgthash = NULL;
1029     int stash_exists = 0;
1030     int overlap_blocks = 0;
1031     int rc = -1;
1032     uint8_t* tgtbuffer = NULL;
1033 
1034     if (!params|| !tgt || !src_blocks || !overlap) {
1035         goto v3out;
1036     }
1037 
1038     srchash = strtok_r(NULL, " ", &params->cpos);
1039 
1040     if (srchash == NULL) {
1041         fprintf(stderr, "missing source hash\n");
1042         goto v3out;
1043     }
1044 
1045     if (onehash) {
1046         tgthash = srchash;
1047     } else {
1048         tgthash = strtok_r(NULL, " ", &params->cpos);
1049 
1050         if (tgthash == NULL) {
1051             fprintf(stderr, "missing target hash\n");
1052             goto v3out;
1053         }
1054     }
1055 
1056     if (LoadSrcTgtVersion2(&params->cpos, tgt, src_blocks, &params->buffer, &params->bufsize,
1057             params->fd, params->stashbase, overlap) == -1) {
1058         goto v3out;
1059     }
1060 
1061     tgtbuffer = (uint8_t*) malloc((*tgt)->size * BLOCKSIZE);
1062 
1063     if (tgtbuffer == NULL) {
1064         fprintf(stderr, "failed to allocate %d bytes\n", (*tgt)->size * BLOCKSIZE);
1065         goto v3out;
1066     }
1067 
1068     if (ReadBlocks(*tgt, tgtbuffer, params->fd) == -1) {
1069         goto v3out;
1070     }
1071 
1072     if (VerifyBlocks(tgthash, tgtbuffer, (*tgt)->size, 0) == 0) {
1073         // Target blocks already have expected content, command should be skipped
1074         rc = 1;
1075         goto v3out;
1076     }
1077 
1078     if (VerifyBlocks(srchash, params->buffer, *src_blocks, 1) == 0) {
1079         // If source and target blocks overlap, stash the source blocks so we can
1080         // resume from possible write errors
1081         if (*overlap) {
1082             fprintf(stderr, "stashing %d overlapping blocks to %s\n", *src_blocks,
1083                 srchash);
1084 
1085             if (WriteStash(params->stashbase, srchash, *src_blocks, params->buffer, 1,
1086                     &stash_exists) != 0) {
1087                 fprintf(stderr, "failed to stash overlapping source blocks\n");
1088                 goto v3out;
1089             }
1090 
1091             // Can be deleted when the write has completed
1092             if (!stash_exists) {
1093                 params->freestash = srchash;
1094             }
1095         }
1096 
1097         // Source blocks have expected content, command can proceed
1098         rc = 0;
1099         goto v3out;
1100     }
1101 
1102     if (*overlap && LoadStash(params->stashbase, srchash, 1, NULL, &params->buffer,
1103                         &params->bufsize, 1) == 0) {
1104         // Overlapping source blocks were previously stashed, command can proceed.
1105         // We are recovering from an interrupted command, so we don't know if the
1106         // stash can safely be deleted after this command.
1107         rc = 0;
1108         goto v3out;
1109     }
1110 
1111     // Valid source data not available, update cannot be resumed
1112     fprintf(stderr, "partition has unexpected contents\n");
1113     params->isunresumable = 1;
1114 
1115 v3out:
1116     if (tgtbuffer) {
1117         free(tgtbuffer);
1118     }
1119 
1120     return rc;
1121 }
1122 
PerformCommandMove(CommandParameters * params)1123 static int PerformCommandMove(CommandParameters* params) {
1124     int blocks = 0;
1125     int overlap = 0;
1126     int rc = -1;
1127     int status = 0;
1128     RangeSet* tgt = NULL;
1129 
1130     if (!params) {
1131         goto pcmout;
1132     }
1133 
1134     if (params->version == 1) {
1135         status = LoadSrcTgtVersion1(&params->cpos, &tgt, &blocks, &params->buffer,
1136                     &params->bufsize, params->fd);
1137     } else if (params->version == 2) {
1138         status = LoadSrcTgtVersion2(&params->cpos, &tgt, &blocks, &params->buffer,
1139                     &params->bufsize, params->fd, params->stashbase, NULL);
1140     } else if (params->version >= 3) {
1141         status = LoadSrcTgtVersion3(params, &tgt, &blocks, 1, &overlap);
1142     }
1143 
1144     if (status == -1) {
1145         fprintf(stderr, "failed to read blocks for move\n");
1146         goto pcmout;
1147     }
1148 
1149     if (status == 0) {
1150         params->foundwrites = 1;
1151     } else if (params->foundwrites) {
1152         fprintf(stderr, "warning: commands executed out of order [%s]\n", params->cmdname);
1153     }
1154 
1155     if (params->canwrite) {
1156         if (status == 0) {
1157             fprintf(stderr, "  moving %d blocks\n", blocks);
1158 
1159             if (WriteBlocks(tgt, params->buffer, params->fd) == -1) {
1160                 goto pcmout;
1161             }
1162         } else {
1163             fprintf(stderr, "skipping %d already moved blocks\n", blocks);
1164         }
1165 
1166     }
1167 
1168     if (params->freestash) {
1169         FreeStash(params->stashbase, params->freestash);
1170         params->freestash = NULL;
1171     }
1172 
1173     params->written += tgt->size;
1174     rc = 0;
1175 
1176 pcmout:
1177     if (tgt) {
1178         free(tgt);
1179     }
1180 
1181     return rc;
1182 }
1183 
PerformCommandStash(CommandParameters * params)1184 static int PerformCommandStash(CommandParameters* params) {
1185     if (!params) {
1186         return -1;
1187     }
1188 
1189     return SaveStash(params->stashbase, &params->cpos, &params->buffer, &params->bufsize,
1190                 params->fd, (params->version >= 3), &params->isunresumable);
1191 }
1192 
PerformCommandFree(CommandParameters * params)1193 static int PerformCommandFree(CommandParameters* params) {
1194     if (!params) {
1195         return -1;
1196     }
1197 
1198     if (params->createdstash || params->canwrite) {
1199         return FreeStash(params->stashbase, params->cpos);
1200     }
1201 
1202     return 0;
1203 }
1204 
PerformCommandZero(CommandParameters * params)1205 static int PerformCommandZero(CommandParameters* params) {
1206     char* range = NULL;
1207     int i;
1208     int j;
1209     int rc = -1;
1210     RangeSet* tgt = NULL;
1211 
1212     if (!params) {
1213         goto pczout;
1214     }
1215 
1216     range = strtok_r(NULL, " ", &params->cpos);
1217 
1218     if (range == NULL) {
1219         fprintf(stderr, "missing target blocks for zero\n");
1220         goto pczout;
1221     }
1222 
1223     tgt = parse_range(range);
1224 
1225     fprintf(stderr, "  zeroing %d blocks\n", tgt->size);
1226 
1227     allocate(BLOCKSIZE, &params->buffer, &params->bufsize);
1228     memset(params->buffer, 0, BLOCKSIZE);
1229 
1230     if (params->canwrite) {
1231         for (i = 0; i < tgt->count; ++i) {
1232             if (!check_lseek(params->fd, (off64_t) tgt->pos[i * 2] * BLOCKSIZE, SEEK_SET)) {
1233                 goto pczout;
1234             }
1235 
1236             for (j = tgt->pos[i * 2]; j < tgt->pos[i * 2 + 1]; ++j) {
1237                 if (write_all(params->fd, params->buffer, BLOCKSIZE) == -1) {
1238                     goto pczout;
1239                 }
1240             }
1241         }
1242     }
1243 
1244     if (params->cmdname[0] == 'z') {
1245         // Update only for the zero command, as the erase command will call
1246         // this if DEBUG_ERASE is defined.
1247         params->written += tgt->size;
1248     }
1249 
1250     rc = 0;
1251 
1252 pczout:
1253     if (tgt) {
1254         free(tgt);
1255     }
1256 
1257     return rc;
1258 }
1259 
PerformCommandNew(CommandParameters * params)1260 static int PerformCommandNew(CommandParameters* params) {
1261     char* range = NULL;
1262     int rc = -1;
1263     RangeSet* tgt = NULL;
1264     RangeSinkState rss;
1265 
1266     if (!params) {
1267         goto pcnout;
1268     }
1269 
1270     range = strtok_r(NULL, " ", &params->cpos);
1271 
1272     if (range == NULL) {
1273         goto pcnout;
1274     }
1275 
1276     tgt = parse_range(range);
1277 
1278     if (params->canwrite) {
1279         fprintf(stderr, " writing %d blocks of new data\n", tgt->size);
1280 
1281         rss.fd = params->fd;
1282         rss.tgt = tgt;
1283         rss.p_block = 0;
1284         rss.p_remain = (tgt->pos[1] - tgt->pos[0]) * BLOCKSIZE;
1285 
1286         if (!check_lseek(params->fd, (off64_t) tgt->pos[0] * BLOCKSIZE, SEEK_SET)) {
1287             goto pcnout;
1288         }
1289 
1290         pthread_mutex_lock(&params->nti.mu);
1291         params->nti.rss = &rss;
1292         pthread_cond_broadcast(&params->nti.cv);
1293 
1294         while (params->nti.rss) {
1295             pthread_cond_wait(&params->nti.cv, &params->nti.mu);
1296         }
1297 
1298         pthread_mutex_unlock(&params->nti.mu);
1299     }
1300 
1301     params->written += tgt->size;
1302     rc = 0;
1303 
1304 pcnout:
1305     if (tgt) {
1306         free(tgt);
1307     }
1308 
1309     return rc;
1310 }
1311 
PerformCommandDiff(CommandParameters * params)1312 static int PerformCommandDiff(CommandParameters* params) {
1313     char* logparams = NULL;
1314     char* value = NULL;
1315     int blocks = 0;
1316     int overlap = 0;
1317     int rc = -1;
1318     int status = 0;
1319     RangeSet* tgt = NULL;
1320     RangeSinkState rss;
1321     size_t len = 0;
1322     size_t offset = 0;
1323     Value patch_value;
1324 
1325     if (!params) {
1326         goto pcdout;
1327     }
1328 
1329     logparams = strdup(params->cpos);
1330     value = strtok_r(NULL, " ", &params->cpos);
1331 
1332     if (value == NULL) {
1333         fprintf(stderr, "missing patch offset for %s\n", params->cmdname);
1334         goto pcdout;
1335     }
1336 
1337     offset = strtoul(value, NULL, 0);
1338 
1339     value = strtok_r(NULL, " ", &params->cpos);
1340 
1341     if (value == NULL) {
1342         fprintf(stderr, "missing patch length for %s\n", params->cmdname);
1343         goto pcdout;
1344     }
1345 
1346     len = strtoul(value, NULL, 0);
1347 
1348     if (params->version == 1) {
1349         status = LoadSrcTgtVersion1(&params->cpos, &tgt, &blocks, &params->buffer,
1350                     &params->bufsize, params->fd);
1351     } else if (params->version == 2) {
1352         status = LoadSrcTgtVersion2(&params->cpos, &tgt, &blocks, &params->buffer,
1353                     &params->bufsize, params->fd, params->stashbase, NULL);
1354     } else if (params->version >= 3) {
1355         status = LoadSrcTgtVersion3(params, &tgt, &blocks, 0, &overlap);
1356     }
1357 
1358     if (status == -1) {
1359         fprintf(stderr, "failed to read blocks for diff\n");
1360         goto pcdout;
1361     }
1362 
1363     if (status == 0) {
1364         params->foundwrites = 1;
1365     } else if (params->foundwrites) {
1366         fprintf(stderr, "warning: commands executed out of order [%s]\n", params->cmdname);
1367     }
1368 
1369     if (params->canwrite) {
1370         if (status == 0) {
1371             fprintf(stderr, "patching %d blocks to %d\n", blocks, tgt->size);
1372 
1373             patch_value.type = VAL_BLOB;
1374             patch_value.size = len;
1375             patch_value.data = (char*) (params->patch_start + offset);
1376 
1377             rss.fd = params->fd;
1378             rss.tgt = tgt;
1379             rss.p_block = 0;
1380             rss.p_remain = (tgt->pos[1] - tgt->pos[0]) * BLOCKSIZE;
1381 
1382             if (!check_lseek(params->fd, (off64_t) tgt->pos[0] * BLOCKSIZE, SEEK_SET)) {
1383                 goto pcdout;
1384             }
1385 
1386             if (params->cmdname[0] == 'i') {      // imgdiff
1387                 ApplyImagePatch(params->buffer, blocks * BLOCKSIZE, &patch_value,
1388                     &RangeSinkWrite, &rss, NULL, NULL);
1389             } else {
1390                 ApplyBSDiffPatch(params->buffer, blocks * BLOCKSIZE, &patch_value,
1391                     0, &RangeSinkWrite, &rss, NULL);
1392             }
1393 
1394             // We expect the output of the patcher to fill the tgt ranges exactly.
1395             if (rss.p_block != tgt->count || rss.p_remain != 0) {
1396                 fprintf(stderr, "range sink underrun?\n");
1397             }
1398         } else {
1399             fprintf(stderr, "skipping %d blocks already patched to %d [%s]\n",
1400                 blocks, tgt->size, logparams);
1401         }
1402     }
1403 
1404     if (params->freestash) {
1405         FreeStash(params->stashbase, params->freestash);
1406         params->freestash = NULL;
1407     }
1408 
1409     params->written += tgt->size;
1410     rc = 0;
1411 
1412 pcdout:
1413     if (logparams) {
1414         free(logparams);
1415     }
1416 
1417     if (tgt) {
1418         free(tgt);
1419     }
1420 
1421     return rc;
1422 }
1423 
PerformCommandErase(CommandParameters * params)1424 static int PerformCommandErase(CommandParameters* params) {
1425     char* range = NULL;
1426     int i;
1427     int rc = -1;
1428     RangeSet* tgt = NULL;
1429     struct stat st;
1430     uint64_t blocks[2];
1431 
1432     if (DEBUG_ERASE) {
1433         return PerformCommandZero(params);
1434     }
1435 
1436     if (!params) {
1437         goto pceout;
1438     }
1439 
1440     if (fstat(params->fd, &st) == -1) {
1441         fprintf(stderr, "failed to fstat device to erase: %s\n", strerror(errno));
1442         goto pceout;
1443     }
1444 
1445     if (!S_ISBLK(st.st_mode)) {
1446         fprintf(stderr, "not a block device; skipping erase\n");
1447         goto pceout;
1448     }
1449 
1450     range = strtok_r(NULL, " ", &params->cpos);
1451 
1452     if (range == NULL) {
1453         fprintf(stderr, "missing target blocks for zero\n");
1454         goto pceout;
1455     }
1456 
1457     tgt = parse_range(range);
1458 
1459     if (params->canwrite) {
1460         fprintf(stderr, " erasing %d blocks\n", tgt->size);
1461 
1462         for (i = 0; i < tgt->count; ++i) {
1463             // offset in bytes
1464             blocks[0] = tgt->pos[i * 2] * (uint64_t) BLOCKSIZE;
1465             // length in bytes
1466             blocks[1] = (tgt->pos[i * 2 + 1] - tgt->pos[i * 2]) * (uint64_t) BLOCKSIZE;
1467 
1468             if (ioctl(params->fd, BLKDISCARD, &blocks) == -1) {
1469                 fprintf(stderr, "BLKDISCARD ioctl failed: %s\n", strerror(errno));
1470                 goto pceout;
1471             }
1472         }
1473     }
1474 
1475     rc = 0;
1476 
1477 pceout:
1478     if (tgt) {
1479         free(tgt);
1480     }
1481 
1482     return rc;
1483 }
1484 
1485 // Definitions for transfer list command functions
1486 typedef int (*CommandFunction)(CommandParameters*);
1487 
1488 typedef struct {
1489     const char* name;
1490     CommandFunction f;
1491 } Command;
1492 
1493 // CompareCommands and CompareCommandNames are for the hash table
1494 
CompareCommands(const void * c1,const void * c2)1495 static int CompareCommands(const void* c1, const void* c2) {
1496     return strcmp(((const Command*) c1)->name, ((const Command*) c2)->name);
1497 }
1498 
CompareCommandNames(const void * c1,const void * c2)1499 static int CompareCommandNames(const void* c1, const void* c2) {
1500     return strcmp(((const Command*) c1)->name, (const char*) c2);
1501 }
1502 
1503 // HashString is used to hash command names for the hash table
1504 
HashString(const char * s)1505 static unsigned int HashString(const char *s) {
1506     unsigned int hash = 0;
1507     if (s) {
1508         while (*s) {
1509             hash = hash * 33 + *s++;
1510         }
1511     }
1512     return hash;
1513 }
1514 
1515 // args:
1516 //    - block device (or file) to modify in-place
1517 //    - transfer list (blob)
1518 //    - new data stream (filename within package.zip)
1519 //    - patch stream (filename within package.zip, must be uncompressed)
1520 
PerformBlockImageUpdate(const char * name,State * state,int argc,Expr * argv[],const Command * commands,int cmdcount,int dryrun)1521 static Value* PerformBlockImageUpdate(const char* name, State* state, int argc, Expr* argv[],
1522             const Command* commands, int cmdcount, int dryrun) {
1523 
1524     char* line = NULL;
1525     char* linesave = NULL;
1526     char* logcmd = NULL;
1527     char* transfer_list = NULL;
1528     CommandParameters params;
1529     const Command* cmd = NULL;
1530     const ZipEntry* new_entry = NULL;
1531     const ZipEntry* patch_entry = NULL;
1532     FILE* cmd_pipe = NULL;
1533     HashTable* cmdht = NULL;
1534     int i;
1535     int res;
1536     int rc = -1;
1537     int stash_max_blocks = 0;
1538     int total_blocks = 0;
1539     pthread_attr_t attr;
1540     unsigned int cmdhash;
1541     UpdaterInfo* ui = NULL;
1542     Value* blockdev_filename = NULL;
1543     Value* new_data_fn = NULL;
1544     Value* patch_data_fn = NULL;
1545     Value* transfer_list_value = NULL;
1546     ZipArchive* za = NULL;
1547 
1548     memset(&params, 0, sizeof(params));
1549     params.canwrite = !dryrun;
1550 
1551     fprintf(stderr, "performing %s\n", dryrun ? "verification" : "update");
1552 
1553     if (ReadValueArgs(state, argv, 4, &blockdev_filename, &transfer_list_value,
1554             &new_data_fn, &patch_data_fn) < 0) {
1555         goto pbiudone;
1556     }
1557 
1558     if (blockdev_filename->type != VAL_STRING) {
1559         ErrorAbort(state, "blockdev_filename argument to %s must be string", name);
1560         goto pbiudone;
1561     }
1562     if (transfer_list_value->type != VAL_BLOB) {
1563         ErrorAbort(state, "transfer_list argument to %s must be blob", name);
1564         goto pbiudone;
1565     }
1566     if (new_data_fn->type != VAL_STRING) {
1567         ErrorAbort(state, "new_data_fn argument to %s must be string", name);
1568         goto pbiudone;
1569     }
1570     if (patch_data_fn->type != VAL_STRING) {
1571         ErrorAbort(state, "patch_data_fn argument to %s must be string", name);
1572         goto pbiudone;
1573     }
1574 
1575     ui = (UpdaterInfo*) state->cookie;
1576 
1577     if (ui == NULL) {
1578         goto pbiudone;
1579     }
1580 
1581     cmd_pipe = ui->cmd_pipe;
1582     za = ui->package_zip;
1583 
1584     if (cmd_pipe == NULL || za == NULL) {
1585         goto pbiudone;
1586     }
1587 
1588     patch_entry = mzFindZipEntry(za, patch_data_fn->data);
1589 
1590     if (patch_entry == NULL) {
1591         fprintf(stderr, "%s(): no file \"%s\" in package", name, patch_data_fn->data);
1592         goto pbiudone;
1593     }
1594 
1595     params.patch_start = ui->package_zip_addr + mzGetZipEntryOffset(patch_entry);
1596     new_entry = mzFindZipEntry(za, new_data_fn->data);
1597 
1598     if (new_entry == NULL) {
1599         fprintf(stderr, "%s(): no file \"%s\" in package", name, new_data_fn->data);
1600         goto pbiudone;
1601     }
1602 
1603     params.fd = TEMP_FAILURE_RETRY(open(blockdev_filename->data, O_RDWR));
1604 
1605     if (params.fd == -1) {
1606         fprintf(stderr, "open \"%s\" failed: %s\n", blockdev_filename->data, strerror(errno));
1607         goto pbiudone;
1608     }
1609 
1610     if (params.canwrite) {
1611         params.nti.za = za;
1612         params.nti.entry = new_entry;
1613 
1614         pthread_mutex_init(&params.nti.mu, NULL);
1615         pthread_cond_init(&params.nti.cv, NULL);
1616         pthread_attr_init(&attr);
1617         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
1618 
1619         int error = pthread_create(&params.thread, &attr, unzip_new_data, &params.nti);
1620         if (error != 0) {
1621             fprintf(stderr, "pthread_create failed: %s\n", strerror(error));
1622             goto pbiudone;
1623         }
1624     }
1625 
1626     // The data in transfer_list_value is not necessarily null-terminated, so we need
1627     // to copy it to a new buffer and add the null that strtok_r will need.
1628     transfer_list = malloc(transfer_list_value->size + 1);
1629 
1630     if (transfer_list == NULL) {
1631         fprintf(stderr, "failed to allocate %zd bytes for transfer list\n",
1632             transfer_list_value->size + 1);
1633         goto pbiudone;
1634     }
1635 
1636     memcpy(transfer_list, transfer_list_value->data, transfer_list_value->size);
1637     transfer_list[transfer_list_value->size] = '\0';
1638 
1639     // First line in transfer list is the version number
1640     line = strtok_r(transfer_list, "\n", &linesave);
1641     params.version = strtol(line, NULL, 0);
1642 
1643     if (params.version < 1 || params.version > 3) {
1644         fprintf(stderr, "unexpected transfer list version [%s]\n", line);
1645         goto pbiudone;
1646     }
1647 
1648     fprintf(stderr, "blockimg version is %d\n", params.version);
1649 
1650     // Second line in transfer list is the total number of blocks we expect to write
1651     line = strtok_r(NULL, "\n", &linesave);
1652     total_blocks = strtol(line, NULL, 0);
1653 
1654     if (total_blocks < 0) {
1655         ErrorAbort(state, "unexpected block count [%s]\n", line);
1656         goto pbiudone;
1657     } else if (total_blocks == 0) {
1658         rc = 0;
1659         goto pbiudone;
1660     }
1661 
1662     if (params.version >= 2) {
1663         // Third line is how many stash entries are needed simultaneously
1664         line = strtok_r(NULL, "\n", &linesave);
1665         fprintf(stderr, "maximum stash entries %s\n", line);
1666 
1667         // Fourth line is the maximum number of blocks that will be stashed simultaneously
1668         line = strtok_r(NULL, "\n", &linesave);
1669         stash_max_blocks = strtol(line, NULL, 0);
1670 
1671         if (stash_max_blocks < 0) {
1672             ErrorAbort(state, "unexpected maximum stash blocks [%s]\n", line);
1673             goto pbiudone;
1674         }
1675 
1676         if (stash_max_blocks >= 0) {
1677             res = CreateStash(state, stash_max_blocks, blockdev_filename->data,
1678                     &params.stashbase);
1679 
1680             if (res == -1) {
1681                 goto pbiudone;
1682             }
1683 
1684             params.createdstash = res;
1685         }
1686     }
1687 
1688     // Build a hash table of the available commands
1689     cmdht = mzHashTableCreate(cmdcount, NULL);
1690 
1691     for (i = 0; i < cmdcount; ++i) {
1692         cmdhash = HashString(commands[i].name);
1693         mzHashTableLookup(cmdht, cmdhash, (void*) &commands[i], CompareCommands, true);
1694     }
1695 
1696     // Subsequent lines are all individual transfer commands
1697     for (line = strtok_r(NULL, "\n", &linesave); line;
1698          line = strtok_r(NULL, "\n", &linesave)) {
1699 
1700         logcmd = strdup(line);
1701         params.cmdname = strtok_r(line, " ", &params.cpos);
1702 
1703         if (params.cmdname == NULL) {
1704             fprintf(stderr, "missing command [%s]\n", line);
1705             goto pbiudone;
1706         }
1707 
1708         cmdhash = HashString(params.cmdname);
1709         cmd = (const Command*) mzHashTableLookup(cmdht, cmdhash, params.cmdname,
1710                                     CompareCommandNames, false);
1711 
1712         if (cmd == NULL) {
1713             fprintf(stderr, "unexpected command [%s]\n", params.cmdname);
1714             goto pbiudone;
1715         }
1716 
1717         if (cmd->f != NULL && cmd->f(&params) == -1) {
1718             fprintf(stderr, "failed to execute command [%s]\n",
1719                 logcmd ? logcmd : params.cmdname);
1720             goto pbiudone;
1721         }
1722 
1723         if (logcmd) {
1724             free(logcmd);
1725             logcmd = NULL;
1726         }
1727 
1728         if (params.canwrite) {
1729             fprintf(cmd_pipe, "set_progress %.4f\n", (double) params.written / total_blocks);
1730             fflush(cmd_pipe);
1731         }
1732     }
1733 
1734     if (params.canwrite) {
1735         pthread_join(params.thread, NULL);
1736 
1737         fprintf(stderr, "wrote %d blocks; expected %d\n", params.written, total_blocks);
1738         fprintf(stderr, "max alloc needed was %zu\n", params.bufsize);
1739 
1740         // Delete stash only after successfully completing the update, as it
1741         // may contain blocks needed to complete the update later.
1742         DeleteStash(params.stashbase);
1743     } else {
1744         fprintf(stderr, "verified partition contents; update may be resumed\n");
1745     }
1746 
1747     rc = 0;
1748 
1749 pbiudone:
1750     if (params.fd != -1) {
1751         if (fsync(params.fd) == -1) {
1752             fprintf(stderr, "fsync failed: %s\n", strerror(errno));
1753         }
1754         close(params.fd);
1755     }
1756 
1757     if (logcmd) {
1758         free(logcmd);
1759     }
1760 
1761     if (cmdht) {
1762         mzHashTableFree(cmdht);
1763     }
1764 
1765     if (params.buffer) {
1766         free(params.buffer);
1767     }
1768 
1769     if (transfer_list) {
1770         free(transfer_list);
1771     }
1772 
1773     if (blockdev_filename) {
1774         FreeValue(blockdev_filename);
1775     }
1776 
1777     if (transfer_list_value) {
1778         FreeValue(transfer_list_value);
1779     }
1780 
1781     if (new_data_fn) {
1782         FreeValue(new_data_fn);
1783     }
1784 
1785     if (patch_data_fn) {
1786         FreeValue(patch_data_fn);
1787     }
1788 
1789     // Only delete the stash if the update cannot be resumed, or it's
1790     // a verification run and we created the stash.
1791     if (params.isunresumable || (!params.canwrite && params.createdstash)) {
1792         DeleteStash(params.stashbase);
1793     }
1794 
1795     if (params.stashbase) {
1796         free(params.stashbase);
1797     }
1798 
1799     return StringValue(rc == 0 ? strdup("t") : strdup(""));
1800 }
1801 
1802 // The transfer list is a text file containing commands to
1803 // transfer data from one place to another on the target
1804 // partition.  We parse it and execute the commands in order:
1805 //
1806 //    zero [rangeset]
1807 //      - fill the indicated blocks with zeros
1808 //
1809 //    new [rangeset]
1810 //      - fill the blocks with data read from the new_data file
1811 //
1812 //    erase [rangeset]
1813 //      - mark the given blocks as empty
1814 //
1815 //    move <...>
1816 //    bsdiff <patchstart> <patchlen> <...>
1817 //    imgdiff <patchstart> <patchlen> <...>
1818 //      - read the source blocks, apply a patch (or not in the
1819 //        case of move), write result to target blocks.  bsdiff or
1820 //        imgdiff specifies the type of patch; move means no patch
1821 //        at all.
1822 //
1823 //        The format of <...> differs between versions 1 and 2;
1824 //        see the LoadSrcTgtVersion{1,2}() functions for a
1825 //        description of what's expected.
1826 //
1827 //    stash <stash_id> <src_range>
1828 //      - (version 2+ only) load the given source range and stash
1829 //        the data in the given slot of the stash table.
1830 //
1831 // The creator of the transfer list will guarantee that no block
1832 // is read (ie, used as the source for a patch or move) after it
1833 // has been written.
1834 //
1835 // In version 2, the creator will guarantee that a given stash is
1836 // loaded (with a stash command) before it's used in a
1837 // move/bsdiff/imgdiff command.
1838 //
1839 // Within one command the source and target ranges may overlap so
1840 // in general we need to read the entire source into memory before
1841 // writing anything to the target blocks.
1842 //
1843 // All the patch data is concatenated into one patch_data file in
1844 // the update package.  It must be stored uncompressed because we
1845 // memory-map it in directly from the archive.  (Since patches are
1846 // already compressed, we lose very little by not compressing
1847 // their concatenation.)
1848 //
1849 // In version 3, commands that read data from the partition (i.e.
1850 // move/bsdiff/imgdiff/stash) have one or more additional hashes
1851 // before the range parameters, which are used to check if the
1852 // command has already been completed and verify the integrity of
1853 // the source data.
1854 
BlockImageVerifyFn(const char * name,State * state,int argc,Expr * argv[])1855 Value* BlockImageVerifyFn(const char* name, State* state, int argc, Expr* argv[]) {
1856     // Commands which are not tested are set to NULL to skip them completely
1857     const Command commands[] = {
1858         { "bsdiff",     PerformCommandDiff  },
1859         { "erase",      NULL                },
1860         { "free",       PerformCommandFree  },
1861         { "imgdiff",    PerformCommandDiff  },
1862         { "move",       PerformCommandMove  },
1863         { "new",        NULL                },
1864         { "stash",      PerformCommandStash },
1865         { "zero",       NULL                }
1866     };
1867 
1868     // Perform a dry run without writing to test if an update can proceed
1869     return PerformBlockImageUpdate(name, state, argc, argv, commands,
1870                 sizeof(commands) / sizeof(commands[0]), 1);
1871 }
1872 
BlockImageUpdateFn(const char * name,State * state,int argc,Expr * argv[])1873 Value* BlockImageUpdateFn(const char* name, State* state, int argc, Expr* argv[]) {
1874     const Command commands[] = {
1875         { "bsdiff",     PerformCommandDiff  },
1876         { "erase",      PerformCommandErase },
1877         { "free",       PerformCommandFree  },
1878         { "imgdiff",    PerformCommandDiff  },
1879         { "move",       PerformCommandMove  },
1880         { "new",        PerformCommandNew   },
1881         { "stash",      PerformCommandStash },
1882         { "zero",       PerformCommandZero  }
1883     };
1884 
1885     return PerformBlockImageUpdate(name, state, argc, argv, commands,
1886                 sizeof(commands) / sizeof(commands[0]), 0);
1887 }
1888 
RangeSha1Fn(const char * name,State * state,int argc,Expr * argv[])1889 Value* RangeSha1Fn(const char* name, State* state, int argc, Expr* argv[]) {
1890     Value* blockdev_filename;
1891     Value* ranges;
1892     const uint8_t* digest = NULL;
1893     if (ReadValueArgs(state, argv, 2, &blockdev_filename, &ranges) < 0) {
1894         return NULL;
1895     }
1896 
1897     if (blockdev_filename->type != VAL_STRING) {
1898         ErrorAbort(state, "blockdev_filename argument to %s must be string", name);
1899         goto done;
1900     }
1901     if (ranges->type != VAL_STRING) {
1902         ErrorAbort(state, "ranges argument to %s must be string", name);
1903         goto done;
1904     }
1905 
1906     int fd = open(blockdev_filename->data, O_RDWR);
1907     if (fd < 0) {
1908         ErrorAbort(state, "open \"%s\" failed: %s", blockdev_filename->data, strerror(errno));
1909         goto done;
1910     }
1911 
1912     RangeSet* rs = parse_range(ranges->data);
1913     uint8_t buffer[BLOCKSIZE];
1914 
1915     SHA_CTX ctx;
1916     SHA_init(&ctx);
1917 
1918     int i, j;
1919     for (i = 0; i < rs->count; ++i) {
1920         if (!check_lseek(fd, (off64_t)rs->pos[i*2] * BLOCKSIZE, SEEK_SET)) {
1921             ErrorAbort(state, "failed to seek %s: %s", blockdev_filename->data,
1922                 strerror(errno));
1923             goto done;
1924         }
1925 
1926         for (j = rs->pos[i*2]; j < rs->pos[i*2+1]; ++j) {
1927             if (read_all(fd, buffer, BLOCKSIZE) == -1) {
1928                 ErrorAbort(state, "failed to read %s: %s", blockdev_filename->data,
1929                     strerror(errno));
1930                 goto done;
1931             }
1932 
1933             SHA_update(&ctx, buffer, BLOCKSIZE);
1934         }
1935     }
1936     digest = SHA_final(&ctx);
1937     close(fd);
1938 
1939   done:
1940     FreeValue(blockdev_filename);
1941     FreeValue(ranges);
1942     if (digest == NULL) {
1943         return StringValue(strdup(""));
1944     } else {
1945         return StringValue(PrintSha1(digest));
1946     }
1947 }
1948 
RegisterBlockImageFunctions()1949 void RegisterBlockImageFunctions() {
1950     RegisterFunction("block_image_verify", BlockImageVerifyFn);
1951     RegisterFunction("block_image_update", BlockImageUpdateFn);
1952     RegisterFunction("range_sha1", RangeSha1Fn);
1953 }
1954