Temporary API to support spawn with uid and gid options
This commit is contained in:
parent
06ae804e03
commit
c42ba103b7
@ -33,6 +33,7 @@
|
||||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <pwd.h>
|
||||
#include <termios.h>
|
||||
|
||||
/* Note: May be cast to struct iovec. See writev(2). */
|
||||
@ -43,6 +44,10 @@ typedef struct {
|
||||
|
||||
typedef int uv_file;
|
||||
|
||||
/* Platform-specific definitions for uv_spawn support. */
|
||||
typedef gid_t uv_gid_t;
|
||||
typedef uid_t uv_uid_t;
|
||||
|
||||
/* Platform-specific definitions for uv_dlopen support. */
|
||||
typedef void* uv_lib_t;
|
||||
#define UV_DYNAMIC /* empty */
|
||||
|
||||
@ -137,6 +137,10 @@ typedef struct uv_buf_t {
|
||||
|
||||
typedef int uv_file;
|
||||
|
||||
/* Platform-specific definitions for uv_spawn support. */
|
||||
typedef unsigned char uv_uid_t;
|
||||
typedef unsigned char uv_gid_t;
|
||||
|
||||
/* Platform-specific definitions for uv_dlopen support. */
|
||||
typedef HMODULE uv_lib_t;
|
||||
#define UV_DYNAMIC FAR WINAPI
|
||||
|
||||
28
include/uv.h
28
include/uv.h
@ -1058,6 +1058,34 @@ struct uv_process_s {
|
||||
UV_EXTERN int uv_spawn(uv_loop_t*, uv_process_t*,
|
||||
uv_process_options_t options);
|
||||
|
||||
|
||||
/* Temporary fix for node. Do no use. */
|
||||
enum uv_process_flags {
|
||||
UV_PROCESS_SETUID = (1 << 0),
|
||||
UV_PROCESS_SETGID = (1 << 1),
|
||||
UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS = (1 << 2)
|
||||
};
|
||||
|
||||
/* Temporary fix for node. Do not use. */
|
||||
typedef struct uv_process_options2_s {
|
||||
uv_exit_cb exit_cb; /* Called after the process exits. */
|
||||
const char* file; /* Path to program to execute. */
|
||||
char** args;
|
||||
char** env;
|
||||
char* cwd;
|
||||
unsigned int flags;
|
||||
uv_pipe_t* stdin_stream;
|
||||
uv_pipe_t* stdout_stream;
|
||||
uv_pipe_t* stderr_stream;
|
||||
uv_uid_t uid;
|
||||
uv_gid_t gid;
|
||||
} uv_process_options2_t;
|
||||
|
||||
/* Temporary fix for node. Do not use. */
|
||||
UV_EXTERN int uv_spawn2(uv_loop_t*, uv_process_t*,
|
||||
uv_process_options2_t options);
|
||||
|
||||
|
||||
/*
|
||||
* Kills the process with the specified signal. The user must still
|
||||
* call uv_close on the process.
|
||||
|
||||
@ -161,8 +161,8 @@ static int uv__process_init_pipe(uv_pipe_t* handle, int fds[2], int flags) {
|
||||
# define SPAWN_WAIT_EXEC 1
|
||||
#endif
|
||||
|
||||
int uv_spawn(uv_loop_t* loop, uv_process_t* process,
|
||||
uv_process_options_t options) {
|
||||
int uv_spawn2(uv_loop_t* loop, uv_process_t* process,
|
||||
uv_process_options2_t options) {
|
||||
/*
|
||||
* Save environ in the case that we get it clobbered
|
||||
* by the child process.
|
||||
@ -179,6 +179,12 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
|
||||
pid_t pid;
|
||||
int flags;
|
||||
|
||||
assert(options.file != NULL);
|
||||
assert(!(options.flags & ~(UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS |
|
||||
UV_PROCESS_SETGID |
|
||||
UV_PROCESS_SETUID)));
|
||||
|
||||
|
||||
uv__handle_init(loop, (uv_handle_t*)process, UV_PROCESS);
|
||||
loop->counters.process_init++;
|
||||
|
||||
@ -268,6 +274,16 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
|
||||
_exit(127);
|
||||
}
|
||||
|
||||
if ((options.flags & UV_PROCESS_SETGID) && setgid(options.gid)) {
|
||||
perror("setgid()");
|
||||
_exit(127);
|
||||
}
|
||||
|
||||
if ((options.flags & UV_PROCESS_SETUID) && setuid(options.uid)) {
|
||||
perror("setuid()");
|
||||
_exit(127);
|
||||
}
|
||||
|
||||
environ = options.env;
|
||||
|
||||
execvp(options.file, options.args);
|
||||
|
||||
@ -261,3 +261,29 @@ int uv_tcp_connect6(uv_connect_t* req,
|
||||
|
||||
return uv__tcp_connect6(req, handle, address, cb);
|
||||
}
|
||||
|
||||
|
||||
/* Thunk that converts uv_process_options_t into uv_process_options2_t, */
|
||||
/* and then calls uv_spawn2. */
|
||||
int uv_spawn(uv_loop_t* loop, uv_process_t* process,
|
||||
uv_process_options_t options) {
|
||||
uv_process_options2_t options2;
|
||||
|
||||
options2.exit_cb = options.exit_cb;
|
||||
options2.file = options.file;
|
||||
options2.args = options.args;
|
||||
options2.cwd = options.cwd;
|
||||
options2.env = options.env;
|
||||
options2.stdin_stream = options.stdin_stream;
|
||||
options2.stdout_stream = options.stdout_stream;
|
||||
options2.stderr_stream = options.stderr_stream;
|
||||
|
||||
options2.flags = 0;
|
||||
if (options.windows_verbatim_arguments) {
|
||||
options2.flags |= UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS;
|
||||
}
|
||||
|
||||
/* No need to set gid and uid. */
|
||||
|
||||
return uv_spawn2(loop, process, options2);
|
||||
}
|
||||
|
||||
@ -860,8 +860,8 @@ static int duplicate_std_handle(uv_loop_t* loop, DWORD id, HANDLE* dup) {
|
||||
}
|
||||
|
||||
|
||||
int uv_spawn(uv_loop_t* loop, uv_process_t* process,
|
||||
uv_process_options_t options) {
|
||||
int uv_spawn2(uv_loop_t* loop, uv_process_t* process,
|
||||
uv_process_options2_t options) {
|
||||
int err = 0, keep_child_stdio_open = 0;
|
||||
wchar_t* path = NULL;
|
||||
int size;
|
||||
@ -872,17 +872,22 @@ int uv_spawn(uv_loop_t* loop, uv_process_t* process,
|
||||
STARTUPINFOW startup;
|
||||
PROCESS_INFORMATION info;
|
||||
|
||||
if (!options.file) {
|
||||
uv__set_artificial_error(loop, UV_EINVAL);
|
||||
if (options.flags & (UV_PROCESS_SETGID | UV_PROCESS_SETUID)) {
|
||||
uv__set_sys_error(loop, UV_ENOTSUP);
|
||||
return -1;
|
||||
}
|
||||
|
||||
assert(options.file != NULL);
|
||||
assert(!(options.flags & ~(UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS |
|
||||
UV_PROCESS_SETGID |
|
||||
UV_PROCESS_SETUID)));
|
||||
|
||||
uv_process_init(loop, process);
|
||||
|
||||
process->exit_cb = options.exit_cb;
|
||||
UTF8_TO_UTF16(options.file, application);
|
||||
arguments = options.args ? make_program_args(options.args,
|
||||
options.windows_verbatim_arguments) : NULL;
|
||||
options.flags & UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS) : NULL;
|
||||
env = options.env ? make_program_env(options.env) : NULL;
|
||||
|
||||
if (options.cwd) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user