int inverse_hash_memory(const struct hash *hash, void *p, size_t n) { const char *waitless_dir = getenv(WAITLESS_DIR); if (!waitless_dir) die("WAITLESS_DIR not set"); int dn = strlen(waitless_dir), in = strlen(INVERSE); int total = dn + in + 3 + SHOW_HASH_SIZE; if (total > PATH_MAX) die("WAITLESS_DIR is too long: %d > %d", dn, PATH_MAX - total + dn); // path = "waitless_dir/inverse/hash[0:2]/hash" char path[total]; memcpy(path, waitless_dir, dn); memcpy(path+dn, INVERSE, in); show_hash(path+dn+in+3, SHOW_HASH_SIZE, hash); memcpy(path+dn+in, path+dn+in+3, 2); path[dn+in+2] = '/'; // Read path // TODO: do enough file locking to prevent reading a partially written file int fd = real_open(path, O_RDONLY, 0); if (fd < 0) die("inverse_hash_memory: failed to open %s: %s", path, strerror(errno)); size_t r = read(fd, p, n); if (r < 0) die("inverse_hash_memory: read failed: %s", strerror(errno)); real_close(fd); return r; }
void remember_hash_memory(struct hash *hash, const void *p, size_t n) { hash_memory(hash, p, n); const char *waitless_dir = getenv(WAITLESS_DIR); if (!waitless_dir) die("WAITLESS_DIR not set"); int dn = strlen(waitless_dir), in = strlen(INVERSE); int total = dn + in + 3 + SHOW_HASH_SIZE; if (total > PATH_MAX) die("WAITLESS_DIR is too long: %d > %d", dn, PATH_MAX - total + dn); // path = "waitless_dir/inverse/hash[0:2]/hash" char path[total]; memcpy(path, waitless_dir, dn); memcpy(path+dn, INVERSE, in); show_hash(path+dn+in+3, SHOW_HASH_SIZE, hash); memcpy(path+dn+in, path+dn+in+3, 2); path[dn+in+2] = '/'; retry:; // Try to open path for exclusive create int fd = real_open(path, O_WRONLY | O_CREAT | O_EXCL, 0644); if (fd < 0) { // Failed: either file exists (great!) or we need to make directories int errno_ = errno; if (errno_ == EEXIST) { // If the file exists, we assume it already has the desired contents // (go cryptographic hashing). return; } else if (errno_ == ENOENT) { // Create the necessary directory components path[dn+in-1] = 0; if (mkdir(path, 0755) < 0 && errno != EEXIST) die("mkdir(\"%s\") failed: %s", path, strerror(errno)); path[dn+in-1] = '/'; path[dn+in+2] = 0; if (mkdir(path, 0755) < 0 && errno != EEXIST) die("mkdir(\"%s\") failed: %s", path, strerror(errno)); path[dn+in+2] = '/'; // Try to open again. Note that it's possible to hit EEXIST on // retry if another thread is trying to remember the same hash. goto retry; } die("failed to create %s: %s", path, strerror(errno_)); } if (write(fd, p, n) != n) die("remember_hash_memory: write failed: %s", strerror(errno)); if (real_close(fd) < 0) die("remember_hash_memory: close failed: %s", strerror(errno)); }
static void new_node(struct process *process, enum action_type type, const struct hash *data) { struct parents *parents = &process->parents; // If there are no parents, skip node generation entirely. This should // happen only from the initial action_execve call in waitless.c. if (!parents->n) return; char buffer[SHOW_HASH_SIZE*parents->n + 3 + SHOW_HASH_SIZE + 1 + SHOW_NODE_SIZE]; char *p = buffer; if (is_verbose()) { p += snprintf(p, sizeof(buffer), "%d: ", getpid()); int i; for (i = 0; i < parents->n; i++) { p = show_hash(p, 8, parents->p+i); *p++ = ' '; } p = stpcpy(p, "-> "); } // The new node's name is the hash of its parents' names. // We store the new node's name as parents[0] since it will be // the first parent of the following node. subgraph_node_name(parents->p, parents->p, parents->n); parents->n = 1; subgraph_new_node(parents->p, type, data); if (is_verbose()) { p = show_hash(p, 8, parents->p+0); p = stpcpy(p, ": "); p = show_subgraph_node(p, type, data); *p++ = '\n'; *p = 0; write_str(STDERR_FILENO, buffer); } }
int hash_command(const char *algo_name, int flags, cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { ulong addr, len; if (argc < 2) return CMD_RET_USAGE; addr = simple_strtoul(*argv++, NULL, 16); len = simple_strtoul(*argv++, NULL, 16); if (multi_hash()) { struct hash_algo *algo; u8 output[HASH_MAX_DIGEST_SIZE]; u8 vsum[HASH_MAX_DIGEST_SIZE]; void *buf; if (hash_lookup_algo(algo_name, &algo)) { printf("Unknown hash algorithm '%s'\n", algo_name); return CMD_RET_USAGE; } argc -= 2; if (algo->digest_size > HASH_MAX_DIGEST_SIZE) { puts("HASH_MAX_DIGEST_SIZE exceeded\n"); return 1; } buf = map_sysmem(addr, len); algo->hash_func_ws(buf, len, output, algo->chunk_size); unmap_sysmem(buf); /* Try to avoid code bloat when verify is not needed */ #ifdef CONFIG_HASH_VERIFY if (flags & HASH_FLAG_VERIFY) { #else if (0) { #endif if (!argc) return CMD_RET_USAGE; if (parse_verify_sum(algo, *argv, vsum, flags & HASH_FLAG_ENV)) { printf("ERROR: %s does not contain a valid " "%s sum\n", *argv, algo->name); return 1; } if (memcmp(output, vsum, algo->digest_size) != 0) { int i; show_hash(algo, addr, len, output); printf(" != "); for (i = 0; i < algo->digest_size; i++) printf("%02x", vsum[i]); puts(" ** ERROR **\n"); return 1; } } else { show_hash(algo, addr, len, output); printf("\n"); if (argc) { store_result(algo, output, *argv, flags & HASH_FLAG_ENV); } } /* Horrible code size hack for boards that just want crc32 */ } else { ulong crc; ulong *ptr; crc = crc32_wd(0, (const uchar *)addr, len, CHUNKSZ_CRC32); printf("CRC32 for %08lx ... %08lx ==> %08lx\n", addr, addr + len - 1, crc); if (argc >= 3) { ptr = (ulong *)simple_strtoul(argv[0], NULL, 16); *ptr = crc; } } return 0; }
static void test_from_string(const char *data, size_t len) { char *buf, *mem; size_t n = s_times; int opt = s_options; size_t out_len, out_len0, len2 = len, work_len; if (s_show_hash) { show_hash(data, len); return; } out_len0 = out_len = bmz_pack_buflen(len); buf = malloc(len + out_len); work_len = bmz_bm_pack_worklen(len, s_fp_len); mem = malloc(work_len); LOG(1, "input length: %lu, out_len %lu, work_len: %lu\n", (Lu)len, (Lu)out_len, (Lu)work_len); /* memcpy/memmove for comparison */ if (opt & O_MEMCPY) { BENCH("memcpy", memcpy(buf, data, len), len, n); } if (opt & O_CHECK_HASH) { if (opt & O_HASH_MOD) HT_CHECK(bmz_check_hash_mod(data, len, s_fp_len, s_b1, s_m) == BMZ_E_OK); if (opt & O_HASH_MOD16X2) HT_CHECK(bmz_check_hash_mod16x2(data, len, s_fp_len, s_b1, s_b2, s_m1, s_m2) == BMZ_E_OK); if (opt & O_HASH_MASK16X2) HT_CHECK(bmz_check_hash_mask16x2(data, len, s_fp_len, s_b1, s_b2) == BMZ_E_OK); if (opt & O_HASH_MASK) HT_CHECK(bmz_check_hash_mask(data, len, s_fp_len, s_b1) == BMZ_E_OK); if (opt & O_HASH_MASK32X2) HT_CHECK(bmz_check_hash_mask32x2(data, len, s_fp_len, s_b1, s_b2) == BMZ_E_OK); } if (opt & O_BENCH_HASH) { if (opt & O_HASH_MOD) BENCH("hash mod", bmz_bench_hash(data, len, BMZ_HASH_MOD), len, n); if (opt & O_HASH_MOD16X2) BENCH("hash mod16x2", bmz_bench_hash(data, len, BMZ_HASH_MOD16X2), len, n); if (opt & O_HASH_MASK16X2) BENCH("hash mask16x2", bmz_bench_hash(data, len, BMZ_HASH_MASK16X2), len, n); if (opt & O_HASH_MASK) BENCH("hash mask", bmz_bench_hash(data, len, BMZ_HASH_MASK), len, n); if (opt & O_HASH_MASK32X2) BENCH("hash mask32x2", bmz_bench_hash(data, len, BMZ_HASH_MASK32X2), len, n); } if (opt & O_BENCH_LUT) { if (opt & O_HASH_MOD) BENCH("lut mod", bmz_bench_lut_mod(data, len, s_fp_len, mem, s_b1, s_m), len, n); if (opt & O_HASH_MOD16X2) BENCH("lut mod16x2", bmz_bench_lut_mod16x2(data, len, s_fp_len, mem, s_b1, s_b2, s_m1, s_m2), len, n); if (opt & O_HASH_MASK16X2) BENCH("lut mask16x2", bmz_bench_lut_mask16x2(data, len, s_fp_len, mem, s_b1, s_b2), len, n); if (opt & O_HASH_MASK) BENCH("lut mask", bmz_bench_lut_mask(data, len, s_fp_len, mem, s_b1), len, n); if (opt & O_HASH_MASK32X2) BENCH("lut mask32x2", bmz_bench_lut_mask32x2(data, len, s_fp_len, mem, s_b1, s_b2), len, n); } if (opt != O_DEFAULT && (opt & 0xf)) return; if (opt & O_HASH_MOD) { BENCH("bm pack mod", test_bm_mod(data, len, buf, &out_len, mem), len, n); BENCH("bm unpack", test_bm_unpack(buf, out_len, buf + out_len, &len2), len, n); HT_CHECK(len == len2); HT_CHECK(memcmp(data, buf + out_len, len) == 0); } if (opt & O_HASH_MOD16X2) { memset(buf, 0, out_len); out_len = out_len0; BENCH("bm pack mod16x2", test_bm_mod16x2(data, len, buf, &out_len, mem), len, n); BENCH("bm unpack", test_bm_unpack(buf, out_len, buf + out_len, &len2), len, n); HT_CHECK(len == len2); HT_CHECK(memcmp(data, buf + out_len, len) == 0); } if (opt & O_HASH_MASK16X2) { memset(buf, 0, out_len); out_len = out_len0; BENCH("bm pack mask16x2", test_bm_mask16x2(data, len, buf, &out_len, mem), len, n); BENCH("bm unpack", test_bm_unpack(buf, out_len, buf + out_len, &len2), len, n); HT_CHECK(len == len2); HT_CHECK(memcmp(data, buf + out_len, len) == 0); } if (opt & O_HASH_MASK) { memset(buf, 0, out_len); out_len = out_len0; BENCH("bm pack mask", test_bm_mask(data, len, buf, &out_len, mem), len, n); BENCH("bm unpack", test_bm_unpack(buf, out_len, buf + out_len, &len2), len, n); HT_CHECK(len == len2); HT_CHECK(memcmp(data, buf + out_len, len) == 0); } if (opt & O_HASH_MASK32X2) { memset(buf, 0, out_len); out_len = out_len0; BENCH("bm pack mask32x2", test_bm_mask32x2(data, len, buf, &out_len, mem), len, n); BENCH("bm unpack", test_bm_unpack(buf, out_len, buf + out_len, &len2), len, n); HT_CHECK(len == len2); HT_CHECK(memcmp(data, buf + out_len, len) == 0); } }
int hash_command(const char *algo_name, int verify, cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { struct hash_algo *algo; ulong addr, len; u8 output[HASH_MAX_DIGEST_SIZE]; u8 vsum[HASH_MAX_DIGEST_SIZE]; if (argc < 2) return CMD_RET_USAGE; algo = find_hash_algo(algo_name); if (!algo) { printf("Unknown hash algorithm '%s'\n", algo_name); return CMD_RET_USAGE; } addr = simple_strtoul(*argv++, NULL, 16); len = simple_strtoul(*argv++, NULL, 16); argc -= 2; if (algo->digest_size > HASH_MAX_DIGEST_SIZE) { puts("HASH_MAX_DIGEST_SIZE exceeded\n"); return 1; } algo->hash_func_ws((const unsigned char *)addr, len, output, algo->chunk_size); /* Try to avoid code bloat when verify is not needed */ #ifdef CONFIG_HASH_VERIFY if (verify) { #else if (0) { #endif if (!argc) return CMD_RET_USAGE; if (parse_verify_sum(algo, *argv, vsum)) { printf("ERROR: %s does not contain a valid %s sum\n", *argv, algo->name); return 1; } if (memcmp(output, vsum, algo->digest_size) != 0) { int i; show_hash(algo, addr, len, output); printf(" != "); for (i = 0; i < algo->digest_size; i++) printf("%02x", vsum[i]); puts(" ** ERROR **\n"); return 1; } } else { show_hash(algo, addr, len, output); printf("\n"); if (argc) store_result(algo, output, *argv); } return 0; }