Skip to content

Commit

Permalink
Mark the derivation outputs as secret if the derivation file is secret.
Browse files Browse the repository at this point in the history
  • Loading branch information
nbp committed Aug 25, 2014
1 parent 8bfcdb4 commit f4dbf8c
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 3 deletions.
7 changes: 4 additions & 3 deletions src/libstore/build.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2193,16 +2193,17 @@ void DerivationGoal::registerOutputs()

ValidPathInfos infos;

/* Inherit ownership of outputs from the permission of the derivation
file. */
SecretMode smode(getOwnerOfSecretFile(drvPath));

/* Check whether the output paths were created, and grep each
output path to determine what other paths it references. Also make all
output paths read-only. */
foreach (DerivationOutputs::iterator, i, drv.outputs) {
Path path = i->second.path;
if (missingPaths.find(path) == missingPaths.end()) continue;

// :TODO: Transfer the user name down to here.
SecretMode smode(publicUserName());

Path actualPath = path;
if (useChroot) {
actualPath = chrootRootDir + path;
Expand Down
46 changes: 46 additions & 0 deletions src/libutil/util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

#include <sys/wait.h>
#include <unistd.h>
#include <pwd.h>
#include <fcntl.h>
#include <limits.h>

Expand Down Expand Up @@ -1174,6 +1175,51 @@ const string & getCurrentUserName()
}


string getOwnerOfSecretFile(const Path & path)
{
/* Extract the uid of the file */
struct stat st;
if (stat(path.c_str(), &st) == -1)
throw SysError("statting file");

/* If the file is readable by the group, then this means this is a
public file. */
if (st.st_mode & S_IRGRP)
return publicUserName();

/* Map the uid of the private file to the user name */
struct passwd pwd;
struct passwd *ppwd;
char *buf;
size_t bufsize;
int err;

bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
if (bufsize == size_t(-1))
bufsize = 16 * 1024;

buf = new char[bufsize];
if (!buf)
throw SysError("allocating passwd entry");

err = getpwuid_r(st.st_uid, &pwd, buf, bufsize, &ppwd);
if (!ppwd) {
delete[] buf;
if (err)
throw SysError("finding owner of a file");

/* The uid does not match any user name, no need to keep any secret
for a non-existing user name. */
return publicUserName();
}

string userName(pwd.pw_name);
delete[] buf;

return userName;
}


SecretMode::SecretMode(const string & userName)
: userName_(userName),
filterMask_(0),
Expand Down
4 changes: 4 additions & 0 deletions src/libutil/util.hh
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,10 @@ const string & publicUserName();
const string & getCurrentUserName();


/* Returns the owner of a file if the file is secret */
string getOwnerOfSecretFile(const Path & path);


/* Ensure that files created within this scope are secure by default. This
RAI does not protect against doing a chmod of the file. */
class SecretMode
Expand Down
24 changes: 24 additions & 0 deletions tests/sec-secretDerivation.sh
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,32 @@ if ! test $publicDrvStat = $expected; then
exit 1
fi

expected="dr-xr-xr-x"
if ! test $publicOutStat = $expected; then
echo "Public derivation output director is not only world readbale."
exit 1
fi

expected="-r--r--r--"
if ! test $publicOutFileStat = $expected; then
echo "Public derivation output file is not only world readbale."
exit 1
fi

expected="-r--------"
if ! test $secretDrvStat = $expected; then
echo "Secret derivation is not only root readbale."
exit 1
fi

expected="dr-x------"
if ! test $secretOutStat = $expected; then
echo "Secret derivation output directory is not only root readbale."
exit 1
fi

expected="-r--------"
if ! test $secretOutFileStat = $expected; then
echo "Secret derivation output file is not only root readbale."
exit 1
fi

0 comments on commit f4dbf8c

Please sign in to comment.