aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nix-setuid-helper/main.cc19
1 files changed, 16 insertions, 3 deletions
diff --git a/src/nix-setuid-helper/main.cc b/src/nix-setuid-helper/main.cc
index 6fa87e372..bf70ee089 100644
--- a/src/nix-setuid-helper/main.cc
+++ b/src/nix-setuid-helper/main.cc
@@ -23,9 +23,22 @@ using namespace nix;
static void secureChown(uid_t uidFrom, uid_t uidTo, gid_t gidTo,
const Path & path)
{
- /* Recursively chown `path' to the specified uid and gid, but only
- if it is currently owned by the Nix account. */
- /* !!! */
+ struct stat st;
+ if (lstat(path.c_str(), &st) == -1)
+ throw SysError(format("statting of `%1%'") % path);
+
+ if (st.st_uid != uidFrom)
+ throw Error(format("path `%1%' owned by the wrong owner") % path);
+
+ if (lchown(path.c_str(), uidTo, gidTo) == -1)
+ throw SysError(format("changing ownership of `%1%'") % path);
+
+ if (S_ISDIR(st.st_mode)) {
+ Strings names = readDirectory(path);
+ for (Strings::iterator i = names.begin(); i != names.end(); ++i)
+ /* !!! recursion; check stack depth */
+ secureChown(uidFrom, uidTo, gidTo, path + "/" + *i);
+ }
}