/* limit zerovm i/o */ static void LimitOwnIO() { struct rlimit rl; assert(storage_limit > 0); ZLOGIF(getrlimit(RLIMIT_FSIZE, &rl) != 0, "cannot get i/o limits"); rl.rlim_cur = storage_limit; ZLOGIF(setrlimit(RLIMIT_FSIZE, &rl) != 0, "cannot set i/o limits"); }
/* limit zerovm i/o */ static void LimitOwnIO(struct NaClApp *nap) { struct rlimit rl; assert(nap != NULL); assert(nap->storage_limit > 0); ZLOGIF(getrlimit(RLIMIT_FSIZE, &rl) != 0, "cannot get i/o limits"); rl.rlim_cur = nap->storage_limit; ZLOGIF(setrlimit(RLIMIT_FSIZE, &rl) != 0, "cannot set i/o limits"); }
/* part of report class dtor */ static void Report(struct NaClApp *nap) { GString *report = g_string_sized_new(BIG_ENOUGH_STRING); char *eol = hide_report ? "; " : "\n"; /* report validator state and user return code */ g_string_append_printf(report, "%s%d%s", REPORT_VALIDATOR, validation_state, eol); g_string_append_printf(report, "%s%d%s", REPORT_RETCODE, user_code, eol); /* add memory digest to cumulative digests if asked */ if(nap != NULL && nap->manifest != NULL) if(nap->manifest->mem_tag != NULL) ReportTag(STDRAM, GetMemoryDigest(nap)); /* report tags digests and remove ending " " if exist */ g_string_append_printf(report, "%s", REPORT_ETAG); g_string_append_printf(report, "%s", digests->len == 0 ? TAG_ENGINE_DISABLED : digests->str); g_string_truncate(report, report->len - 1); /* report accounting and session message */ g_string_append_printf(report, "%s%s%s%s", eol, REPORT_ACCOUNTING, GetAccountingInfo(), eol); g_string_append_printf(report, "%s%s%s", REPORT_STATE, zvm_state, eol); /* output report */ if(hide_report) ZLOGS(LOG_ERROR, "%s", report->str); else ZLOGIF(write(STDOUT_FILENO, report->str, report->len) != report->len, "report write error %d: %s", errno, strerror(errno)); g_string_free(report, TRUE); g_string_free(digests, TRUE); }
/* todo(d'b): under construction */ static void LimitOwnMemory() { #if 0 int result; ZLOGIF(result != 0, "cannot limit zerovm i/o"); #endif }
/* todo(d'b): under construction */ static void DisableSuperUser() { #if 0 int result; if (getuid() == 0) { /* process is running as root, drop privileges */ if (setgid(groupid) != 0) fatal("setgid: Unable to drop group privileges: %s", strerror(errno)); if (setuid(userid) != 0) fatal("setuid: Unable to drop user privileges: %S", strerror(errno)); } ZLOGIF(result != 0, "cannot disable super user"); #endif }
/* populate "buf" with an extended accounting statistics, return string size */ static int ReadSystemAccounting(const struct NaClApp *nap, char *buf, int size) { uint64_t user_time = 0; uint64_t sys_time = 0; uint64_t c_user_time = 0; /* 0mq network time */ uint64_t c_sys_time = 0; /* 0mq network time */ int64_t memory_size = 0; uint64_t ticks; pid_t pid; FILE *f; char path[BIG_ENOUGH_STRING]; assert(nap != NULL); assert(buf != NULL); assert(nap->system_manifest != NULL); assert(size > 0); /* get time information */ ticks = sysconf(_SC_CLK_TCK); pid = getpid(); g_snprintf(path, BIG_ENOUGH_STRING, "/proc/%d/stat", pid); f = fopen(path, "r"); if(f != NULL) { int code; code = fscanf(f, STAT_FMT, &user_time, &sys_time, &c_user_time, &c_sys_time); ZLOGIF(code != 4, "error %d occured while reading '%s'", errno, path); /* combine user times and system times */ user_time += c_user_time; sys_time += c_sys_time; fclose(f); } /* get memory information */ memory_size = nap->heap_end + nap->stack_size; /* construct and return the result */ return g_snprintf(buf, size, "%.2f %.2f %ld %ld", (float)sys_time / ticks, (float)user_time / ticks, memory_size, (int64_t)0); }
/* * send the parcel to the name server and get it back * return the received parcel size */ static int32_t PollServer(const struct Connection *server, char *parcel, uint32_t size) { int i; int s; int32_t result; struct sockaddr_in addr; uint32_t len = sizeof addr; struct timeval timeout = {TIMEOUT / MICRO_PER_SEC, TIMEOUT % MICRO_PER_SEC}; /* connect to the name server */ s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); addr.sin_addr.s_addr = server->host; addr.sin_port = bswap_16(server->port); addr.sin_family = AF_INET; /* set timeout on socket i/o */ result = setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof timeout); ZLOGFAIL(result == -1, errno, "cannot set receiving timeout"); result = setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof timeout); ZLOGFAIL(result == -1, errno, "cannot set sending timeout"); /* poll server */ for(i = 0; i < RETRY; ++i) { ZLOGS(LOG_DEBUG, "parcel out #%d: %s", i, HexDump(parcel, size)); result = sendto(s, parcel, size, 0, &addr, sizeof addr); if(result < 0) continue; result = recvfrom(s, parcel, size, 0, &addr, &len); if(result > 0) break; } ZLOGIF(i && result > 0, "name service polled with %d retries", i); ZLOGFAIL(result == -1, errno, "name service failed"); ZLOGS(LOG_DEBUG, "parcel in: %s", HexDump(parcel, size)); close(s); return result; }
/* lower zerovm priority */ static void LowerOwnPriority() { ZLOGIF(setpriority(PRIO_PROCESS, 0, ZEROVM_PRIORITY) != 0, "cannot lower zerovm priority"); }
/* put zerovm in a "jail" */ static void ChrootJail() { ZLOGS(LOG_DEBUG, "'chrooting' zerovm to %s", NEW_ROOT); ZLOGIF(chdir(NEW_ROOT) != 0, "cannot 'chdir' zerovm"); ZLOGIF(chroot(NEW_ROOT) != 0, "cannot 'chroot' zerovm"); }