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