runProgram: support gid, uid, chdir
This commit is contained in:
		
							parent
							
								
									dde8eeb39a
								
							
						
					
					
						commit
						b4a05edbfe
					
				
					 3 changed files with 30 additions and 22 deletions
				
			
		|  | @ -465,26 +465,22 @@ void handleDiffHook(bool allowVfork, uid_t uid, uid_t gid, Path tryA, Path tryB, | ||||||
| { | { | ||||||
|     auto diffHook = settings.diffHook; |     auto diffHook = settings.diffHook; | ||||||
|     if (diffHook != "" && settings.runDiffHook) { |     if (diffHook != "" && settings.runDiffHook) { | ||||||
|         auto wrapper = [&]() { |         try { | ||||||
|             if (chdir("/") == -1) |             RunOptions diffHookOptions(diffHook,{tryA, tryB, drvPath, tmpDir}); | ||||||
|                 throw SysError("chdir / failed"); |             diffHookOptions.searchPath = true; | ||||||
|             if (setgid(gid) == -1) |             diffHookOptions.uid = uid; | ||||||
|                 throw SysError("setgid failed"); |             diffHookOptions.gid = gid; | ||||||
|             if (setgroups(0, 0) == -1) |             diffHookOptions.chdir = "/"; | ||||||
|                 throw SysError("setgroups failed"); |  | ||||||
|             if (setuid(uid) == -1) |  | ||||||
|                 throw SysError("setuid failed"); |  | ||||||
| 
 | 
 | ||||||
|             try { |             auto diffRes = runProgram(diffHookOptions); | ||||||
|                 auto diff = runProgram(diffHook, true, {tryA, tryB, drvPath, tmpDir}); |             if (!statusOk(diffRes.first)) | ||||||
|                 if (diff != "") |                 throw ExecError(diffRes.first, fmt("diff-hook program '%1%' %2%", diffHook, statusToString(diffRes.first))); | ||||||
|                     printError(chomp(diff)); |  | ||||||
|             } catch (Error & error) { |  | ||||||
|                 printError("diff hook execution failed: %s", error.what()); |  | ||||||
|             } |  | ||||||
|         }; |  | ||||||
| 
 | 
 | ||||||
|         doFork(allowVfork, wrapper); |             if (diffRes.second != "") | ||||||
|  |                 printError(chomp(diffRes.second)); | ||||||
|  |         } catch (Error & error) { | ||||||
|  |             printError("diff hook execution failed: %s", error.what()); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -16,6 +16,7 @@ | ||||||
| #include <future> | #include <future> | ||||||
| 
 | 
 | ||||||
| #include <fcntl.h> | #include <fcntl.h> | ||||||
|  | #include <grp.h> | ||||||
| #include <limits.h> | #include <limits.h> | ||||||
| #include <pwd.h> | #include <pwd.h> | ||||||
| #include <sys/ioctl.h> | #include <sys/ioctl.h> | ||||||
|  | @ -914,8 +915,8 @@ void killUser(uid_t uid) | ||||||
| 
 | 
 | ||||||
| /* Wrapper around vfork to prevent the child process from clobbering
 | /* Wrapper around vfork to prevent the child process from clobbering
 | ||||||
|    the caller's stack frame in the parent. */ |    the caller's stack frame in the parent. */ | ||||||
| pid_t doFork(bool allowVfork, std::function<void()> fun) __attribute__((noinline)); | static pid_t doFork(bool allowVfork, std::function<void()> fun) __attribute__((noinline)); | ||||||
| pid_t doFork(bool allowVfork, std::function<void()> fun) | static pid_t doFork(bool allowVfork, std::function<void()> fun) | ||||||
| { | { | ||||||
| #ifdef __linux__ | #ifdef __linux__ | ||||||
|     pid_t pid = allowVfork ? vfork() : fork(); |     pid_t pid = allowVfork ? vfork() : fork(); | ||||||
|  | @ -1025,6 +1026,16 @@ void runProgram2(const RunOptions & options) | ||||||
|         if (source && dup2(in.readSide.get(), STDIN_FILENO) == -1) |         if (source && dup2(in.readSide.get(), STDIN_FILENO) == -1) | ||||||
|             throw SysError("dupping stdin"); |             throw SysError("dupping stdin"); | ||||||
| 
 | 
 | ||||||
|  |         //if (options.chdir && chdir((*options.chdir).c_str()) == -1)
 | ||||||
|  |         //    throw SysError("chdir failed");
 | ||||||
|  |         if (options.gid && setgid(*options.gid) == -1) | ||||||
|  |             throw SysError("setgid failed"); | ||||||
|  |         /* Drop all other groups if we're setgid. */ | ||||||
|  |         if (options.gid && setgroups(0, 0) == -1) | ||||||
|  |             throw SysError("setgroups failed"); | ||||||
|  |         if (options.uid && setuid(*options.uid) == -1) | ||||||
|  |             throw SysError("setuid failed"); | ||||||
|  | 
 | ||||||
|         Strings args_(options.args); |         Strings args_(options.args); | ||||||
|         args_.push_front(options.program); |         args_.push_front(options.program); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -265,10 +265,11 @@ string runProgram(Path program, bool searchPath = false, | ||||||
|     const Strings & args = Strings(), |     const Strings & args = Strings(), | ||||||
|     const std::optional<std::string> & input = {}); |     const std::optional<std::string> & input = {}); | ||||||
| 
 | 
 | ||||||
| pid_t doFork(bool allowVfork, std::function<void()> fun); |  | ||||||
| 
 |  | ||||||
| struct RunOptions | struct RunOptions | ||||||
| { | { | ||||||
|  |     std::optional<uid_t> uid; | ||||||
|  |     std::optional<uid_t> gid; | ||||||
|  |     std::optional<Path> chdir; | ||||||
|     Path program; |     Path program; | ||||||
|     bool searchPath = true; |     bool searchPath = true; | ||||||
|     Strings args; |     Strings args; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue