* Don't run setuid root when build-users is empty.
* Send startup errors to the client.
This commit is contained in:
parent
35247c4c9f
commit
f4279bcde0
3 changed files with 54 additions and 29 deletions
|
@ -244,7 +244,7 @@ static void setuidInit()
|
||||||
could also modify the Nix executables (say, replace them by a
|
could also modify the Nix executables (say, replace them by a
|
||||||
Trojan horse), so the problem is already there. */
|
Trojan horse), so the problem is already there. */
|
||||||
|
|
||||||
#if 0 && HAVE_SETRESUID
|
#if HAVE_SETRESUID
|
||||||
if (setresuid(nixUid, nixUid, nixUid)) abort();
|
if (setresuid(nixUid, nixUid, nixUid)) abort();
|
||||||
if (setresgid(nixGid, nixGid, nixGid)) abort();
|
if (setresgid(nixGid, nixGid, nixGid)) abort();
|
||||||
#elif HAVE_SETREUID
|
#elif HAVE_SETREUID
|
||||||
|
|
|
@ -73,6 +73,7 @@ RemoteStore::RemoteStore()
|
||||||
|
|
||||||
/* Send the magic greeting, check for the reply. */
|
/* Send the magic greeting, check for the reply. */
|
||||||
try {
|
try {
|
||||||
|
processStderr();
|
||||||
writeInt(WORKER_MAGIC_1, to);
|
writeInt(WORKER_MAGIC_1, to);
|
||||||
unsigned int magic = readInt(from);
|
unsigned int magic = readInt(from);
|
||||||
if (magic != WORKER_MAGIC_2) throw Error("protocol mismatch");
|
if (magic != WORKER_MAGIC_2) throw Error("protocol mismatch");
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "serialise.hh"
|
#include "serialise.hh"
|
||||||
#include "worker-protocol.hh"
|
#include "worker-protocol.hh"
|
||||||
#include "archive.hh"
|
#include "archive.hh"
|
||||||
|
#include "globals.hh"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
@ -30,7 +31,9 @@ static PathSet readStorePaths(Source & from)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static Sink * _to; /* !!! should make writeToStderr an object */
|
static FdSource from(STDIN_FILENO);
|
||||||
|
static FdSink to(STDOUT_FILENO);
|
||||||
|
|
||||||
bool canSendStderr;
|
bool canSendStderr;
|
||||||
|
|
||||||
|
|
||||||
|
@ -40,11 +43,13 @@ bool canSendStderr;
|
||||||
socket. */
|
socket. */
|
||||||
static void tunnelStderr(const unsigned char * buf, size_t count)
|
static void tunnelStderr(const unsigned char * buf, size_t count)
|
||||||
{
|
{
|
||||||
|
if (canSendStderr)
|
||||||
|
writeFull(STDERR_FILENO, (unsigned char *) "L: ", 3);
|
||||||
writeFull(STDERR_FILENO, buf, count);
|
writeFull(STDERR_FILENO, buf, count);
|
||||||
if (canSendStderr) {
|
if (canSendStderr) {
|
||||||
try {
|
try {
|
||||||
writeInt(STDERR_NEXT, *_to);
|
writeInt(STDERR_NEXT, to);
|
||||||
writeString(string((char *) buf, count), *_to);
|
writeString(string((char *) buf, count), to);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
/* Write failed; that means that the other side is
|
/* Write failed; that means that the other side is
|
||||||
gone. */
|
gone. */
|
||||||
|
@ -118,7 +123,7 @@ static void stopWork()
|
||||||
throw SysError("ignoring SIGIO");
|
throw SysError("ignoring SIGIO");
|
||||||
|
|
||||||
canSendStderr = false;
|
canSendStderr = false;
|
||||||
writeInt(STDERR_LAST, *_to);
|
writeInt(STDERR_LAST, to);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -225,21 +230,46 @@ static void performOp(Source & from, Sink & to, unsigned int op)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void processConnection(Source & from, Sink & to)
|
static void processConnection()
|
||||||
{
|
{
|
||||||
store = boost::shared_ptr<StoreAPI>(new LocalStore(true));
|
|
||||||
|
|
||||||
unsigned int magic = readInt(from);
|
|
||||||
if (magic != WORKER_MAGIC_1) throw Error("protocol mismatch");
|
|
||||||
|
|
||||||
writeInt(WORKER_MAGIC_2, to);
|
|
||||||
|
|
||||||
debug("greeting exchanged");
|
|
||||||
|
|
||||||
_to = &to;
|
|
||||||
canSendStderr = false;
|
canSendStderr = false;
|
||||||
writeToStderr = tunnelStderr;
|
writeToStderr = tunnelStderr;
|
||||||
|
|
||||||
|
/* Allow us to receive SIGIO for events on the client socket. */
|
||||||
|
signal(SIGIO, SIG_IGN);
|
||||||
|
if (fcntl(STDIN_FILENO, F_SETOWN, getpid()) == -1)
|
||||||
|
throw SysError("F_SETOWN");
|
||||||
|
if (fcntl(STDIN_FILENO, F_SETFL, fcntl(STDIN_FILENO, F_GETFL, 0) | FASYNC) == -1)
|
||||||
|
throw SysError("F_SETFL");
|
||||||
|
|
||||||
|
/* Send startup error messages to the client. */
|
||||||
|
startWork();
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
/* Prevent users from doing something very dangerous. */
|
||||||
|
if (setuidMode && geteuid() == 0 &&
|
||||||
|
querySetting("build-users", Strings()).size() == 0)
|
||||||
|
throw Error("if you run `nix-worker' setuid root, then you MUST set `build-users'!");
|
||||||
|
|
||||||
|
/* Open the store. */
|
||||||
|
store = boost::shared_ptr<StoreAPI>(new LocalStore(true));
|
||||||
|
|
||||||
|
stopWork();
|
||||||
|
|
||||||
|
} catch (Error & e) {
|
||||||
|
writeInt(STDERR_ERROR, to);
|
||||||
|
writeString(e.msg(), to);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Exchange the greeting. */
|
||||||
|
unsigned int magic = readInt(from);
|
||||||
|
if (magic != WORKER_MAGIC_1) throw Error("protocol mismatch");
|
||||||
|
writeInt(WORKER_MAGIC_2, to);
|
||||||
|
debug("greeting exchanged");
|
||||||
|
|
||||||
|
/* Process client requests. */
|
||||||
bool quit = false;
|
bool quit = false;
|
||||||
|
|
||||||
unsigned int opCount = 0;
|
unsigned int opCount = 0;
|
||||||
|
@ -252,7 +282,7 @@ static void processConnection(Source & from, Sink & to)
|
||||||
try {
|
try {
|
||||||
performOp(from, to, op);
|
performOp(from, to, op);
|
||||||
} catch (Error & e) {
|
} catch (Error & e) {
|
||||||
writeInt(STDERR_ERROR, *_to);
|
writeInt(STDERR_ERROR, to);
|
||||||
writeString(e.msg(), to);
|
writeString(e.msg(), to);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -273,27 +303,21 @@ void run(Strings args)
|
||||||
if (arg == "--daemon") daemon = true;
|
if (arg == "--daemon") daemon = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allow us to receive SIGIO for events on the client socket. */
|
|
||||||
signal(SIGIO, SIG_IGN);
|
|
||||||
if (fcntl(STDIN_FILENO, F_SETOWN, getpid()) == -1)
|
|
||||||
throw SysError("F_SETOWN");
|
|
||||||
if (fcntl(STDIN_FILENO, F_SETFL, fcntl(STDIN_FILENO, F_GETFL, 0) | FASYNC) == -1)
|
|
||||||
throw SysError("F_SETFL");
|
|
||||||
|
|
||||||
if (slave) {
|
if (slave) {
|
||||||
FdSource source(STDIN_FILENO);
|
|
||||||
FdSink sink(STDOUT_FILENO);
|
|
||||||
|
|
||||||
/* This prevents us from receiving signals from the terminal
|
/* This prevents us from receiving signals from the terminal
|
||||||
when we're running in setuid mode. */
|
when we're running in setuid mode. */
|
||||||
if (setsid() == -1)
|
if (setsid() == -1)
|
||||||
throw SysError(format("creating a new session"));
|
throw SysError(format("creating a new session"));
|
||||||
|
|
||||||
processConnection(source, sink);
|
processConnection();
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (daemon)
|
else if (daemon) {
|
||||||
|
if (setuidMode)
|
||||||
|
throw Error("daemon cannot be started in setuid mode");
|
||||||
|
|
||||||
throw Error("daemon mode not implemented");
|
throw Error("daemon mode not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
throw Error("must be run in either --slave or --daemon mode");
|
throw Error("must be run in either --slave or --daemon mode");
|
||||||
|
|
Loading…
Reference in a new issue