mirror of
https://github.com/SirHumza/orbisRPC.git
synced 2026-10-06 07:00:39 +02:00
installer: verify copy by byte count + hash, stat lies in sandbox
This commit is contained in:
1 parent
ed30a008ce
commit
391b45f12c
1 file changed
+55
-25
+55
-25
@@ -56,36 +56,71 @@ static int step_assets(void){
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The sandbox makes stat()/fstat() lie about sizes (observed: 4096/4160
|
||||||
|
* for a 2071552-byte file, which made a perfect copy report "denied").
|
||||||
|
* open/read/write are truthful, so the proof is: count and hash what we
|
||||||
|
* wrote, then count and hash what we read back. No stat anywhere. */
|
||||||
|
static unsigned long long fnv1a(const unsigned char *p, size_t n,
|
||||||
|
unsigned long long h){
|
||||||
|
size_t i;
|
||||||
|
for(i = 0; i < n; i++){
|
||||||
|
h ^= p[i];
|
||||||
|
h *= 1099511628211ULL;
|
||||||
|
}
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
static int copy_file(const char *src, const char *dst){
|
static int copy_file(const char *src, const char *dst){
|
||||||
FILE *in, *out;
|
FILE *in, *out;
|
||||||
static unsigned char buf[65536];
|
static unsigned char buf[65536];
|
||||||
size_t n;
|
size_t n;
|
||||||
long expect = -1, got;
|
long written = 0, reread = 0;
|
||||||
struct stat st;
|
unsigned long long hw = 14695981039346656037ULL, hr = 14695981039346656037ULL;
|
||||||
int err = 0;
|
char detail[96];
|
||||||
|
|
||||||
in = fopen(src, "rb");
|
in = fopen(src, "rb");
|
||||||
if(!in){ ilog("src-open", errno, -1, -1); return -1; }
|
if(!in){ ilog("src-open", errno, -1, -1); return -1; }
|
||||||
if(fstat(fileno(in), &st) == 0) expect = (long)st.st_size;
|
|
||||||
else ilog("src-fstat", errno, -1, -1);
|
|
||||||
out = fopen(dst, "wb");
|
out = fopen(dst, "wb");
|
||||||
if(!out){ ilog("dst-open", errno, expect, -1); fclose(in); return -1; }
|
if(!out){ ilog("dst-open", errno, -1, -1); fclose(in); return -1; }
|
||||||
while((n = fread(buf, 1, sizeof buf, in)) > 0){
|
while((n = fread(buf, 1, sizeof buf, in)) > 0){
|
||||||
if(fwrite(buf, 1, n, out) != n){
|
if(fwrite(buf, 1, n, out) != n){
|
||||||
err = errno;
|
ilog("dst-write", errno, written, -1);
|
||||||
ilog("dst-write", err, expect, -1);
|
|
||||||
fclose(in); fclose(out); return -1;
|
fclose(in); fclose(out); return -1;
|
||||||
}
|
}
|
||||||
|
hw = fnv1a(buf, n, hw);
|
||||||
|
written += (long)n;
|
||||||
}
|
}
|
||||||
fclose(in);
|
fclose(in);
|
||||||
if(fclose(out) != 0){ ilog("dst-close", errno, expect, -1); return -1; }
|
if(fclose(out) != 0){ ilog("dst-close", errno, written, -1); return -1; }
|
||||||
/* Read-back proof: a short write must never pass as installed. */
|
if(written <= 0){ ilog("src-empty", 0, written, -1); return -1; }
|
||||||
if(expect > 0 && stat(dst, &st) == 0) got = (long)st.st_size;
|
|
||||||
else { got = -1; ilog("dst-stat", errno, expect, -1); }
|
/* Read-back proof: reopen and re-count/re-hash the destination. */
|
||||||
if(expect > 0 && got == expect){ ilog("copy-ok", 0, expect, got); return 0; }
|
in = fopen(dst, "rb");
|
||||||
ilog("size-mismatch", 0, expect, got);
|
if(!in){ ilog("verify-open", errno, written, -1); return -1; }
|
||||||
|
while((n = fread(buf, 1, sizeof buf, in)) > 0){
|
||||||
|
hr = fnv1a(buf, n, hr);
|
||||||
|
reread += (long)n;
|
||||||
|
}
|
||||||
|
fclose(in);
|
||||||
|
snprintf(detail, sizeof detail, "h=%016llx/%016llx", hw, hr);
|
||||||
|
if(written == reread && hw == hr){
|
||||||
|
ilog("copy-ok", 0, written, reread);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ilog("verify-mismatch", 0, written, reread);
|
||||||
|
ilog(detail, 0, 0, 0);
|
||||||
|
g_stage = "verify-mismatch";
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Existence check without stat() (the sandbox lies about stat sizes). */
|
||||||
|
static int exists(const char *p){
|
||||||
|
FILE *f = fopen(p, "rb");
|
||||||
|
if(!f) return 0;
|
||||||
|
fclose(f);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* mkdir -p (parents as needed). 0 ok or already there. */
|
/* mkdir -p (parents as needed). 0 ok or already there. */
|
||||||
static int mkdirs(const char *path){
|
static int mkdirs(const char *path){
|
||||||
char tmp[256];
|
char tmp[256];
|
||||||
@@ -181,26 +216,21 @@ static void step_token(void){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Status: read-only health snapshot for debugging. Never mutates. */
|
/* Status: read-only health snapshot for debugging. Never mutates.
|
||||||
|
* Existence only — stat() sizes/mtimes are unreliable under the sandbox. */
|
||||||
static void step_status(void){
|
static void step_status(void){
|
||||||
char out[640];
|
char out[640];
|
||||||
size_t used = 0;
|
size_t used = 0;
|
||||||
char tok[160];
|
char tok[160];
|
||||||
struct stat st;
|
|
||||||
tok[0] = 0;
|
tok[0] = 0;
|
||||||
icfg_token_load(ICFG_PATH, tok, sizeof tok);
|
icfg_token_load(ICFG_PATH, tok, sizeof tok);
|
||||||
used = (size_t)snprintf(out, sizeof out, "orbisRPC status:\n");
|
used = (size_t)snprintf(out, sizeof out, "orbisRPC status:\n");
|
||||||
used += (size_t)snprintf(out + used, sizeof out - used,
|
used += (size_t)snprintf(out + used, sizeof out - used,
|
||||||
"\ndaemon files: %s", stat(PAYLOAD_BIN, &st) == 0 ? "installed" : "missing");
|
"\ndaemon payload: %s", exists(PAYLOAD_BIN) ? "installed" : "missing");
|
||||||
used += (size_t)snprintf(out + used, sizeof out - used,
|
used += (size_t)snprintf(out + used, sizeof out - used,
|
||||||
"\nlock: %s", stat("/data/orbisRPC/daemon.lock", &st) == 0 ? "held (may be running)" : "free");
|
"\nlock: %s", exists("/data/orbisRPC/daemon.lock") ? "held (may be running)" : "free");
|
||||||
if(stat("/data/orbisRPC/log.txt", &st) == 0){
|
used += (size_t)snprintf(out + used, sizeof out - used,
|
||||||
long age = (long)time(NULL) - (long)st.st_mtime;
|
"\nlog: %s", exists("/data/orbisRPC/log.txt") ? "present" : "none yet");
|
||||||
used += (size_t)snprintf(out + used, sizeof out - used,
|
|
||||||
"\nlog: present, last write %lds ago", age < 0 ? 0 : age);
|
|
||||||
} else {
|
|
||||||
used += (size_t)snprintf(out + used, sizeof out - used, "\nlog: none yet");
|
|
||||||
}
|
|
||||||
used += (size_t)snprintf(out + used, sizeof out - used,
|
used += (size_t)snprintf(out + used, sizeof out - used,
|
||||||
"\ntoken: %s", token_valid(tok) ? "saved" : "missing/invalid");
|
"\ntoken: %s", token_valid(tok) ? "saved" : "missing/invalid");
|
||||||
used += (size_t)snprintf(out + used, sizeof out - used,
|
used += (size_t)snprintf(out + used, sizeof out - used,
|
||||||
|
|||||||
Reference in new issue
Block a user