doos 1.1.0: limits, hardening, pasta, signatures, Debian image
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
+50
-2
@@ -18,14 +18,16 @@ namespace doos {
|
||||
|
||||
NetMode Network::parse(const std::string& s) {
|
||||
if (s == "slirp") return NetMode::Slirp;
|
||||
if (s == "pasta") return NetMode::Pasta;
|
||||
if (s == "host") return NetMode::Host;
|
||||
if (s == "none") return NetMode::None;
|
||||
throw std::runtime_error("unknown network mode '" + s + "' (use slirp, host or none)");
|
||||
throw std::runtime_error("unknown network mode '" + s + "' (use slirp, pasta, host or none)");
|
||||
}
|
||||
|
||||
std::string Network::name(NetMode m) {
|
||||
switch (m) {
|
||||
case NetMode::Slirp: return "slirp";
|
||||
case NetMode::Pasta: return "pasta";
|
||||
case NetMode::Host: return "host";
|
||||
case NetMode::None: return "none";
|
||||
}
|
||||
@@ -36,8 +38,10 @@ std::string Network::resolvConf(NetMode m) {
|
||||
switch (m) {
|
||||
case NetMode::Slirp: return "nameserver " + std::string(spec::kSlirpDns) + "\n";
|
||||
case NetMode::None: return "";
|
||||
case NetMode::Pasta:
|
||||
case NetMode::Host: {
|
||||
// Host netns is shared, so the host resolver config is valid. Stub on 127.0.0.53 works too.
|
||||
// pasta forwards the namespace's loopback to the host and host mode shares it, so the host resolver
|
||||
// config is valid as is, including the 127.0.0.53 stub.
|
||||
std::ifstream in("/etc/resolv.conf");
|
||||
return std::string(std::istreambuf_iterator<char>(in), {});
|
||||
}
|
||||
@@ -84,3 +88,47 @@ void SlirpSession::stop() {
|
||||
}
|
||||
|
||||
} // namespace doos
|
||||
|
||||
namespace doos {
|
||||
|
||||
void PastaSession::start(pid_t targetPid) {
|
||||
pid_ = ::fork();
|
||||
if (pid_ < 0) throw SysError("fork pasta");
|
||||
if (pid_ == 0) {
|
||||
::prctl(PR_SET_PDEATHSIG, SIGKILL);
|
||||
int nul = ::open("/dev/null", O_WRONLY);
|
||||
if (nul >= 0) { ::dup2(nul, 1); ::dup2(nul, 2); }
|
||||
std::string target = std::to_string(targetPid);
|
||||
::execlp("pasta", "pasta", "--foreground", "--quiet", "--config-net", target.c_str(), static_cast<char*>(nullptr));
|
||||
::_exit(127);
|
||||
}
|
||||
// pasta has no ready fd: wait until the target namespace has an interface besides lo.
|
||||
std::string dev = "/proc/" + std::to_string(targetPid) + "/net/dev";
|
||||
for (int waited = 0; waited < spec::kNetReadyTimeoutMs; waited += 20) {
|
||||
int st = 0;
|
||||
if (::waitpid(pid_, &st, WNOHANG) == pid_) {
|
||||
pid_ = -1;
|
||||
throw std::runtime_error("pasta exited early (is it installed and permitted?)");
|
||||
}
|
||||
std::ifstream in(dev);
|
||||
int lines = 0;
|
||||
for (std::string line; std::getline(in, line);) ++lines;
|
||||
if (lines > 3) return; // two header lines + lo + at least one more interface
|
||||
::poll(nullptr, 0, 20);
|
||||
}
|
||||
stop();
|
||||
throw std::runtime_error("pasta not ready in time");
|
||||
}
|
||||
|
||||
void PastaSession::stop() {
|
||||
if (pid_ <= 0) return;
|
||||
// pasta drops to another uid after start, so we cannot signal it, and it leaves by itself shortly after its
|
||||
// namespace is gone. Reap it if it is already done; otherwise let init adopt it instead of blocking the exit.
|
||||
for (int waited = 0; waited < 20; waited += 5) {
|
||||
if (::waitpid(pid_, nullptr, WNOHANG) == pid_) break;
|
||||
::poll(nullptr, 0, 5);
|
||||
}
|
||||
pid_ = -1;
|
||||
}
|
||||
|
||||
} // namespace doos
|
||||
|
||||
Reference in New Issue
Block a user