Example #1
0
int internal_eqvp(CELL obj1, CELL obj2)
{
	if (AS_LITERAL(obj1) == AS_LITERAL(obj2)) {
		return 1;
	}

	if (! (IS_POINTER(obj1) && IS_POINTER(obj2)) ) {
		return 0;
	}

	TYPEID t = GET_POINTER_TYPE(obj1);
	if (t != GET_POINTER_TYPE(obj2)) {
		return 0;
	}

	switch(t) {
	case T_FLOAT:
		return GET_FLOAT(obj1) == GET_FLOAT(obj2);

	case T_BIGINT:
		return GET_BIGINT(obj1) == GET_BIGINT(obj2);

	default:
		return 0;
	}
	//FIXME - does not implement equality correctly for LAMBDAs
	//principally because LAMBDAs are not implemented correctly
	//yet either (i.e. as closures).
}
Example #2
0
bool ConstraintList::literal_matches(const T& base_expr) const {
  bool aggregate = true;
  for (size_t i = 0; i < constraints_.size(); ++i) {
    T constraint_expr = AS_LITERAL(T, constraints_[i].expr);
    if (constraints_[i].op == EQUALS) {
      aggregate = aggregate && (base_expr == constraint_expr);
    } else if (constraints_[i].op == GREATER_THAN) {
      aggregate = aggregate && (base_expr > constraint_expr);
    } else if (constraints_[i].op == LESS_THAN) {
      aggregate = aggregate && (base_expr < constraint_expr);
    } else if (constraints_[i].op == GREATER_THAN_OR_EQUALS) {
      aggregate = aggregate && (base_expr >= constraint_expr);
    } else if (constraints_[i].op == LESS_THAN_OR_EQUALS) {
      aggregate = aggregate && (base_expr <= constraint_expr);
    } else {
      // Unsupported constraint.
      return false;
    }
    if (!aggregate) {
      // Speed up comparison.
      return false;
    }
  }
  return true;
}
Example #3
0
int internal_eqp(CELL obj1, CELL obj2)
{
	if (AS_LITERAL(obj1) == AS_LITERAL(obj2)) {
		return 1;
	}

	if (! (IS_POINTER(obj1) && IS_POINTER(obj2)) ) {
		return 0;
	}

	TYPEID t = GET_POINTER_TYPE(obj1);
	if (t != GET_POINTER_TYPE(obj2)) {
		return 0;
	}

    return 0;
}
Example #4
0
bool ConstraintList::matches(const std::string& expr) const {
  // Support each SQL affinity type casting.
  if (affinity == TEXT_TYPE) {
    return literal_matches<TEXT_LITERAL>(expr);
  } else if (affinity == INTEGER_TYPE) {
    INTEGER_LITERAL lexpr = AS_LITERAL(INTEGER_LITERAL, expr);
    return literal_matches<INTEGER_LITERAL>(lexpr);
  } else if (affinity == BIGINT_TYPE) {
    BIGINT_LITERAL lexpr = AS_LITERAL(BIGINT_LITERAL, expr);
    return literal_matches<BIGINT_LITERAL>(lexpr);
  } else if (affinity == UNSIGNED_BIGINT_TYPE) {
    UNSIGNED_BIGINT_LITERAL lexpr = AS_LITERAL(UNSIGNED_BIGINT_LITERAL, expr);
    return literal_matches<UNSIGNED_BIGINT_LITERAL>(lexpr);
  } else {
    // Unsupported affinity type.
    return false;
  }
}
Example #5
0
SimpleProcStat getProcStat(const std::string& pid) {
  SimpleProcStat stat;
  std::string content;
  if (readFile(getProcAttr("stat", pid), content).ok()) {
    auto detail_start = content.find_last_of(")");
    // Start parsing stats from ") <MODE>..."
    auto details = osquery::split(content.substr(detail_start + 2), " ");
    stat.state = details.at(0);
    stat.parent = details.at(1);
    stat.group = details.at(2);
    stat.user_time = details.at(11);
    stat.system_time = details.at(12);
    stat.nice = details.at(16);
    stat.start_time = TEXT(AS_LITERAL(BIGINT_LITERAL, details.at(19)) / 100);
  }

  if (readFile(getProcAttr("status", pid), content).ok()) {
    for (const auto& line : osquery::split(content, "\n")) {
      // Status lines are formatted: Key: Value....\n.
      auto detail = osquery::split(line, ":", 1);
      if (detail.size() != 2) {
        continue;
      }

      // There are specific fields from each detail.
      if (detail.at(0) == "Name") {
        stat.name = detail.at(1);
      } else if (detail.at(0) == "VmRSS") {
        detail[1].erase(detail.at(1).end() - 3, detail.at(1).end());
        // Memory is reported in kB.
        stat.resident_size = detail.at(1) + "000";
      } else if (detail.at(0) == "VmSize") {
        detail[1].erase(detail.at(1).end() - 3, detail.at(1).end());
        // Memory is reported in kB.
        stat.phys_footprint = detail.at(1) + "000";
      } else if (detail.at(0) == "Gid") {
        // Format is: R E - -
        auto gid_detail = osquery::split(detail.at(1), "\t");
        if (gid_detail.size() == 4) {
          stat.real_gid = gid_detail.at(0);
          stat.effective_gid = gid_detail.at(1);
        }
      } else if (detail.at(0) == "Uid") {
        auto uid_detail = osquery::split(detail.at(1), "\t");
        if (uid_detail.size() == 4) {
          stat.real_uid = uid_detail.at(0);
          stat.effective_uid = uid_detail.at(1);
        }
      }
    }
  }

  return stat;
}
Example #6
0
void Config::recordQueryPerformance(const std::string& name,
                                    size_t delay,
                                    size_t size,
                                    const Row& r0,
                                    const Row& r1) {
  RecursiveLock lock(config_performance_mutex_);
  if (performance_.count(name) == 0) {
    performance_[name] = QueryPerformance();
  }

  // Grab access to the non-const schedule item.
  auto& query = performance_.at(name);
  BIGINT_LITERAL diff = 0;
  if (!r1.at("user_time").empty() && !r0.at("user_time").empty()) {
    diff = AS_LITERAL(BIGINT_LITERAL, r1.at("user_time")) -
           AS_LITERAL(BIGINT_LITERAL, r0.at("user_time"));
    if (diff > 0) {
      query.user_time += diff;
    }
  }

  if (!r1.at("system_time").empty() && !r0.at("system_time").empty()) {
    diff = AS_LITERAL(BIGINT_LITERAL, r1.at("system_time")) -
           AS_LITERAL(BIGINT_LITERAL, r0.at("system_time"));
    if (diff > 0) {
      query.system_time += diff;
    }
  }

  if (!r1.at("resident_size").empty() && !r0.at("resident_size").empty()) {
    diff = AS_LITERAL(BIGINT_LITERAL, r1.at("resident_size")) -
           AS_LITERAL(BIGINT_LITERAL, r0.at("resident_size"));
    if (diff > 0) {
      // Memory is stored as an average of RSS changes between query executions.
      query.average_memory = (query.average_memory * query.executions) + diff;
      query.average_memory = (query.average_memory / (query.executions + 1));
    }
  }

  query.wall_time += delay;
  query.output_size += size;
  query.executions += 1;
  query.last_executed = getUnixTime();

  // Clear the executing query (remove the dirty bit).
  setDatabaseValue(kPersistentSettings, kExecutingQuery, "");
}
Example #7
0
void Config::recordQueryPerformance(const std::string& name,
                                    size_t delay,
                                    size_t size,
                                    const Row& r0,
                                    const Row& r1) {
  // Grab a lock on the schedule structure and check the name.
  ConfigDataInstance config;
  if (config.schedule().count(name) == 0) {
    // Unknown query schedule name.
    return;
  }

  // Grab access to the non-const schedule item.
  auto& query = getInstance().data_.schedule.at(name);
  auto diff = AS_LITERAL(BIGINT_LITERAL, r1.at("user_time")) -
              AS_LITERAL(BIGINT_LITERAL, r0.at("user_time"));
  if (diff > 0) {
    query.user_time += diff;
  }

  diff = AS_LITERAL(BIGINT_LITERAL, r1.at("system_time")) -
         AS_LITERAL(BIGINT_LITERAL, r0.at("system_time"));
  if (diff > 0) {
    query.system_time += diff;
  }

  diff = AS_LITERAL(BIGINT_LITERAL, r1.at("resident_size")) -
         AS_LITERAL(BIGINT_LITERAL, r0.at("resident_size"));
  if (diff > 0) {
    // Memory is stored as an average of RSS changes between query executions.
    query.average_memory = (query.average_memory * query.executions) + diff;
    query.average_memory = (query.average_memory / (query.executions + 1));
  }

  query.wall_time += delay;
  query.output_size += size;
  query.executions += 1;
}
Example #8
0
int internal_equalp(CELL obj1, CELL obj2)
{
	while(1) {
		if (AS_LITERAL(obj1) == AS_LITERAL(obj2)) {
			return 1;
		}

		if (! (IS_POINTER(obj1) && IS_POINTER(obj2)) ) {
			return 0;
		}

		if (GET_POINTER_TYPE(obj1) != GET_POINTER_TYPE(obj2)) {
			return 0;
		}

		switch(GET_POINTER_TYPE(obj1)) {
		case T_CONS:
            // FIXME - unbounded recursion!
			if (!internal_equalp(CAR(obj1), CAR(obj2))) {
				return 0;
			}
			obj1 = CDR(obj1);
			obj2 = CDR(obj2);
			break;

		case T_VECTOR:
		case T_RECORD:
			{
				VECTOR * const vec1 = GET_VECTOR(obj1);
				VECTOR * const vec2 = GET_VECTOR(obj2);
				if (vec1->len != vec2->len) {
					return 0;
				}
				int i;
				for(i = 0; i < vec1->len; ++i) {
                    // FIXME - unbounded recursion!
					if (!internal_equalp(vec1->data[i], vec2->data[i])) {
						return 0;
					}
				}
				return 1;
			}

		case T_STRING:
			{
				STRING * const p1 = GET_STRING(obj1);
				STRING * const p2 = GET_STRING(obj2);
				return p1->len == p2->len && 0 == memcmp(p1->data, p2->data, p1->len);
			}

        case T_FLOAT:
            return GET_FLOAT(obj1) == GET_FLOAT(obj2);

        case T_BIGINT:
            return GET_BIGINT(obj1) == GET_BIGINT(obj2);

        default:
            return 0;
        }
	}
}
Example #9
0
bool WatcherRunner::isChildSane(const PlatformProcess& child) const {
  auto rows =
      SQL::selectAllFrom("processes", "pid", EQUALS, INTEGER(child.pid()));
  if (rows.size() == 0) {
    // Could not find worker process?
    return false;
  }

  // Get the performance state for the worker or extension.
  size_t sustained_latency = 0;
  // Compare CPU utilization since last check.
  size_t footprint = 0;
  pid_t parent = 0;
  // IV is the check interval in seconds, and utilization is set per-second.
  auto iv = std::max(getWorkerLimit(INTERVAL), (size_t)1);

  {
    WatcherLocker locker;
    auto& state = Watcher::getState(child);
    UNSIGNED_BIGINT_LITERAL user_time = 0, system_time = 0;
    try {
      parent = AS_LITERAL(BIGINT_LITERAL, rows[0].at("parent"));
      user_time = AS_LITERAL(BIGINT_LITERAL, rows[0].at("user_time")) / iv;
      system_time = AS_LITERAL(BIGINT_LITERAL, rows[0].at("system_time")) / iv;
      footprint = AS_LITERAL(BIGINT_LITERAL, rows[0].at("resident_size"));
    } catch (const std::exception& e) {
      state.sustained_latency = 0;
    }

    // Check the difference of CPU time used since last check.
    if (user_time - state.user_time > getWorkerLimit(UTILIZATION_LIMIT) ||
        system_time - state.system_time > getWorkerLimit(UTILIZATION_LIMIT)) {
      state.sustained_latency++;
    } else {
      state.sustained_latency = 0;
    }
    // Update the current CPU time.
    state.user_time = user_time;
    state.system_time = system_time;

    // Check if the sustained difference exceeded the acceptable latency limit.
    sustained_latency = state.sustained_latency;

    // Set the memory footprint as the amount of resident bytes allocated
    // since the process image was created (estimate).
    // A more-meaningful check would limit this to writable regions.
    if (state.initial_footprint == 0) {
      state.initial_footprint = footprint;
    }

    // Set the measured/limit-applied footprint to the post-launch allocations.
    if (footprint < state.initial_footprint) {
      footprint = 0;
    } else {
      footprint = footprint - state.initial_footprint;
    }
  }

  // Only make a decision about the child sanity if it is still the watcher's
  // child. It's possible for the child to die, and its pid reused.
  if (parent != PlatformProcess::getCurrentProcess()->pid()) {
    // The child's parent is not the watcher.
    Watcher::reset(child);
    // Do not stop or call the child insane, since it is not our child.
    return true;
  }

  if (sustained_latency > 0 &&
      sustained_latency * iv >= getWorkerLimit(LATENCY_LIMIT)) {
    LOG(WARNING) << "osqueryd worker (" << child.pid()
                 << ") system performance limits exceeded";
    return false;
  }
  // Check if the private memory exceeds a memory limit.
  if (footprint > 0 && footprint > getWorkerLimit(MEMORY_LIMIT) * 1024 * 1024) {
    LOG(WARNING) << "osqueryd worker (" << child.pid()
                 << ") memory limits exceeded: " << footprint;
    return false;
  }

  // The worker is sane, no action needed.
  // Attempt to flush status logs to the well-behaved worker.
  if (use_worker_) {
    relayStatusLogs();
  }

  return true;
}
Example #10
0
void internal_generic_output(FILE* fp, CELL cell, int strict, int tab)
{
	switch(GET_TYPE(cell)) {
	case T_VOID:
		fputs("#<void>", fp);
		break;

	case T_NULL:
		fputs("()", fp);
		break;

	case T_UNDEFINED:
		fputs("#<undefined>", fp);
		break;

	case T_EMPTY:
		fputs("#<empty>", fp);
		break;

	case T_BOOL:
		fputs(GET_BOOL(cell) ? "#t" : "#f", fp);
		break;

	case T_CHAR:
		{
			CHAR ch = GET_CHAR(cell);
			if (strict) {
				switch(ch) {
				case ' ':  fputs("#\\space",     fp); break;
				case 0:    fputs("#\\nul",       fp); break;
				case 27:   fputs("#\\escape",    fp); break;
				case 127:  fputs("#\\rubout",    fp); break;
				case '\a': fputs("#\\alarm",     fp); break;
				case '\b': fputs("#\\backspace", fp); break;
				case '\f': fputs("#\\page",      fp); break;
				case '\n': fputs("#\\newline",   fp); break;
				case '\r': fputs("#\\return",    fp); break;
				case '\t': fputs("#\\tab",       fp); break;
				case '\v': fputs("#\\vtab",      fp); break;
				default:   fprintf(fp, "#\\%c", ch); break;
				}
			}
			else {
				fputc(ch, fp);
			}
		}
		break;

	case T_INT:
		fprintf(fp, "%d", GET_INT(cell));
		break;

    case T_BIGINT:
        fprintf(fp, "%lld", GET_BIGINT(cell));
        break;

	case T_FLOAT:
		fprintf(fp, "%f", GET_FLOAT(cell));
		break;

	case T_STRING:
		{
			STRING* p = GET_STRING(cell);
			size_t len = p->len;
			char* data = p->data;
			if (strict) {
				// FIXME -- make this more efficient, and escape other special chars?
				fputc('"', fp);
				while(len--) {
					char ch = *data++;
					if (ch == '"' || ch == '\\') {
						fputc('\\', fp);
					}
					fputc(ch, fp);
				}
				fputc('"', fp);
			}
			else {
				fwrite(data, 1, len, fp);
			}
		}
		break;

	case T_NAME:
		{
			NAME* p = GET_NAME(cell);
			if (p->gensym) {
				fprintf(fp, "#_%d", p->gensym);
			}
			else {
				fwrite(GET_NAME(cell)->data, 1, GET_NAME(cell)->len, fp);
			}
		}
		break;

	case T_KEYWORD:
		{
			KEYWORD* p = GET_KEYWORD(cell);
            fwrite(p->data, 1, p->len, fp);
            fputc(':', fp);
		}
		break;

	case T_SLOT:
		fprintf(fp, "#<slot:%d>", GET_SLOT(cell));
		break;

    // FIXME - arbitrary recursion
	case T_CONS:
		fputc('(', fp);
		if (tab) ++tab;
		int did = 0;
		while(1) {
			int pair = CONSP(CAR(cell));
			if (!did && tab && pair && !CONSP(CAR(CAR(cell)))) { fprintf(fp, "\n%*s", (tab-1)*2, ""); }
			internal_generic_output(fp, CAR(cell), strict, tab);
			cell = CDR(cell);
			if (NULLP(cell)) {
				break;
			}
			did = (tab && pair);
			if (did) { fprintf(fp, "\n%*s", (tab-1)*2, ""); }
			else fputc(' ', fp);
			if (!CONSP(cell)) {
				fputs(". ", fp);
				internal_generic_output(fp, cell, strict, tab);
				break;
			}
		}
		fputc(')', fp);
		break;

    // FIXME - arbitrary recursion
	case T_VECTOR:
		{
			VECTOR *vec = GET_VECTOR(cell);
			fputs("#(", fp);
			if (vec->len > 0) {
				int i = 0;
				internal_generic_output(fp, vec->data[i++], strict, tab);
				while(i < vec->len) {
					fputc(' ', fp);
					internal_generic_output(fp, vec->data[i++], strict, tab);
				}
			}
			fputc(')', fp);
			break;
		}

	case T_FUNC:
		fprintf(fp, "#<primitive:%s>", GET_FUNC(cell)->name);
		break;

	case T_COMPILED_LAMBDA:
		fprintf(fp, "#<compiled-lambda:0x%08x>", AS_LITERAL(cell));
		break;
		{
			if (tab) ++tab;
			COMPILED_LAMBDA *l = GET_COMPILED_LAMBDA(cell);
			fprintf(fp, "#<%s %d%s:%d/%d",
					l->is_macro ? "macro" : "lambda",
					l->argc, l->rest ? "+" : "",
					l->depth,
					l->max_slot);

			if (tab) { fprintf(fp, "\n%*s", (tab-1)*2, ""); }
			else { fputc(' ', fp); }

			internal_generic_output(fp, l->body, strict, tab);
			fputc('>', fp);
		}
		break;
		
	case T_CLOSURE:
		fprintf(fp, "#<closure:0x%08x>", AS_LITERAL(cell));
		break;
		{
			if (tab) ++tab;
			CLOSURE *c = GET_CLOSURE(cell);
			fprintf(fp, "#<closure ");
			if (tab) { fprintf(fp, "\n%*s", (tab-1)*2, ""); }
			internal_print_env(fp, c->env);
			if (tab) { fprintf(fp, "\n%*s", (tab-1)*2, ""); }
			fputc(' ', fp);
			internal_generic_output(fp, c->compiled_lambda, strict, tab);
			fputc('>', fp);
		}
		break;

	case T_EXCEPTION:
		fputs("#<exception:", fp);
		fwrite(GET_EXCEPTION(cell)->data, 1, GET_EXCEPTION(cell)->len, fp);
		fputc('>', fp);
		break;

	case T_REIFIED_CONTINUATION:
		fprintf(fp, "#<continuation:0x%08x>", (int)GET_REIFIED_CONTINUATION(cell)->cont);
		break;

	case T_STACK_FRAME:
		{
			STACK_FRAME* p = GET_STACK_FRAME(cell);
			fputs("#<stack-frame [", fp);
			int i;
			for(i = 0; i < p->len; ++i) {
				if (i) fputc(' ', fp);
				fprintf(fp, "0x%08x", (int)p->cells[i]);
			}
			fputs("]>", fp);
		}
		break;

	case T_ENV:
		fprintf(fp, "#<env:count=%d>", GET_ENV(cell)->count);
		break;

	case T_RELOC:
		fprintf(fp, "#<reloc:0x%08x>", (int)GET_RELOC(cell));
		break;

    case T_PORT:
        fprintf(fp, "#<port:%s>", GET_PORT(cell)->data);
        break;

    case T_DB_CONNECTION:
        fprintf(fp, "#<db-connection>");
        break;

    case T_DB_RESULT:
        fprintf(fp, "#<db-result>");
        break;

    case T_RECORD:
        fprintf(fp, "#<record>");
        break;

	default:
		fprintf(fp, "#<%s-%02x:%08x>",
			IS_LITERAL(cell) ? "literal" : "pointer",
			GET_TYPE(cell),
			AS_LITERAL(cell)
		);
		break;
	}
}