Update the cwd for log_subcmds too.
Fixes a problem for intercept_method=trace when running a relative command from a different directory than what sudo ws started from. GitHub issue #194
This commit is contained in:
@@ -361,34 +361,36 @@ bad:
|
|||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
intercept_check_policy(const char *command, int argc, char **argv, int envc,
|
intercept_check_policy(const char *command, int argc, char **argv, int envc,
|
||||||
char **envp, const char *runcwd, void *v)
|
char **envp, const char *runcwd, int *oldcwd, void *v)
|
||||||
{
|
{
|
||||||
struct intercept_closure *closure = v;
|
struct intercept_closure *closure = v;
|
||||||
char **command_info = NULL;
|
char **command_info = NULL;
|
||||||
char **command_info_copy = NULL;
|
char **command_info_copy = NULL;
|
||||||
char **user_env_out = NULL;
|
char **user_env_out = NULL;
|
||||||
char **run_argv = NULL;
|
char **run_argv = NULL;
|
||||||
bool ret = true;
|
|
||||||
int i, rc, saved_dir = -1;
|
int i, rc, saved_dir = -1;
|
||||||
|
bool ret = true;
|
||||||
|
struct stat sb;
|
||||||
debug_decl(intercept_check_policy, SUDO_DEBUG_EXEC);
|
debug_decl(intercept_check_policy, SUDO_DEBUG_EXEC);
|
||||||
|
|
||||||
if (ISSET(closure->details->flags, CD_INTERCEPT)) {
|
/* Change to runcwd before the policy check if necessary. */
|
||||||
/* Change to runcwd for the policy check if necessary. */
|
if (*command != '/') {
|
||||||
if (*command != '/') {
|
if (runcwd == NULL || (saved_dir = open(".", O_RDONLY)) == -1 ||
|
||||||
if (runcwd == NULL || (saved_dir = open(".", O_RDONLY)) == -1 ||
|
chdir(runcwd) == -1) {
|
||||||
chdir(runcwd) == -1) {
|
if (runcwd == NULL) {
|
||||||
if (runcwd == NULL) {
|
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
||||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
|
"relative command path but no runcwd specified");
|
||||||
"relative command path but no runcwd specified");
|
} else if (saved_dir == -1) {
|
||||||
} else if (saved_dir == -1) {
|
sudo_debug_printf(
|
||||||
sudo_debug_printf(
|
SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
|
||||||
SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
|
"unable to open current directory for reading");
|
||||||
"unable to open current directory for reading");
|
} else {
|
||||||
} else {
|
sudo_debug_printf(
|
||||||
sudo_debug_printf(
|
SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
|
||||||
SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO|SUDO_DEBUG_ERRNO,
|
"unable to chdir for %s", runcwd);
|
||||||
"unable to chdir for %s", runcwd);
|
}
|
||||||
}
|
if (ISSET(closure->details->flags, CD_INTERCEPT)) {
|
||||||
|
/* Inability to change cwd is fatal in intercept mode. */
|
||||||
if (closure->errstr == NULL)
|
if (closure->errstr == NULL)
|
||||||
closure->errstr = N_("command rejected by policy");
|
closure->errstr = N_("command rejected by policy");
|
||||||
audit_reject(policy_plugin.name, SUDO_POLICY_PLUGIN,
|
audit_reject(policy_plugin.name, SUDO_POLICY_PLUGIN,
|
||||||
@@ -397,7 +399,19 @@ intercept_check_policy(const char *command, int argc, char **argv, int envc,
|
|||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Short-circuit the policy check if the command doesn't exist.
|
||||||
|
* Otherwise, both sudo and the shell will report the error.
|
||||||
|
*/
|
||||||
|
if (stat(command, &sb) == -1) {
|
||||||
|
closure->errstr = NULL;
|
||||||
|
closure->state = POLICY_REJECT;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ISSET(closure->details->flags, CD_INTERCEPT)) {
|
||||||
/* We don't currently have a good way to validate the environment. */
|
/* We don't currently have a good way to validate the environment. */
|
||||||
sudo_debug_set_active_instance(policy_plugin.debug_instance);
|
sudo_debug_set_active_instance(policy_plugin.debug_instance);
|
||||||
rc = policy_plugin.u.policy->check_policy(argc, argv, NULL,
|
rc = policy_plugin.u.policy->check_policy(argc, argv, NULL,
|
||||||
@@ -504,6 +518,14 @@ oom:
|
|||||||
closure->errstr = N_("unable to allocate memory");
|
closure->errstr = N_("unable to allocate memory");
|
||||||
|
|
||||||
bad:
|
bad:
|
||||||
|
if (saved_dir != -1) {
|
||||||
|
if (fchdir(saved_dir) == -1) {
|
||||||
|
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
|
||||||
|
"%s: unable to restore saved cwd", __func__);
|
||||||
|
}
|
||||||
|
close(saved_dir);
|
||||||
|
saved_dir = -1;
|
||||||
|
}
|
||||||
if (closure->errstr == NULL)
|
if (closure->errstr == NULL)
|
||||||
closure->errstr = N_("policy plugin error");
|
closure->errstr = N_("policy plugin error");
|
||||||
audit_error(policy_plugin.name, SUDO_POLICY_PLUGIN, closure->errstr,
|
audit_error(policy_plugin.name, SUDO_POLICY_PLUGIN, closure->errstr,
|
||||||
@@ -512,20 +534,13 @@ bad:
|
|||||||
ret = false;
|
ret = false;
|
||||||
|
|
||||||
done:
|
done:
|
||||||
if (saved_dir != -1) {
|
|
||||||
if (fchdir(saved_dir) == -1) {
|
|
||||||
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
|
|
||||||
"%s: unable to restore saved cwd", __func__);
|
|
||||||
}
|
|
||||||
close(saved_dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (command_info_copy != NULL) {
|
if (command_info_copy != NULL) {
|
||||||
for (i = 0; command_info_copy[i] != NULL; i++) {
|
for (i = 0; command_info_copy[i] != NULL; i++) {
|
||||||
free(command_info_copy[i]);
|
free(command_info_copy[i]);
|
||||||
}
|
}
|
||||||
free(command_info_copy);
|
free(command_info_copy);
|
||||||
}
|
}
|
||||||
|
*oldcwd = saved_dir;
|
||||||
|
|
||||||
debug_return_bool(ret);
|
debug_return_bool(ret);
|
||||||
}
|
}
|
||||||
@@ -536,6 +551,7 @@ intercept_check_policy_req(PolicyCheckRequest *req,
|
|||||||
{
|
{
|
||||||
char **argv = NULL;
|
char **argv = NULL;
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
|
int oldcwd = -1;
|
||||||
size_t n;
|
size_t n;
|
||||||
debug_decl(intercept_check_policy_req, SUDO_DEBUG_EXEC);
|
debug_decl(intercept_check_policy_req, SUDO_DEBUG_EXEC);
|
||||||
|
|
||||||
@@ -573,9 +589,17 @@ intercept_check_policy_req(PolicyCheckRequest *req,
|
|||||||
argv[n] = NULL;
|
argv[n] = NULL;
|
||||||
|
|
||||||
ret = intercept_check_policy(req->command, req->n_argv, argv, req->n_envp,
|
ret = intercept_check_policy(req->command, req->n_argv, argv, req->n_envp,
|
||||||
req->envp, req->cwd, closure);
|
req->envp, req->cwd, &oldcwd, closure);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
if (oldcwd != -1) {
|
||||||
|
if (fchdir(oldcwd) == -1) {
|
||||||
|
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
|
||||||
|
"%s: unable to restore saved cwd", __func__);
|
||||||
|
}
|
||||||
|
close(oldcwd);
|
||||||
|
}
|
||||||
|
|
||||||
free(argv);
|
free(argv);
|
||||||
|
|
||||||
debug_return_bool(ret);
|
debug_return_bool(ret);
|
||||||
|
@@ -50,6 +50,6 @@ struct intercept_closure {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void intercept_closure_reset(struct intercept_closure *closure);
|
void intercept_closure_reset(struct intercept_closure *closure);
|
||||||
bool intercept_check_policy(const char *command, int argc, char **argv, int envc, char **envp, const char *runcwd, void *closure);
|
bool intercept_check_policy(const char *command, int argc, char **argv, int envc, char **envp, const char *runcwd, int *oldcwd, void *closure);
|
||||||
|
|
||||||
#endif /* SUDO_EXEC_INTERCEPT_H */
|
#endif /* SUDO_EXEC_INTERCEPT_H */
|
||||||
|
@@ -1697,8 +1697,7 @@ ptrace_intercept_execve(pid_t pid, struct intercept_closure *closure)
|
|||||||
char cwd[PATH_MAX];
|
char cwd[PATH_MAX];
|
||||||
unsigned long msg;
|
unsigned long msg;
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
struct stat sb;
|
int i, oldcwd = -1;
|
||||||
int i;
|
|
||||||
debug_decl(ptrace_intercept_execve, SUDO_DEBUG_EXEC);
|
debug_decl(ptrace_intercept_execve, SUDO_DEBUG_EXEC);
|
||||||
|
|
||||||
/* Do not check the policy if we are executing the initial command. */
|
/* Do not check the policy if we are executing the initial command. */
|
||||||
@@ -1783,16 +1782,6 @@ ptrace_intercept_execve(pid_t pid, struct intercept_closure *closure)
|
|||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Short-circuit the policy check if the command doesn't exist.
|
|
||||||
* Otherwise, both sudo and the shell will report the error.
|
|
||||||
*/
|
|
||||||
if (stat(pathname, &sb) == -1) {
|
|
||||||
ptrace_fail_syscall(pid, ®s, errno);
|
|
||||||
ret = true;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We can only pass the pathname to exececute via argv[0] (plugin API). */
|
/* We can only pass the pathname to exececute via argv[0] (plugin API). */
|
||||||
argv[0] = pathname;
|
argv[0] = pathname;
|
||||||
if (argc == 0) {
|
if (argc == 0) {
|
||||||
@@ -1806,8 +1795,9 @@ ptrace_intercept_execve(pid_t pid, struct intercept_closure *closure)
|
|||||||
sudo_debug_printf(SUDO_DEBUG_INFO, "%s: %d: checking policy for %s",
|
sudo_debug_printf(SUDO_DEBUG_INFO, "%s: %d: checking policy for %s",
|
||||||
__func__, (int)pid, pathname);
|
__func__, (int)pid, pathname);
|
||||||
if (!intercept_check_policy(pathname, argc, argv, envc, envp, cwd,
|
if (!intercept_check_policy(pathname, argc, argv, envc, envp, cwd,
|
||||||
closure)) {
|
&oldcwd, closure)) {
|
||||||
sudo_warnx("%s", U_(closure->errstr));
|
if (closure->errstr != NULL)
|
||||||
|
sudo_warnx("%s", U_(closure->errstr));
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (closure->state) {
|
switch (closure->state) {
|
||||||
@@ -1939,6 +1929,13 @@ ptrace_intercept_execve(pid_t pid, struct intercept_closure *closure)
|
|||||||
ret = true;
|
ret = true;
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
if (oldcwd != -1) {
|
||||||
|
if (fchdir(oldcwd) == -1) {
|
||||||
|
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO,
|
||||||
|
"%s: unable to restore saved cwd", __func__);
|
||||||
|
}
|
||||||
|
close(oldcwd);
|
||||||
|
}
|
||||||
free(buf);
|
free(buf);
|
||||||
intercept_closure_reset(closure);
|
intercept_closure_reset(closure);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user