Commit a5e4f3cc authored by topjohnwu's avatar topjohnwu

Separate cpio logic from MagiskBoot

parent a30777bd
...@@ -100,12 +100,13 @@ LOCAL_SRC_FILES := \ ...@@ -100,12 +100,13 @@ LOCAL_SRC_FILES := \
magiskboot/bootimg.c \ magiskboot/bootimg.c \
magiskboot/hexpatch.c \ magiskboot/hexpatch.c \
magiskboot/compress.c \ magiskboot/compress.c \
magiskboot/cpio.c \
magiskboot/sha1.c \ magiskboot/sha1.c \
magiskboot/types.c \ magiskboot/types.c \
magiskboot/dtb.c \ magiskboot/dtb.c \
magiskboot/ramdisk.c \
utils/xwrap.c \ utils/xwrap.c \
utils/file.c \ utils/file.c \
utils/cpio.c \
utils/vector.c utils/vector.c
LOCAL_CFLAGS := -DNO_SELINUX LOCAL_CFLAGS := -DNO_SELINUX
......
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
#include <stdint.h> #include <stdint.h>
#include "vector.h"
typedef struct cpio_entry { typedef struct cpio_entry {
// uint32_t ino; // uint32_t ino;
uint32_t mode; uint32_t mode;
...@@ -39,18 +41,17 @@ typedef struct cpio_newc_header { ...@@ -39,18 +41,17 @@ typedef struct cpio_newc_header {
char check[8]; char check[8];
} cpio_newc_header; } cpio_newc_header;
typedef enum { void parse_cpio(const char *filename, struct vector *v);
NONE, void dump_cpio(const char *filename, struct vector *v);
RM, void cpio_vec_destroy(struct vector *v);
MKDIR, void cpio_rm(int recursive, const char *entry, struct vector *v);
ADD, void cpio_mkdir(mode_t mode, const char *entry, struct vector *v);
MV, void cpio_add(mode_t mode, const char *entry, const char *filename, struct vector *v);
EXTRACT, void cpio_mv(struct vector *v, const char *from, const char *to);
TEST, void cpio_test(struct vector *v);
PATCH, void cpio_extract(const char *entry, const char *filename, struct vector *v);
BACKUP, void cpio_backup(const char *orig, const char *sha1, struct vector *v);
RESTORE, int cpio_restore(struct vector *v);
STOCKSHA1 void cpio_stocksha1(struct vector *v);
} command_t;
#endif #endif
...@@ -32,4 +32,18 @@ size_t lz4_legacy(int mode, int fd, const void *buf, size_t size); ...@@ -32,4 +32,18 @@ size_t lz4_legacy(int mode, int fd, const void *buf, size_t size);
long long comp(file_t type, int to, const void *from, size_t size); long long comp(file_t type, int to, const void *from, size_t size);
long long decomp(file_t type, int to, const void *from, size_t size); long long decomp(file_t type, int to, const void *from, size_t size);
typedef enum {
NONE,
RM,
MKDIR,
ADD,
MV,
EXTRACT,
TEST,
PATCH,
BACKUP,
RESTORE,
STOCKSHA1
} command_t;
#endif #endif
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include "magiskboot.h"
#include "cpio.h"
int check_verity_pattern(const char *s) {
int pos = 0;
if (s[0] == ',') ++pos;
if (strncmp(s + pos, "verify", 6) == 0)
pos += 6;
else if (strncmp(s + pos, "avb", 3) == 0)
pos += 3;
else
return -1;
if (s[pos] == '=') {
while (s[pos] != '\0' && s[pos] != ' ' && s[pos] != '\n' && s[pos] != ',') ++pos;
}
return pos;
}
int check_encryption_pattern(const char *s) {
const char *encrypt_list[] = { "forceencrypt", "forcefdeorfbe", NULL };
for (int i = 0 ; encrypt_list[i]; ++i) {
int len = strlen(encrypt_list[i]);
if (strncmp(s, encrypt_list[i], len) == 0)
return len;
}
return -1;
}
void cpio_patch(struct vector *v, int keepverity, int keepforceencrypt) {
cpio_entry *f;
int skip, write;
vec_for_each(v, f) {
if (!keepverity) {
if (strstr(f->filename, "fstab") != NULL && S_ISREG(f->mode)) {
write = 0;
for (int read = 0; read < f->filesize; ++write, ++read) {
if ((skip = check_verity_pattern(f->data + read)) > 0) {
fprintf(stderr, "Remove pattern [%.*s] in [%s]\n", skip, f->data + read, f->filename);
read += skip;
}
f->data[write] = f->data[read];
}
f->filesize = write;
} else if (strcmp(f->filename, "verity_key") == 0) {
fprintf(stderr, "Remove [verity_key]\n");
f->remove = 1;
}
}
if (!keepforceencrypt) {
if (strstr(f->filename, "fstab") != NULL && S_ISREG(f->mode)) {
write = 0;
for (int read = 0; read < f->filesize; ++write, ++read) {
if ((skip = check_encryption_pattern(f->data + read)) > 0) {
// assert(skip > 11)!
fprintf(stderr, "Replace pattern [%.*s] with [encryptable] in [%s]\n", skip, f->data + read, f->filename);
memcpy(f->data + write, "encryptable", 11);
write += 11;
read += skip;
}
f->data[write] = f->data[read];
}
f->filesize = write;
}
}
}
}
int cpio_commands(const char *command, int argc, char *argv[]) {
int recursive = 0, ret = 0;
command_t cmd;
char *incpio = argv[0];
++argv;
--argc;
if (strcmp(command, "test") == 0) {
cmd = TEST;
} else if (strcmp(command, "restore") == 0) {
cmd = RESTORE;
} else if (strcmp(command, "stocksha1") == 0) {
cmd = STOCKSHA1;
} else if (argc >= 1 && strcmp(command, "backup") == 0) {
cmd = BACKUP;
} else if (argc > 0 && strcmp(command, "rm") == 0) {
cmd = RM;
if (argc == 2 && strcmp(argv[0], "-r") == 0) {
recursive = 1;
++argv;
--argc;
}
} else if (argc == 2 && strcmp(command, "mv") == 0) {
cmd = MV;
} else if (argc == 2 && strcmp(command, "patch") == 0) {
cmd = PATCH;
} else if (argc == 2 && strcmp(command, "extract") == 0) {
cmd = EXTRACT;
} else if (argc == 2 && strcmp(command, "mkdir") == 0) {
cmd = MKDIR;
} else if (argc == 3 && strcmp(command, "add") == 0) {
cmd = ADD;
} else {
cmd = NONE;
}
struct vector v;
vec_init(&v);
parse_cpio(incpio, &v);
switch(cmd) {
case TEST:
cpio_test(&v);
break;
case RESTORE:
ret = cpio_restore(&v);
break;
case STOCKSHA1:
cpio_stocksha1(&v);
return 0;
case BACKUP:
cpio_backup(argv[0], argc > 1 ? argv[1] : NULL, &v);
case RM:
cpio_rm(recursive, argv[0], &v);
break;
case PATCH:
cpio_patch(&v, strcmp(argv[0], "true") == 0, strcmp(argv[1], "true") == 0);
break;
case EXTRACT:
cpio_extract(argv[0], argv[1], &v);
break;
case MKDIR:
cpio_mkdir(strtoul(argv[0], NULL, 8), argv[1], &v);
break;
case ADD:
cpio_add(strtoul(argv[0], NULL, 8), argv[1], argv[2], &v);
break;
case MV:
cpio_mv(&v, argv[0], argv[1]);
break;
case NONE:
return 1;
}
dump_cpio(incpio, &v);
cpio_vec_destroy(&v);
exit(ret);
}
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include "magiskboot.h"
#include "cpio.h" #include "cpio.h"
#include "logging.h" #include "logging.h"
#include "utils.h" #include "utils.h"
...@@ -49,7 +48,7 @@ static int cpio_cmp(const void *a, const void *b) { ...@@ -49,7 +48,7 @@ static int cpio_cmp(const void *a, const void *b) {
} }
// Parse cpio file to a vector of cpio_entry // Parse cpio file to a vector of cpio_entry
static void parse_cpio(const char *filename, struct vector *v) { void parse_cpio(const char *filename, struct vector *v) {
fprintf(stderr, "Loading cpio: [%s]\n\n", filename); fprintf(stderr, "Loading cpio: [%s]\n\n", filename);
int fd = xopen(filename, O_RDONLY); int fd = xopen(filename, O_RDONLY);
cpio_newc_header header; cpio_newc_header header;
...@@ -90,7 +89,7 @@ static void parse_cpio(const char *filename, struct vector *v) { ...@@ -90,7 +89,7 @@ static void parse_cpio(const char *filename, struct vector *v) {
close(fd); close(fd);
} }
static void dump_cpio(const char *filename, struct vector *v) { void dump_cpio(const char *filename, struct vector *v) {
fprintf(stderr, "\nDump cpio: [%s]\n\n", filename); fprintf(stderr, "\nDump cpio: [%s]\n\n", filename);
int fd = creat(filename, 0644); int fd = creat(filename, 0644);
unsigned inode = 300000; unsigned inode = 300000;
...@@ -131,7 +130,7 @@ static void dump_cpio(const char *filename, struct vector *v) { ...@@ -131,7 +130,7 @@ static void dump_cpio(const char *filename, struct vector *v) {
close(fd); close(fd);
} }
static void cpio_vec_destroy(struct vector *v) { void cpio_vec_destroy(struct vector *v) {
// Free each cpio_entry // Free each cpio_entry
cpio_entry *f; cpio_entry *f;
vec_for_each(v, f) { vec_for_each(v, f) {
...@@ -140,7 +139,7 @@ static void cpio_vec_destroy(struct vector *v) { ...@@ -140,7 +139,7 @@ static void cpio_vec_destroy(struct vector *v) {
vec_destroy(v); vec_destroy(v);
} }
static void cpio_rm(int recursive, const char *entry, struct vector *v) { void cpio_rm(int recursive, const char *entry, struct vector *v) {
cpio_entry *f; cpio_entry *f;
vec_for_each(v, f) { vec_for_each(v, f) {
if (strncmp(f->filename, entry, strlen(entry)) == 0) { if (strncmp(f->filename, entry, strlen(entry)) == 0) {
...@@ -156,7 +155,7 @@ static void cpio_rm(int recursive, const char *entry, struct vector *v) { ...@@ -156,7 +155,7 @@ static void cpio_rm(int recursive, const char *entry, struct vector *v) {
} }
} }
static void cpio_mkdir(mode_t mode, const char *entry, struct vector *v) { void cpio_mkdir(mode_t mode, const char *entry, struct vector *v) {
cpio_entry *f = xcalloc(sizeof(*f), 1); cpio_entry *f = xcalloc(sizeof(*f), 1);
f->mode = S_IFDIR | mode; f->mode = S_IFDIR | mode;
f->namesize = strlen(entry) + 1; f->namesize = strlen(entry) + 1;
...@@ -165,7 +164,7 @@ static void cpio_mkdir(mode_t mode, const char *entry, struct vector *v) { ...@@ -165,7 +164,7 @@ static void cpio_mkdir(mode_t mode, const char *entry, struct vector *v) {
fprintf(stderr, "Create directory [%s] (%04o)\n",entry, mode); fprintf(stderr, "Create directory [%s] (%04o)\n",entry, mode);
} }
static void cpio_add(mode_t mode, const char *entry, const char *filename, struct vector *v) { void cpio_add(mode_t mode, const char *entry, const char *filename, struct vector *v) {
int fd = xopen(filename, O_RDONLY); int fd = xopen(filename, O_RDONLY);
cpio_entry *f = xcalloc(sizeof(*f), 1); cpio_entry *f = xcalloc(sizeof(*f), 1);
f->mode = S_IFREG | mode; f->mode = S_IFREG | mode;
...@@ -180,7 +179,28 @@ static void cpio_add(mode_t mode, const char *entry, const char *filename, struc ...@@ -180,7 +179,28 @@ static void cpio_add(mode_t mode, const char *entry, const char *filename, struc
fprintf(stderr, "Add entry [%s] (%04o)\n", entry, mode); fprintf(stderr, "Add entry [%s] (%04o)\n", entry, mode);
} }
static void cpio_test(struct vector *v) { void cpio_mv(struct vector *v, const char *from, const char *to) {
struct cpio_entry *f, *t;
vec_for_each(v, f) {
if (strcmp(f->filename, from) == 0) {
fprintf(stderr, "Move [%s] -> [%s]\n", from, to);
vec_for_each(v, t) {
if (strcmp(t->filename, to) == 0) {
t->remove = 1;
break;
}
}
free(f->filename);
f->namesize = strlen(to) + 1;
f->filename = strdup(to);
return;
}
}
fprintf(stderr, "Cannot find entry %s\n", from);
exit(1);
}
void cpio_test(struct vector *v) {
#define STOCK_BOOT 0x0 #define STOCK_BOOT 0x0
#define MAGISK_PATCH 0x1 #define MAGISK_PATCH 0x1
#define OTHER_PATCH 0x2 #define OTHER_PATCH 0x2
...@@ -205,72 +225,9 @@ static void cpio_test(struct vector *v) { ...@@ -205,72 +225,9 @@ static void cpio_test(struct vector *v) {
exit(ret); exit(ret);
} }
int check_verity_pattern(const char *s) {
int pos = 0;
if (s[0] == ',') ++pos;
if (strncmp(s + pos, "verify", 6) == 0)
pos += 6;
else if (strncmp(s + pos, "avb", 3) == 0)
pos += 3;
else
return -1;
if (s[pos] == '=') {
while (s[pos] != '\0' && s[pos] != ' ' && s[pos] != '\n' && s[pos] != ',') ++pos;
}
return pos;
}
int check_encryption_pattern(const char *s) {
const char *encrypt_list[] = { "forceencrypt", "forcefdeorfbe", NULL };
for (int i = 0 ; encrypt_list[i]; ++i) {
int len = strlen(encrypt_list[i]);
if (strncmp(s, encrypt_list[i], len) == 0)
return len;
}
return -1;
}
static void cpio_patch(struct vector *v, int keepverity, int keepforceencrypt) { void cpio_extract(const char *entry, const char *filename, struct vector *v) {
cpio_entry *f;
int skip, write;
vec_for_each(v, f) {
if (!keepverity) {
if (strstr(f->filename, "fstab") != NULL && S_ISREG(f->mode)) {
write = 0;
for (int read = 0; read < f->filesize; ++write, ++read) {
if ((skip = check_verity_pattern(f->data + read)) > 0) {
fprintf(stderr, "Remove pattern [%.*s] in [%s]\n", skip, f->data + read, f->filename);
read += skip;
}
f->data[write] = f->data[read];
}
f->filesize = write;
} else if (strcmp(f->filename, "verity_key") == 0) {
fprintf(stderr, "Remove [verity_key]\n");
f->remove = 1;
}
}
if (!keepforceencrypt) {
if (strstr(f->filename, "fstab") != NULL && S_ISREG(f->mode)) {
write = 0;
for (int read = 0; read < f->filesize; ++write, ++read) {
if ((skip = check_encryption_pattern(f->data + read)) > 0) {
// assert(skip > 11)!
fprintf(stderr, "Replace pattern [%.*s] with [encryptable] in [%s]\n", skip, f->data + read, f->filename);
memcpy(f->data + write, "encryptable", 11);
write += 11;
read += skip;
}
f->data[write] = f->data[read];
}
f->filesize = write;
}
}
}
}
static void cpio_extract(const char *entry, const char *filename, struct vector *v) {
cpio_entry *f; cpio_entry *f;
vec_for_each(v, f) { vec_for_each(v, f) {
if (strcmp(f->filename, entry) == 0 && S_ISREG(f->mode)) { if (strcmp(f->filename, entry) == 0 && S_ISREG(f->mode)) {
...@@ -286,7 +243,7 @@ static void cpio_extract(const char *entry, const char *filename, struct vector ...@@ -286,7 +243,7 @@ static void cpio_extract(const char *entry, const char *filename, struct vector
LOGE("Cannot find the file entry [%s]\n", entry); LOGE("Cannot find the file entry [%s]\n", entry);
} }
static void cpio_backup(const char *orig, const char *sha1, struct vector *v) { void cpio_backup(const char *orig, const char *sha1, struct vector *v) {
struct vector o_body, *o = &o_body, bak; struct vector o_body, *o = &o_body, bak;
cpio_entry *m, *n, *rem, *cksm; cpio_entry *m, *n, *rem, *cksm;
char buf[PATH_MAX]; char buf[PATH_MAX];
...@@ -394,7 +351,7 @@ static void cpio_backup(const char *orig, const char *sha1, struct vector *v) { ...@@ -394,7 +351,7 @@ static void cpio_backup(const char *orig, const char *sha1, struct vector *v) {
cpio_vec_destroy(o); cpio_vec_destroy(o);
} }
static int cpio_restore(struct vector *v) { int cpio_restore(struct vector *v) {
cpio_entry *f, *n; cpio_entry *f, *n;
int ret = 1; int ret = 1;
vec_for_each(v, f) { vec_for_each(v, f) {
...@@ -428,7 +385,7 @@ static int cpio_restore(struct vector *v) { ...@@ -428,7 +385,7 @@ static int cpio_restore(struct vector *v) {
return ret; return ret;
} }
static void cpio_stocksha1(struct vector *v) { void cpio_stocksha1(struct vector *v) {
cpio_entry *f; cpio_entry *f;
char sha1[41]; char sha1[41];
vec_for_each(v, f) { vec_for_each(v, f) {
...@@ -448,99 +405,3 @@ static void cpio_stocksha1(struct vector *v) { ...@@ -448,99 +405,3 @@ static void cpio_stocksha1(struct vector *v) {
} }
} }
} }
static void cpio_mv(struct vector *v, const char *from, const char *to) {
struct cpio_entry *f, *t;
vec_for_each(v, f) {
if (strcmp(f->filename, from) == 0) {
fprintf(stderr, "Move [%s] -> [%s]\n", from, to);
vec_for_each(v, t) {
if (strcmp(t->filename, to) == 0) {
t->remove = 1;
break;
}
}
free(f->filename);
f->namesize = strlen(to) + 1;
f->filename = strdup(to);
return;
}
}
fprintf(stderr, "Cannot find entry %s\n", from);
exit(1);
}
int cpio_commands(const char *command, int argc, char *argv[]) {
int recursive = 0, ret = 0;
command_t cmd;
char *incpio = argv[0];
++argv;
--argc;
if (strcmp(command, "test") == 0) {
cmd = TEST;
} else if (strcmp(command, "restore") == 0) {
cmd = RESTORE;
} else if (strcmp(command, "stocksha1") == 0) {
cmd = STOCKSHA1;
} else if (argc >= 1 && strcmp(command, "backup") == 0) {
cmd = BACKUP;
} else if (argc > 0 && strcmp(command, "rm") == 0) {
cmd = RM;
if (argc == 2 && strcmp(argv[0], "-r") == 0) {
recursive = 1;
++argv;
--argc;
}
} else if (argc == 2 && strcmp(command, "mv") == 0) {
cmd = MV;
} else if (argc == 2 && strcmp(command, "patch") == 0) {
cmd = PATCH;
} else if (argc == 2 && strcmp(command, "extract") == 0) {
cmd = EXTRACT;
} else if (argc == 2 && strcmp(command, "mkdir") == 0) {
cmd = MKDIR;
} else if (argc == 3 && strcmp(command, "add") == 0) {
cmd = ADD;
} else {
cmd = NONE;
}
struct vector v;
vec_init(&v);
parse_cpio(incpio, &v);
switch(cmd) {
case TEST:
cpio_test(&v);
break;
case RESTORE:
ret = cpio_restore(&v);
break;
case STOCKSHA1:
cpio_stocksha1(&v);
return 0;
case BACKUP:
cpio_backup(argv[0], argc > 1 ? argv[1] : NULL, &v);
case RM:
cpio_rm(recursive, argv[0], &v);
break;
case PATCH:
cpio_patch(&v, strcmp(argv[0], "true") == 0, strcmp(argv[1], "true") == 0);
break;
case EXTRACT:
cpio_extract(argv[0], argv[1], &v);
break;
case MKDIR:
cpio_mkdir(strtoul(argv[0], NULL, 8), argv[1], &v);
break;
case ADD:
cpio_add(strtoul(argv[0], NULL, 8), argv[1], argv[2], &v);
break;
case MV:
cpio_mv(&v, argv[0], argv[1]);
break;
case NONE:
return 1;
}
dump_cpio(incpio, &v);
cpio_vec_destroy(&v);
exit(ret);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment