* If Nix is not running as root, call the setuid helper to start the
builder under the desired build user.
This commit is contained in:
		
							parent
							
								
									813a7c65c9
								
							
						
					
					
						commit
						a45c498e4e
					
				
					 2 changed files with 41 additions and 26 deletions
				
			
		|  | @ -1342,11 +1342,6 @@ void DerivationGoal::startBuilder() | |||
| 
 | ||||
|             initChild(); | ||||
| 
 | ||||
|             /* Fill in the arguments. */ | ||||
|             Strings args(drv.args); | ||||
|             args.push_front(baseNameOf(drv.builder)); | ||||
|             const char * * argArr = strings2CharPtrs(args); | ||||
| 
 | ||||
|             /* Fill in the environment. */ | ||||
|             Strings envStrs; | ||||
|             for (Environment::const_iterator i = env.begin(); | ||||
|  | @ -1354,32 +1349,53 @@ void DerivationGoal::startBuilder() | |||
|                 envStrs.push_back(i->first + "=" + i->second); | ||||
|             const char * * envArr = strings2CharPtrs(envStrs); | ||||
| 
 | ||||
|             Path program = drv.builder.c_str(); | ||||
|             std::vector<const char *> args; /* careful with c_str()! */ | ||||
|              | ||||
|             /* If we are running in `build-users' mode, then switch to
 | ||||
|                the user we allocated above.  Make sure that we drop | ||||
|                all root privileges.  Note that initChild() above has | ||||
|                closed all file descriptors except std*, so that's | ||||
|                safe.  Also note that setuid() when run as root sets | ||||
|                the real, effective and saved UIDs. */ | ||||
|             if (buildUser.getUID() != 0) { | ||||
|             if (buildUser.enabled()) { | ||||
|                 printMsg(lvlInfo, format("switching to uid `%1%'") % buildUser.getUID()); | ||||
| 
 | ||||
|                 if (setgroups(0, 0) == -1) | ||||
|                     throw SysError("cannot clear the set of supplementary groups"); | ||||
|                 if (amPrivileged()) { | ||||
|                      | ||||
|                 if (setgid(buildUser.getGID()) == -1 || | ||||
|                     getgid() != buildUser.getGID() || | ||||
|                     getegid() != buildUser.getGID()) | ||||
|                     throw SysError("setgid failed"); | ||||
|                     if (setgroups(0, 0) == -1) | ||||
|                         throw SysError("cannot clear the set of supplementary groups"); | ||||
|                  | ||||
|                 if (setuid(buildUser.getUID()) == -1 || | ||||
|                     getuid() != buildUser.getUID() || | ||||
|                     geteuid() != buildUser.getUID()) | ||||
|                     throw SysError("setuid failed"); | ||||
|                     if (setgid(buildUser.getGID()) == -1 || | ||||
|                         getgid() != buildUser.getGID() || | ||||
|                         getegid() != buildUser.getGID()) | ||||
|                         throw SysError("setgid failed"); | ||||
| 
 | ||||
|                     if (setuid(buildUser.getUID()) == -1 || | ||||
|                         getuid() != buildUser.getUID() || | ||||
|                         geteuid() != buildUser.getUID()) | ||||
|                         throw SysError("setuid failed"); | ||||
|                      | ||||
|                 } else { | ||||
|                     /* Let the setuid helper take care of it. */ | ||||
|                     program = nixLibexecDir + "/nix-setuid-helper"; | ||||
|                     args.push_back(program.c_str()); | ||||
|                     args.push_back("run-builder"); | ||||
|                     args.push_back("nix-builder-1"); /* !!! TODO */ | ||||
|                     args.push_back(drv.builder.c_str()); | ||||
|                 } | ||||
|             } | ||||
|              | ||||
|             /* Fill in the arguments. */ | ||||
|             string builderBasename = baseNameOf(drv.builder); | ||||
|             args.push_back(builderBasename.c_str()); | ||||
|             for (Strings::iterator i = drv.args.begin(); | ||||
|                  i != drv.args.end(); ++i) | ||||
|                 args.push_back(i->c_str()); | ||||
|             args.push_back(0); | ||||
| 
 | ||||
|             /* Execute the program.  This should not return. */ | ||||
|             execve(drv.builder.c_str(), | ||||
|                 (char * *) argArr, (char * *) envArr); | ||||
|             execve(program.c_str(), (char * *) &args[0], (char * *) envArr); | ||||
| 
 | ||||
|             throw SysError(format("executing `%1%'") | ||||
|                 % drv.builder); | ||||
|  | @ -1484,7 +1500,7 @@ void DerivationGoal::computeClosure() | |||
|            build.  Also, the output should be owned by the build | ||||
|            user. */ | ||||
|         if ((st.st_mode & (S_IWGRP | S_IWOTH)) || | ||||
|             (buildUser.getUID() != 0 && st.st_uid != buildUser.getUID())) | ||||
|             (buildUser.enabled() && st.st_uid != buildUser.getUID())) | ||||
|             throw Error(format("suspicious ownership or permission on `%1%'; rejecting this build output") % path); | ||||
| #endif | ||||
| 
 | ||||
|  |  | |||
|  | @ -57,7 +57,7 @@ static uid_t nameToUid(const string & userName) | |||
|    user. */ | ||||
| static void runBuilder(uid_t uidNix, | ||||
|     const string & buildUsersGroup, const string & targetUser, | ||||
|     string program, int argc, char * * argv) | ||||
|     string program, int argc, char * * argv, char * * env) | ||||
| { | ||||
|     uid_t uidTargetUser = nameToUid(targetUser); | ||||
| 
 | ||||
|  | @ -107,12 +107,11 @@ static void runBuilder(uid_t uidNix, | |||
| 
 | ||||
|     /* Execute the program. */ | ||||
|     std::vector<const char *> args; | ||||
|     args.push_back(program.c_str()); | ||||
|     for (int i = 0; i < argc; ++i) | ||||
|         args.push_back(argv[i]); | ||||
|     args.push_back(0); | ||||
|      | ||||
|     if (execve(program.c_str(), (char * *) &args[0], 0) == -1) | ||||
|     if (execve(program.c_str(), (char * *) &args[0], env) == -1) | ||||
|         throw SysError(format("cannot execute `%1%'") % program); | ||||
| } | ||||
| 
 | ||||
|  | @ -180,10 +179,10 @@ static void run(int argc, char * * argv) | |||
| 
 | ||||
|     if (command == "run-builder") { | ||||
|         /* Syntax: nix-setuid-helper run-builder <username> <program>
 | ||||
|              <args...> */ | ||||
|              <arg0 arg1...> */ | ||||
|         if (argc < 4) throw Error("missing user name / program name"); | ||||
|         runBuilder(uidNix, buildUsersGroup, | ||||
|             argv[2], argv[3], argc - 4, argv + 4); | ||||
|             argv[2], argv[3], argc - 4, argv + 4, oldEnviron); | ||||
|     } | ||||
| 
 | ||||
|     else if (command == "fix-ownership") { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue