From bac7fba02763ae5e78e8e4ba0bea727330ad953e Mon Sep 17 00:00:00 2001 From: Doug Zongker Date: Wed, 10 Apr 2013 11:32:17 -0700 Subject: verifier: update to support certificates using SHA-256 Change-Id: Ifd5a29d459acf101311fa1c220f728c3d0ac2e4e --- updater/install.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'updater') diff --git a/updater/install.c b/updater/install.c index 19054236c..1fc4fd394 100644 --- a/updater/install.c +++ b/updater/install.c @@ -1057,7 +1057,7 @@ Value* Sha1CheckFn(const char* name, State* state, int argc, Expr* argv[]) { return StringValue(strdup("")); } uint8_t digest[SHA_DIGEST_SIZE]; - SHA(args[0]->data, args[0]->size, digest); + SHA_hash(args[0]->data, args[0]->size, digest); FreeValue(args[0]); if (argc == 1) { -- cgit v1.2.3 From fafc85b4ad7a5679c6b562bed64460732e05fd1e Mon Sep 17 00:00:00 2001 From: Doug Zongker Date: Tue, 9 Jul 2013 12:29:45 -0700 Subject: recovery: move log output to stdout Recovery currently has a random mix of messages printed to stdout and messages printed to stderr, which can make logs hard to read. Move everything to stdout. Change-Id: Ie33bd4a9e1272e731302569cdec918e0534c48a6 --- updater/install.c | 72 +++++++++++++++++++++++++++---------------------------- updater/updater.c | 24 +++++++++---------- 2 files changed, 48 insertions(+), 48 deletions(-) (limited to 'updater') diff --git a/updater/install.c b/updater/install.c index 1fc4fd394..9fa06a225 100644 --- a/updater/install.c +++ b/updater/install.c @@ -97,13 +97,13 @@ Value* MountFn(const char* name, State* state, int argc, Expr* argv[]) { const MtdPartition* mtd; mtd = mtd_find_partition_by_name(location); if (mtd == NULL) { - fprintf(stderr, "%s: no mtd partition named \"%s\"", + printf("%s: no mtd partition named \"%s\"", name, location); result = strdup(""); goto done; } if (mtd_mount_partition(mtd, mount_point, fs_type, 0 /* rw */) != 0) { - fprintf(stderr, "mtd mount of %s failed: %s\n", + printf("mtd mount of %s failed: %s\n", location, strerror(errno)); result = strdup(""); goto done; @@ -112,7 +112,7 @@ Value* MountFn(const char* name, State* state, int argc, Expr* argv[]) { } else { if (mount(location, mount_point, fs_type, MS_NOATIME | MS_NODEV | MS_NODIRATIME, "") < 0) { - fprintf(stderr, "%s: failed to mount %s at %s: %s\n", + printf("%s: failed to mount %s at %s: %s\n", name, location, mount_point, strerror(errno)); result = strdup(""); } else { @@ -175,7 +175,7 @@ Value* UnmountFn(const char* name, State* state, int argc, Expr* argv[]) { scan_mounted_volumes(); const MountedVolume* vol = find_mounted_volume_by_mount_point(mount_point); if (vol == NULL) { - fprintf(stderr, "unmount of %s failed; no such volume\n", mount_point); + printf("unmount of %s failed; no such volume\n", mount_point); result = strdup(""); } else { unmount_mounted_volume(vol); @@ -233,25 +233,25 @@ Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) { mtd_scan_partitions(); const MtdPartition* mtd = mtd_find_partition_by_name(location); if (mtd == NULL) { - fprintf(stderr, "%s: no mtd partition named \"%s\"", + printf("%s: no mtd partition named \"%s\"", name, location); result = strdup(""); goto done; } MtdWriteContext* ctx = mtd_write_partition(mtd); if (ctx == NULL) { - fprintf(stderr, "%s: can't write \"%s\"", name, location); + printf("%s: can't write \"%s\"", name, location); result = strdup(""); goto done; } if (mtd_erase_blocks(ctx, -1) == -1) { mtd_write_close(ctx); - fprintf(stderr, "%s: failed to erase \"%s\"", name, location); + printf("%s: failed to erase \"%s\"", name, location); result = strdup(""); goto done; } if (mtd_write_close(ctx) != 0) { - fprintf(stderr, "%s: failed to close \"%s\"", name, location); + printf("%s: failed to close \"%s\"", name, location); result = strdup(""); goto done; } @@ -260,7 +260,7 @@ Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) { } else if (strcmp(fs_type, "ext4") == 0) { int status = make_ext4fs(location, atoll(fs_size), mount_point, sehandle); if (status != 0) { - fprintf(stderr, "%s: make_ext4fs failed (%d) on %s", + printf("%s: make_ext4fs failed (%d) on %s", name, status, location); result = strdup(""); goto done; @@ -268,7 +268,7 @@ Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) { result = location; #endif } else { - fprintf(stderr, "%s: unsupported fs_type \"%s\" partition_type \"%s\"", + printf("%s: unsupported fs_type \"%s\" partition_type \"%s\"", name, fs_type, partition_type); } @@ -394,13 +394,13 @@ Value* PackageExtractFileFn(const char* name, State* state, ZipArchive* za = ((UpdaterInfo*)(state->cookie))->package_zip; const ZipEntry* entry = mzFindZipEntry(za, zip_path); if (entry == NULL) { - fprintf(stderr, "%s: no %s in package\n", name, zip_path); + printf("%s: no %s in package\n", name, zip_path); goto done2; } FILE* f = fopen(dest_path, "wb"); if (f == NULL) { - fprintf(stderr, "%s: can't open %s for write: %s\n", + printf("%s: can't open %s for write: %s\n", name, dest_path, strerror(errno)); goto done2; } @@ -426,14 +426,14 @@ Value* PackageExtractFileFn(const char* name, State* state, ZipArchive* za = ((UpdaterInfo*)(state->cookie))->package_zip; const ZipEntry* entry = mzFindZipEntry(za, zip_path); if (entry == NULL) { - fprintf(stderr, "%s: no %s in package\n", name, zip_path); + printf("%s: no %s in package\n", name, zip_path); goto done1; } v->size = mzGetZipEntryUncompLen(entry); v->data = malloc(v->size); if (v->data == NULL) { - fprintf(stderr, "%s: failed to allocate %ld bytes for %s\n", + printf("%s: failed to allocate %ld bytes for %s\n", name, (long)v->size, zip_path); goto done1; } @@ -460,13 +460,13 @@ static int make_parents(char* name) { *p = '\0'; if (make_parents(name) < 0) return -1; int result = mkdir(name, 0700); - if (result == 0) fprintf(stderr, "symlink(): created [%s]\n", name); + if (result == 0) printf("symlink(): created [%s]\n", name); *p = '/'; if (result == 0 || errno == EEXIST) { // successfully created or already existed; we're done return 0; } else { - fprintf(stderr, "failed to mkdir %s: %s\n", name, strerror(errno)); + printf("failed to mkdir %s: %s\n", name, strerror(errno)); return -1; } } @@ -494,18 +494,18 @@ Value* SymlinkFn(const char* name, State* state, int argc, Expr* argv[]) { for (i = 0; i < argc-1; ++i) { if (unlink(srcs[i]) < 0) { if (errno != ENOENT) { - fprintf(stderr, "%s: failed to remove %s: %s\n", + printf("%s: failed to remove %s: %s\n", name, srcs[i], strerror(errno)); ++bad; } } if (make_parents(srcs[i])) { - fprintf(stderr, "%s: failed to symlink %s to %s: making parents failed\n", + printf("%s: failed to symlink %s to %s: making parents failed\n", name, srcs[i], target); ++bad; } if (symlink(target, srcs[i]) < 0) { - fprintf(stderr, "%s: failed to symlink %s to %s: %s\n", + printf("%s: failed to symlink %s to %s: %s\n", name, srcs[i], target, strerror(errno)); ++bad; } @@ -574,12 +574,12 @@ Value* SetPermFn(const char* name, State* state, int argc, Expr* argv[]) { for (i = 3; i < argc; ++i) { if (chown(args[i], uid, gid) < 0) { - fprintf(stderr, "%s: chown of %s to %d %d failed: %s\n", + printf("%s: chown of %s to %d %d failed: %s\n", name, args[i], uid, gid, strerror(errno)); ++bad; } if (chmod(args[i], mode) < 0) { - fprintf(stderr, "%s: chmod of %s to %o failed: %s\n", + printf("%s: chmod of %s to %o failed: %s\n", name, args[i], mode, strerror(errno)); ++bad; } @@ -720,7 +720,7 @@ static bool write_raw_image_cb(const unsigned char* data, int data_len, void* ctx) { int r = mtd_write_data((MtdWriteContext*)ctx, (const char *)data, data_len); if (r == data_len) return true; - fprintf(stderr, "%s\n", strerror(errno)); + printf("%s\n", strerror(errno)); return false; } @@ -752,14 +752,14 @@ Value* WriteRawImageFn(const char* name, State* state, int argc, Expr* argv[]) { mtd_scan_partitions(); const MtdPartition* mtd = mtd_find_partition_by_name(partition); if (mtd == NULL) { - fprintf(stderr, "%s: no mtd partition named \"%s\"\n", name, partition); + printf("%s: no mtd partition named \"%s\"\n", name, partition); result = strdup(""); goto done; } MtdWriteContext* ctx = mtd_write_partition(mtd); if (ctx == NULL) { - fprintf(stderr, "%s: can't write mtd partition \"%s\"\n", + printf("%s: can't write mtd partition \"%s\"\n", name, partition); result = strdup(""); goto done; @@ -772,7 +772,7 @@ Value* WriteRawImageFn(const char* name, State* state, int argc, Expr* argv[]) { char* filename = contents->data; FILE* f = fopen(filename, "rb"); if (f == NULL) { - fprintf(stderr, "%s: can't open %s: %s\n", + printf("%s: can't open %s: %s\n", name, filename, strerror(errno)); result = strdup(""); goto done; @@ -793,15 +793,15 @@ Value* WriteRawImageFn(const char* name, State* state, int argc, Expr* argv[]) { success = (wrote == contents->size); } if (!success) { - fprintf(stderr, "mtd_write_data to %s failed: %s\n", + printf("mtd_write_data to %s failed: %s\n", partition, strerror(errno)); } if (mtd_erase_blocks(ctx, -1) == -1) { - fprintf(stderr, "%s: error erasing blocks of %s\n", name, partition); + printf("%s: error erasing blocks of %s\n", name, partition); } if (mtd_write_close(ctx) != 0) { - fprintf(stderr, "%s: error closing write of %s\n", name, partition); + printf("%s: error closing write of %s\n", name, partition); } printf("%s %s partition\n", @@ -988,23 +988,23 @@ Value* RunProgramFn(const char* name, State* state, int argc, Expr* argv[]) { memcpy(args2, args, sizeof(char*) * argc); args2[argc] = NULL; - fprintf(stderr, "about to run program [%s] with %d args\n", args2[0], argc); + printf("about to run program [%s] with %d args\n", args2[0], argc); pid_t child = fork(); if (child == 0) { execv(args2[0], args2); - fprintf(stderr, "run_program: execv failed: %s\n", strerror(errno)); + printf("run_program: execv failed: %s\n", strerror(errno)); _exit(1); } int status; waitpid(child, &status, 0); if (WIFEXITED(status)) { if (WEXITSTATUS(status) != 0) { - fprintf(stderr, "run_program: child exited with status %d\n", + printf("run_program: child exited with status %d\n", WEXITSTATUS(status)); } } else if (WIFSIGNALED(status)) { - fprintf(stderr, "run_program: child terminated by signal %d\n", + printf("run_program: child terminated by signal %d\n", WTERMSIG(status)); } @@ -1053,7 +1053,7 @@ Value* Sha1CheckFn(const char* name, State* state, int argc, Expr* argv[]) { } if (args[0]->size < 0) { - fprintf(stderr, "%s(): no file contents received", name); + printf("%s(): no file contents received", name); return StringValue(strdup("")); } uint8_t digest[SHA_DIGEST_SIZE]; @@ -1068,12 +1068,12 @@ Value* Sha1CheckFn(const char* name, State* state, int argc, Expr* argv[]) { uint8_t* arg_digest = malloc(SHA_DIGEST_SIZE); for (i = 1; i < argc; ++i) { if (args[i]->type != VAL_STRING) { - fprintf(stderr, "%s(): arg %d is not a string; skipping", + printf("%s(): arg %d is not a string; skipping", name, i); } else if (ParseSha1(args[i]->data, arg_digest) != 0) { // Warn about bad args and skip them. - fprintf(stderr, "%s(): error parsing \"%s\" as sha-1; skipping", - name, args[i]->data); + printf("%s(): error parsing \"%s\" as sha-1; skipping", + name, args[i]->data); } else if (memcmp(digest, arg_digest, SHA_DIGEST_SIZE) == 0) { break; } diff --git a/updater/updater.c b/updater/updater.c index 58ac27f9e..c7009feac 100644 --- a/updater/updater.c +++ b/updater/updater.c @@ -36,13 +36,14 @@ struct selabel_handle *sehandle; int main(int argc, char** argv) { // Various things log information to stdout or stderr more or less - // at random. The log file makes more sense if buffering is - // turned off so things appear in the right order. + // at random (though we've tried to standardize on stdout). The + // log file makes more sense if buffering is turned off so things + // appear in the right order. setbuf(stdout, NULL); setbuf(stderr, NULL); if (argc != 4) { - fprintf(stderr, "unexpected number of arguments (%d)\n", argc); + printf("unexpected number of arguments (%d)\n", argc); return 1; } @@ -50,7 +51,7 @@ int main(int argc, char** argv) { if ((version[0] != '1' && version[0] != '2' && version[0] != '3') || version[1] != '\0') { // We support version 1, 2, or 3. - fprintf(stderr, "wrong updater binary API; expected 1, 2, or 3; " + printf("wrong updater binary API; expected 1, 2, or 3; " "got %s\n", argv[1]); return 2; @@ -69,20 +70,20 @@ int main(int argc, char** argv) { int err; err = mzOpenZipArchive(package_data, &za); if (err != 0) { - fprintf(stderr, "failed to open package %s: %s\n", + printf("failed to open package %s: %s\n", package_data, strerror(err)); return 3; } const ZipEntry* script_entry = mzFindZipEntry(&za, SCRIPT_NAME); if (script_entry == NULL) { - fprintf(stderr, "failed to find %s in %s\n", SCRIPT_NAME, package_data); + printf("failed to find %s in %s\n", SCRIPT_NAME, package_data); return 4; } char* script = malloc(script_entry->uncompLen+1); if (!mzReadZipEntry(&za, script_entry, script, script_entry->uncompLen)) { - fprintf(stderr, "failed to read script from package\n"); + printf("failed to read script from package\n"); return 5; } script[script_entry->uncompLen] = '\0'; @@ -101,7 +102,7 @@ int main(int argc, char** argv) { yy_scan_string(script); int error = yyparse(&root, &error_count); if (error != 0 || error_count > 0) { - fprintf(stderr, "%d parse errors\n", error_count); + printf("%d parse errors\n", error_count); return 6; } @@ -112,7 +113,6 @@ int main(int argc, char** argv) { sehandle = selabel_open(SELABEL_CTX_FILE, seopts, 1); if (!sehandle) { - fprintf(stderr, "Warning: No file_contexts\n"); fprintf(cmd_pipe, "ui_print Warning: No file_contexts\n"); } @@ -131,10 +131,10 @@ int main(int argc, char** argv) { char* result = Evaluate(&state, root); if (result == NULL) { if (state.errmsg == NULL) { - fprintf(stderr, "script aborted (no error message)\n"); + printf("script aborted (no error message)\n"); fprintf(cmd_pipe, "ui_print script aborted (no error message)\n"); } else { - fprintf(stderr, "script aborted: %s\n", state.errmsg); + printf("script aborted: %s\n", state.errmsg); char* line = strtok(state.errmsg, "\n"); while (line) { fprintf(cmd_pipe, "ui_print %s\n", line); @@ -145,7 +145,7 @@ int main(int argc, char** argv) { free(state.errmsg); return 7; } else { - fprintf(stderr, "script result was [%s]\n", result); + fprintf(cmd_pipe, "ui_print script succeeded: result was [%s]\n", result); free(result); } -- cgit v1.2.3 From 627eb30f73c29257acaeb6568f3da38880784f7c Mon Sep 17 00:00:00 2001 From: Nick Kralevich Date: Wed, 17 Jul 2013 19:01:37 -0700 Subject: Update OTA installer to understand SELinux filesystem labels Modify the OTA installer to understand SELinux filesystem labels. We do this by introducing new set_perm2 / set_perm2_recursive calls, which understand SELinux filesystem labels. These filesystem labels are applied at the same time that we apply the UID / GID / permission changes. For compatibility, we preserve the behavior of the existing set_perm / set_perm_recursive calls. If the destination kernel doesn't support security labels, don't fail. SELinux isn't enabled on all kernels. Bug: 8985290 Change-Id: I99800499f01784199e4918a82e3e2db1089cf25b --- updater/install.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) (limited to 'updater') diff --git a/updater/install.c b/updater/install.c index 9fa06a225..c81bbb59d 100644 --- a/updater/install.c +++ b/updater/install.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "cutils/misc.h" #include "cutils/properties.h" @@ -521,9 +522,10 @@ Value* SymlinkFn(const char* name, State* state, int argc, Expr* argv[]) { Value* SetPermFn(const char* name, State* state, int argc, Expr* argv[]) { char* result = NULL; - bool recursive = (strcmp(name, "set_perm_recursive") == 0); + bool recursive = (strcmp(name, "set_perm_recursive") == 0) || (strcmp(name, "set_perm2_recursive") == 0); + bool has_selabel = (strcmp(name, "set_perm2") == 0) || (strcmp(name, "set_perm2_recursive") == 0); - int min_args = 4 + (recursive ? 1 : 0); + int min_args = 4 + (has_selabel ? 1 : 0) + (recursive ? 1 : 0); if (argc < min_args) { return ErrorAbort(state, "%s() expects %d+ args, got %d", name, min_args, argc); @@ -562,8 +564,13 @@ Value* SetPermFn(const char* name, State* state, int argc, Expr* argv[]) { goto done; } - for (i = 4; i < argc; ++i) { - dirSetHierarchyPermissions(args[i], uid, gid, dir_mode, file_mode); + char* secontext = NULL; + if (has_selabel) { + secontext = args[4]; + } + + for (i = 4 + (has_selabel ? 1 : 0); i < argc; ++i) { + dirSetHierarchyPermissions(args[i], uid, gid, dir_mode, file_mode, secontext); } } else { int mode = strtoul(args[2], &end, 0); @@ -572,7 +579,12 @@ Value* SetPermFn(const char* name, State* state, int argc, Expr* argv[]) { goto done; } - for (i = 3; i < argc; ++i) { + char* secontext = NULL; + if (has_selabel) { + secontext = args[3]; + } + + for (i = 3 + (has_selabel ? 1 : 0); i < argc; ++i) { if (chown(args[i], uid, gid) < 0) { printf("%s: chown of %s to %d %d failed: %s\n", name, args[i], uid, gid, strerror(errno)); @@ -583,6 +595,11 @@ Value* SetPermFn(const char* name, State* state, int argc, Expr* argv[]) { name, args[i], mode, strerror(errno)); ++bad; } + if (has_selabel && lsetfilecon(args[i], secontext) && (errno != ENOTSUP)) { + printf("%s: lsetfilecon of %s to %s failed: %s\n", + name, args[i], secontext, strerror(errno)); + ++bad; + } } } result = strdup(""); @@ -1135,6 +1152,8 @@ void RegisterInstallFunctions() { RegisterFunction("symlink", SymlinkFn); RegisterFunction("set_perm", SetPermFn); RegisterFunction("set_perm_recursive", SetPermFn); + RegisterFunction("set_perm2", SetPermFn); + RegisterFunction("set_perm2_recursive", SetPermFn); RegisterFunction("getprop", GetPropFn); RegisterFunction("file_getprop", FileGetPropFn); -- cgit v1.2.3 From 3328e3bc81161c2a57ea94d304162276facdd826 Mon Sep 17 00:00:00 2001 From: Nick Kralevich Date: Mon, 9 Sep 2013 10:47:14 -0700 Subject: Revert "Update OTA installer to understand SELinux filesystem labels" This reverts commit 627eb30f73c29257acaeb6568f3da38880784f7c. Bug: 10183961 Bug: 10186213 --- updater/install.c | 29 +++++------------------------ 1 file changed, 5 insertions(+), 24 deletions(-) (limited to 'updater') diff --git a/updater/install.c b/updater/install.c index c81bbb59d..9fa06a225 100644 --- a/updater/install.c +++ b/updater/install.c @@ -27,7 +27,6 @@ #include #include #include -#include #include "cutils/misc.h" #include "cutils/properties.h" @@ -522,10 +521,9 @@ Value* SymlinkFn(const char* name, State* state, int argc, Expr* argv[]) { Value* SetPermFn(const char* name, State* state, int argc, Expr* argv[]) { char* result = NULL; - bool recursive = (strcmp(name, "set_perm_recursive") == 0) || (strcmp(name, "set_perm2_recursive") == 0); - bool has_selabel = (strcmp(name, "set_perm2") == 0) || (strcmp(name, "set_perm2_recursive") == 0); + bool recursive = (strcmp(name, "set_perm_recursive") == 0); - int min_args = 4 + (has_selabel ? 1 : 0) + (recursive ? 1 : 0); + int min_args = 4 + (recursive ? 1 : 0); if (argc < min_args) { return ErrorAbort(state, "%s() expects %d+ args, got %d", name, min_args, argc); @@ -564,13 +562,8 @@ Value* SetPermFn(const char* name, State* state, int argc, Expr* argv[]) { goto done; } - char* secontext = NULL; - if (has_selabel) { - secontext = args[4]; - } - - for (i = 4 + (has_selabel ? 1 : 0); i < argc; ++i) { - dirSetHierarchyPermissions(args[i], uid, gid, dir_mode, file_mode, secontext); + for (i = 4; i < argc; ++i) { + dirSetHierarchyPermissions(args[i], uid, gid, dir_mode, file_mode); } } else { int mode = strtoul(args[2], &end, 0); @@ -579,12 +572,7 @@ Value* SetPermFn(const char* name, State* state, int argc, Expr* argv[]) { goto done; } - char* secontext = NULL; - if (has_selabel) { - secontext = args[3]; - } - - for (i = 3 + (has_selabel ? 1 : 0); i < argc; ++i) { + for (i = 3; i < argc; ++i) { if (chown(args[i], uid, gid) < 0) { printf("%s: chown of %s to %d %d failed: %s\n", name, args[i], uid, gid, strerror(errno)); @@ -595,11 +583,6 @@ Value* SetPermFn(const char* name, State* state, int argc, Expr* argv[]) { name, args[i], mode, strerror(errno)); ++bad; } - if (has_selabel && lsetfilecon(args[i], secontext) && (errno != ENOTSUP)) { - printf("%s: lsetfilecon of %s to %s failed: %s\n", - name, args[i], secontext, strerror(errno)); - ++bad; - } } } result = strdup(""); @@ -1152,8 +1135,6 @@ void RegisterInstallFunctions() { RegisterFunction("symlink", SymlinkFn); RegisterFunction("set_perm", SetPermFn); RegisterFunction("set_perm_recursive", SetPermFn); - RegisterFunction("set_perm2", SetPermFn); - RegisterFunction("set_perm2_recursive", SetPermFn); RegisterFunction("getprop", GetPropFn); RegisterFunction("file_getprop", FileGetPropFn); -- cgit v1.2.3 From 5dbdef0e5b8a841fadc64d016d10ce81a962b284 Mon Sep 17 00:00:00 2001 From: Nick Kralevich Date: Sat, 7 Sep 2013 14:41:06 -0700 Subject: updater: introduce and set_metadata and set_metadata_recursive Introduce two new updater functions: * set_metadata * set_metadata_recursive Long term, these functions are intended to be more flexible replacements for the following methods: * set_perm * set_perm_recursive Usage: set_metadata("filename", "key1", "value1", "key2", "value2", ...) set_metadata_recursive("dirname", "key1", "value1", "key2", "value2", ...) Description: set_metadata() and set_metadata_recursive() set the attributes on a file/directory according to the key/value pairs provided. Today, the following keys are supported: * uid * gid * mode (set_perm_extd only) * fmode (set_perm_extd_recursive only) * dmode (set_perm_extd_recursive only) * selabel * capabilities Unknown keys are logged as warnings, but are not fatal errors. Examples: * set_metadata("/system/bin/netcfg", "selabel", "u:object_r:system_file:s0"); This sets the SELinux label of /system/bin/netcfg to u:object_r:system_file:s0. No other changes occur. * set_metadata("/system/bin/netcfg", "uid", 0, "gid", 3003, "mode", 02750, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0); This sets /system/bin/netcfg to uid=0, gid=3003, mode=02750, selinux label=u:object_r:system_file:s0, and clears the capabilities associated with the file. * set_metadata_recursive("/system", "uid", 0, "gid", 0, "fmode", 0644, "dmode", 0755, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0); All files and directories under /system are set to uid=0, gid=0, and selinux label=u:object_r:system_file:s0. Directories are set to mode=0755. Files are set to mode=0644 and all capabilities are cleared. Bug: 10183961 Bug: 10186213 Bug: 8985290 Change-Id: Ifdcf186a7ed45265511dc493c4036e1ac5e3d0af --- updater/install.c | 274 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 274 insertions(+) (limited to 'updater') diff --git a/updater/install.c b/updater/install.c index 9fa06a225..770dbd09e 100644 --- a/updater/install.c +++ b/updater/install.c @@ -27,6 +27,12 @@ #include #include #include +#include +#include +#include +#include +#include +#include #include "cutils/misc.h" #include "cutils/properties.h" @@ -600,6 +606,259 @@ done: return StringValue(result); } +struct perm_parsed_args { + bool has_uid; + uid_t uid; + bool has_gid; + gid_t gid; + bool has_mode; + mode_t mode; + bool has_fmode; + mode_t fmode; + bool has_dmode; + mode_t dmode; + bool has_selabel; + char* selabel; + bool has_capabilities; + uint64_t capabilities; +}; + +static struct perm_parsed_args ParsePermArgs(int argc, char** args) { + int i; + struct perm_parsed_args parsed; + int bad = 0; + static int max_warnings = 20; + + memset(&parsed, 0, sizeof(parsed)); + + for (i = 1; i < argc; i += 2) { + if (strcmp("uid", args[i]) == 0) { + int64_t uid; + if (sscanf(args[i+1], "%" SCNd64, &uid) == 1) { + parsed.uid = uid; + parsed.has_uid = true; + } else { + printf("ParsePermArgs: invalid UID \"%s\"\n", args[i + 1]); + bad++; + } + continue; + } + if (strcmp("gid", args[i]) == 0) { + int64_t gid; + if (sscanf(args[i+1], "%" SCNd64, &gid) == 1) { + parsed.gid = gid; + parsed.has_gid = true; + } else { + printf("ParsePermArgs: invalid GID \"%s\"\n", args[i + 1]); + bad++; + } + continue; + } + if (strcmp("mode", args[i]) == 0) { + int32_t mode; + if (sscanf(args[i+1], "%" SCNi32, &mode) == 1) { + parsed.mode = mode; + parsed.has_mode = true; + } else { + printf("ParsePermArgs: invalid mode \"%s\"\n", args[i + 1]); + bad++; + } + continue; + } + if (strcmp("dmode", args[i]) == 0) { + int32_t mode; + if (sscanf(args[i+1], "%" SCNi32, &mode) == 1) { + parsed.dmode = mode; + parsed.has_dmode = true; + } else { + printf("ParsePermArgs: invalid dmode \"%s\"\n", args[i + 1]); + bad++; + } + continue; + } + if (strcmp("fmode", args[i]) == 0) { + int32_t mode; + if (sscanf(args[i+1], "%" SCNi32, &mode) == 1) { + parsed.fmode = mode; + parsed.has_fmode = true; + } else { + printf("ParsePermArgs: invalid fmode \"%s\"\n", args[i + 1]); + bad++; + } + continue; + } + if (strcmp("capabilities", args[i]) == 0) { + int64_t capabilities; + if (sscanf(args[i+1], "%" SCNi64, &capabilities) == 1) { + parsed.capabilities = capabilities; + parsed.has_capabilities = true; + } else { + printf("ParsePermArgs: invalid capabilities \"%s\"\n", args[i + 1]); + bad++; + } + continue; + } + if (strcmp("selabel", args[i]) == 0) { + if (args[i+1][0] != '\0') { + parsed.selabel = args[i+1]; + parsed.has_selabel = true; + } else { + printf("ParsePermArgs: invalid selabel \"%s\"\n", args[i + 1]); + bad++; + } + continue; + } + if (max_warnings != 0) { + printf("ParsedPermArgs: unknown key \"%s\", ignoring\n", args[i]); + max_warnings--; + if (max_warnings == 0) { + printf("ParsedPermArgs: suppressing further warnings\n"); + } + } + } + return parsed; +} + +static int ApplyParsedPerms( + const char* filename, + const struct stat *statptr, + struct perm_parsed_args parsed) +{ + int bad = 0; + + if (parsed.has_uid) { + if (chown(filename, parsed.uid, -1) < 0) { + printf("ApplyParsedPerms: chown of %s to %d failed: %s\n", + filename, parsed.uid, strerror(errno)); + bad++; + } + } + + if (parsed.has_gid) { + if (chown(filename, -1, parsed.gid) < 0) { + printf("ApplyParsedPerms: chgrp of %s to %d failed: %s\n", + filename, parsed.gid, strerror(errno)); + bad++; + } + } + + if (parsed.has_mode) { + if (chmod(filename, parsed.mode) < 0) { + printf("ApplyParsedPerms: chmod of %s to %d failed: %s\n", + filename, parsed.mode, strerror(errno)); + bad++; + } + } + + if (parsed.has_dmode && S_ISDIR(statptr->st_mode)) { + if (chmod(filename, parsed.dmode) < 0) { + printf("ApplyParsedPerms: chmod of %s to %d failed: %s\n", + filename, parsed.dmode, strerror(errno)); + bad++; + } + } + + if (parsed.has_fmode && S_ISREG(statptr->st_mode)) { + if (chmod(filename, parsed.fmode) < 0) { + printf("ApplyParsedPerms: chmod of %s to %d failed: %s\n", + filename, parsed.fmode, strerror(errno)); + bad++; + } + } + + if (parsed.has_selabel) { + // TODO: Don't silently ignore ENOTSUP + if (lsetfilecon(filename, parsed.selabel) && (errno != ENOTSUP)) { + printf("ApplyParsedPerms: lsetfilecon of %s to %s failed: %s\n", + filename, parsed.selabel, strerror(errno)); + bad++; + } + } + + if (parsed.has_capabilities && S_ISREG(statptr->st_mode)) { + if (parsed.capabilities == 0) { + if ((removexattr(filename, XATTR_NAME_CAPS) == -1) && (errno != ENODATA)) { + // Report failure unless it's ENODATA (attribute not set) + printf("ApplyParsedPerms: removexattr of %s to %" PRIx64 " failed: %s\n", + filename, parsed.capabilities, strerror(errno)); + bad++; + } + } else { + struct vfs_cap_data cap_data; + memset(&cap_data, 0, sizeof(cap_data)); + cap_data.magic_etc = VFS_CAP_REVISION | VFS_CAP_FLAGS_EFFECTIVE; + cap_data.data[0].permitted = (uint32_t) (parsed.capabilities & 0xffffffff); + cap_data.data[0].inheritable = 0; + cap_data.data[1].permitted = (uint32_t) (parsed.capabilities >> 32); + cap_data.data[1].inheritable = 0; + if (setxattr(filename, XATTR_NAME_CAPS, &cap_data, sizeof(cap_data), 0) < 0) { + printf("ApplyParsedPerms: setcap of %s to %" PRIx64 " failed: %s\n", + filename, parsed.capabilities, strerror(errno)); + bad++; + } + } + } + + return bad; +} + +// nftw doesn't allow us to pass along context, so we need to use +// global variables. *sigh* +static struct perm_parsed_args recursive_parsed_args; + +static int do_SetMetadataRecursive(const char* filename, const struct stat *statptr, + int fileflags, struct FTW *pfwt) { + return ApplyParsedPerms(filename, statptr, recursive_parsed_args); +} + +static Value* SetMetadataFn(const char* name, State* state, int argc, Expr* argv[]) { + int i; + int bad = 0; + static int nwarnings = 0; + struct stat sb; + Value* result = NULL; + + bool recursive = (strcmp(name, "set_metadata_recursive") == 0); + + if ((argc % 2) != 1) { + return ErrorAbort(state, "%s() expects an odd number of arguments, got %d", + name, argc); + } + + char** args = ReadVarArgs(state, argc, argv); + if (args == NULL) return NULL; + + if (lstat(args[0], &sb) == -1) { + result = ErrorAbort(state, "%s: Error on lstat of \"%s\": %s", name, args[0], strerror(errno)); + goto done; + } + + struct perm_parsed_args parsed = ParsePermArgs(argc, args); + + if (recursive) { + recursive_parsed_args = parsed; + bad += nftw(args[0], do_SetMetadataRecursive, 30, FTW_CHDIR | FTW_DEPTH | FTW_PHYS); + memset(&recursive_parsed_args, 0, sizeof(recursive_parsed_args)); + } else { + bad += ApplyParsedPerms(args[0], &sb, parsed); + } + +done: + for (i = 0; i < argc; ++i) { + free(args[i]); + } + free(args); + + if (result != NULL) { + return result; + } + + if (bad > 0) { + return ErrorAbort(state, "%s: some changes failed", name); + } + + return StringValue(strdup("")); +} Value* GetPropFn(const char* name, State* state, int argc, Expr* argv[]) { if (argc != 1) { @@ -1133,9 +1392,24 @@ void RegisterInstallFunctions() { RegisterFunction("package_extract_dir", PackageExtractDirFn); RegisterFunction("package_extract_file", PackageExtractFileFn); RegisterFunction("symlink", SymlinkFn); + + // Maybe, at some future point, we can delete these functions? They have been + // replaced by perm_set and perm_set_recursive. RegisterFunction("set_perm", SetPermFn); RegisterFunction("set_perm_recursive", SetPermFn); + // Usage: + // set_metadata("filename", "key1", "value1", "key2", "value2", ...) + // Example: + // set_metadata("/system/bin/netcfg", "uid", 0, "gid", 3003, "mode", 02750, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0); + RegisterFunction("set_metadata", SetMetadataFn); + + // Usage: + // set_metadata_recursive("dirname", "key1", "value1", "key2", "value2", ...) + // Example: + // set_metadata_recursive("/system", "uid", 0, "gid", 0, "fmode", 0644, "dmode", 0755, "selabel", "u:object_r:system_file:s0", "capabilities", 0x0); + RegisterFunction("set_metadata_recursive", SetMetadataFn); + RegisterFunction("getprop", GetPropFn); RegisterFunction("file_getprop", FileGetPropFn); RegisterFunction("write_raw_image", WriteRawImageFn); -- cgit v1.2.3 From e461251e2caa5561cf6a315bffaebfd4eb896b1d Mon Sep 17 00:00:00 2001 From: Nick Kralevich Date: Tue, 10 Sep 2013 15:34:19 -0700 Subject: Don't apply permission changes to symlink. Bug: 10183961 Bug: 10186213 Bug: 8985290 Change-Id: I57cb14af59682c5f25f1e091564548bdbf20f74e --- updater/install.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'updater') diff --git a/updater/install.c b/updater/install.c index 770dbd09e..0a859452a 100644 --- a/updater/install.c +++ b/updater/install.c @@ -726,6 +726,11 @@ static int ApplyParsedPerms( { int bad = 0; + /* ignore symlinks */ + if (S_ISLNK(statptr->st_mode)) { + return 0; + } + if (parsed.has_uid) { if (chown(filename, parsed.uid, -1) < 0) { printf("ApplyParsedPerms: chown of %s to %d failed: %s\n", -- cgit v1.2.3