Update runcwd in command_info[] before passing it to the audit plugin.

Since sudoers does rejected commands itself the runcwd will still
not be correct for those.
This commit is contained in:
Todd C. Miller
2021-08-27 15:58:19 -06:00
parent 22de92b0da
commit 168d5c47c9
5 changed files with 97 additions and 51 deletions

View File

@@ -94,6 +94,7 @@ struct _PolicyCheckRequest
{ {
ProtobufCMessage base; ProtobufCMessage base;
char *command; char *command;
char *cwd;
size_t n_argv; size_t n_argv;
char **argv; char **argv;
size_t n_envp; size_t n_envp;
@@ -103,7 +104,7 @@ struct _PolicyCheckRequest
}; };
#define POLICY_CHECK_REQUEST__INIT \ #define POLICY_CHECK_REQUEST__INIT \
{ PROTOBUF_C_MESSAGE_INIT (&policy_check_request__descriptor) \ { PROTOBUF_C_MESSAGE_INIT (&policy_check_request__descriptor) \
, (char *)protobuf_c_empty_string, 0,NULL, 0,NULL, 0, 0 } , (char *)protobuf_c_empty_string, (char *)protobuf_c_empty_string, 0,NULL, 0,NULL, 0, 0 }
struct _PolicyAcceptMessage struct _PolicyAcceptMessage

View File

@@ -203,45 +203,76 @@ bad:
} }
/* /*
* Allocate a new command_info[] and update the command in it. * Allocate a new command_info[] and update command and runcwd in it.
* Only allocates new space for command_info[] itseld and the new command. * Fills in cmnd_out with a copy of the command if not NULL.
* Stores a pointer to the new command in the tofree parameter. * Returns the new command_info[] which the caller must free.
*/ */
static char ** static char **
update_command_info(char * const *old_command_info, const char *cmnd, update_command_info(char * const *old_command_info, const char *cmnd,
char **tofree) const char *runcwd, char **cmnd_out)
{ {
char **command_info; char **command_info;
char *tmp_command = NULL; char * const *oci;
size_t n; size_t n;
debug_decl(update_command_info, SUDO_DEBUG_EXEC); debug_decl(update_command_info, SUDO_DEBUG_EXEC);
/* Rebuild command_info[] with new command. */ /* Rebuild command_info[] with new command and add a runcwd. */
for (n = 0; old_command_info[n] != NULL; n++) for (n = 0; old_command_info[n] != NULL; n++)
continue; continue;
command_info = reallocarray(NULL, n + 1, sizeof(char *)); command_info = reallocarray(NULL, n + 2, sizeof(char *));
if (command_info == NULL) { if (command_info == NULL) {
goto bad; goto bad;
} }
for (n = 0; old_command_info[n] != NULL; n++) { for (oci = old_command_info, n = 0; *oci != NULL; oci++) {
const char *cp = old_command_info[n]; const char *cp = *oci;
switch (*cp) {
case 'c':
if (strncmp(cp, "command=", sizeof("command=") - 1) == 0) { if (strncmp(cp, "command=", sizeof("command=") - 1) == 0) {
if (tmp_command != NULL) if (cmnd != NULL) {
continue; command_info[n] = sudo_new_key_val("command", cmnd);
tmp_command = sudo_new_key_val("command", cmnd); if (command_info[n] == NULL) {
if (tmp_command == NULL) {
goto bad; goto bad;
} }
cp = tmp_command; n++;
continue;
} else if (cmnd_out != NULL) {
*cmnd_out = strdup(cp + sizeof("command=") - 1);
if (*cmnd_out == NULL) {
goto bad;
} }
command_info[n] = (char *)cp;
} }
}
break;
case 'r':
if (strncmp(cp, "runcwd=", sizeof("runcwd=") - 1) == 0) {
/* Filled in at the end. */
continue;
}
break;
}
command_info[n] = strdup(cp);
if (command_info[n] == NULL) {
goto bad;
}
n++;
}
/* Append actual runcwd. */
command_info[n] = sudo_new_key_val("runcwd", runcwd);
if (command_info[n] == NULL) {
goto bad;
}
n++;
command_info[n] = NULL; command_info[n] = NULL;
*tofree = tmp_command;
debug_return_ptr(command_info); debug_return_ptr(command_info);
bad: bad:
if (command_info != NULL) {
for (n = 0; command_info[n] != NULL; n++) {
free(command_info[n]);
}
free(command_info); free(command_info);
}
debug_return_ptr(NULL); debug_return_ptr(NULL);
} }
@@ -252,7 +283,6 @@ intercept_check_policy(PolicyCheckRequest *req,
char **command_info = NULL; char **command_info = NULL;
char **user_env_out = NULL; char **user_env_out = NULL;
char **argv = NULL, **run_argv = NULL; char **argv = NULL, **run_argv = NULL;
char *tofree = NULL;
bool ret = false; bool ret = false;
int result; int result;
size_t n; size_t n;
@@ -302,18 +332,13 @@ intercept_check_policy(PolicyCheckRequest *req,
switch (result) { switch (result) {
case 1: case 1:
/* Extract command path from command_info[] */ /* Rebuild command_info[] with runcwd and extract command. */
for (n = 0; command_info[n] != NULL; n++) { command_info = update_command_info(command_info, NULL,
const char *cp = command_info[n]; req->cwd ? req->cwd : "unknown", &closure->command);
if (strncmp(cp, "command=", sizeof("command=") - 1) == 0) { if (command_info == NULL) {
closure->command = strdup(cp + sizeof("command=") - 1);
if (closure->command == NULL) {
closure->errstr = N_("unable to allocate memory"); closure->errstr = N_("unable to allocate memory");
goto done; goto done;
} }
break;
}
}
closure->state = POLICY_ACCEPT; closure->state = POLICY_ACCEPT;
break; break;
case 0: case 0:
@@ -336,9 +361,9 @@ intercept_check_policy(PolicyCheckRequest *req,
goto done; goto done;
} }
/* Rebuild command_info[] with new command. */ /* Rebuild command_info[] with new command and runcwd. */
command_info = update_command_info(closure->details->info, command_info = update_command_info(closure->details->info,
req->command, &tofree); req->command, req->cwd ? req->cwd : "unknown", NULL);
if (command_info == NULL) { if (command_info == NULL) {
closure->errstr = N_("unable to allocate memory"); closure->errstr = N_("unable to allocate memory");
goto done; goto done;
@@ -415,8 +440,10 @@ done:
command_info ? command_info : closure->details->info); command_info ? command_info : closure->details->info);
closure->state = POLICY_ERROR; closure->state = POLICY_ERROR;
} }
if (!ISSET(closure->details->flags, CD_INTERCEPT)) { if (command_info != NULL) {
free(tofree); for (n = 0; command_info[n] != NULL; n++) {
free(command_info[n]);
}
free(command_info); free(command_info);
} }
free(argv); free(argv);

View File

@@ -507,7 +507,7 @@ const ProtobufCMessageDescriptor hello_response__descriptor =
(ProtobufCMessageInit) hello_response__init, (ProtobufCMessageInit) hello_response__init,
NULL,NULL,NULL /* reserved[123] */ NULL,NULL,NULL /* reserved[123] */
}; };
static const ProtobufCFieldDescriptor policy_check_request__field_descriptors[5] = static const ProtobufCFieldDescriptor policy_check_request__field_descriptors[6] =
{ {
{ {
"command", "command",
@@ -522,8 +522,20 @@ static const ProtobufCFieldDescriptor policy_check_request__field_descriptors[5]
0,NULL,NULL /* reserved1,reserved2, etc */ 0,NULL,NULL /* reserved1,reserved2, etc */
}, },
{ {
"argv", "cwd",
2, 2,
PROTOBUF_C_LABEL_NONE,
PROTOBUF_C_TYPE_STRING,
0, /* quantifier_offset */
offsetof(PolicyCheckRequest, cwd),
NULL,
&protobuf_c_empty_string,
0, /* flags */
0,NULL,NULL /* reserved1,reserved2, etc */
},
{
"argv",
3,
PROTOBUF_C_LABEL_REPEATED, PROTOBUF_C_LABEL_REPEATED,
PROTOBUF_C_TYPE_STRING, PROTOBUF_C_TYPE_STRING,
offsetof(PolicyCheckRequest, n_argv), offsetof(PolicyCheckRequest, n_argv),
@@ -535,7 +547,7 @@ static const ProtobufCFieldDescriptor policy_check_request__field_descriptors[5]
}, },
{ {
"envp", "envp",
3, 4,
PROTOBUF_C_LABEL_REPEATED, PROTOBUF_C_LABEL_REPEATED,
PROTOBUF_C_TYPE_STRING, PROTOBUF_C_TYPE_STRING,
offsetof(PolicyCheckRequest, n_envp), offsetof(PolicyCheckRequest, n_envp),
@@ -547,7 +559,7 @@ static const ProtobufCFieldDescriptor policy_check_request__field_descriptors[5]
}, },
{ {
"intercept_fd", "intercept_fd",
4, 5,
PROTOBUF_C_LABEL_NONE, PROTOBUF_C_LABEL_NONE,
PROTOBUF_C_TYPE_INT32, PROTOBUF_C_TYPE_INT32,
0, /* quantifier_offset */ 0, /* quantifier_offset */
@@ -559,7 +571,7 @@ static const ProtobufCFieldDescriptor policy_check_request__field_descriptors[5]
}, },
{ {
"secret", "secret",
5, 6,
PROTOBUF_C_LABEL_NONE, PROTOBUF_C_LABEL_NONE,
PROTOBUF_C_TYPE_FIXED64, PROTOBUF_C_TYPE_FIXED64,
0, /* quantifier_offset */ 0, /* quantifier_offset */
@@ -571,16 +583,17 @@ static const ProtobufCFieldDescriptor policy_check_request__field_descriptors[5]
}, },
}; };
static const unsigned policy_check_request__field_indices_by_name[] = { static const unsigned policy_check_request__field_indices_by_name[] = {
1, /* field[1] = argv */ 2, /* field[2] = argv */
0, /* field[0] = command */ 0, /* field[0] = command */
2, /* field[2] = envp */ 1, /* field[1] = cwd */
3, /* field[3] = intercept_fd */ 3, /* field[3] = envp */
4, /* field[4] = secret */ 4, /* field[4] = intercept_fd */
5, /* field[5] = secret */
}; };
static const ProtobufCIntRange policy_check_request__number_ranges[1 + 1] = static const ProtobufCIntRange policy_check_request__number_ranges[1 + 1] =
{ {
{ 1, 0 }, { 1, 0 },
{ 0, 5 } { 0, 6 }
}; };
const ProtobufCMessageDescriptor policy_check_request__descriptor = const ProtobufCMessageDescriptor policy_check_request__descriptor =
{ {
@@ -590,7 +603,7 @@ const ProtobufCMessageDescriptor policy_check_request__descriptor =
"PolicyCheckRequest", "PolicyCheckRequest",
"", "",
sizeof(PolicyCheckRequest), sizeof(PolicyCheckRequest),
5, 6,
policy_check_request__field_descriptors, policy_check_request__field_descriptors,
policy_check_request__field_indices_by_name, policy_check_request__field_indices_by_name,
1, policy_check_request__number_ranges, 1, policy_check_request__number_ranges,

View File

@@ -36,10 +36,11 @@ message HelloResponse {
*/ */
message PolicyCheckRequest { message PolicyCheckRequest {
string command = 1; string command = 1;
repeated string argv = 2; string cwd = 2;
repeated string envp = 3; repeated string argv = 3;
int32 intercept_fd = 4; repeated string envp = 4;
fixed64 secret = 5; int32 intercept_fd = 5;
fixed64 secret = 6;
} }
message PolicyAcceptMessage { message PolicyAcceptMessage {

View File

@@ -253,6 +253,7 @@ send_policy_check_req(int sock, const char *cmnd, char * const argv[],
{ {
InterceptRequest msg = INTERCEPT_REQUEST__INIT; InterceptRequest msg = INTERCEPT_REQUEST__INIT;
PolicyCheckRequest req = POLICY_CHECK_REQUEST__INIT; PolicyCheckRequest req = POLICY_CHECK_REQUEST__INIT;
char cwdbuf[PATH_MAX];
uint8_t *buf = NULL; uint8_t *buf = NULL;
bool ret = false; bool ret = false;
uint32_t msg_len; uint32_t msg_len;
@@ -271,6 +272,9 @@ send_policy_check_req(int sock, const char *cmnd, char * const argv[],
for (len = 0; envp[len] != NULL; len++) for (len = 0; envp[len] != NULL; len++)
continue; continue;
req.n_envp = len; req.n_envp = len;
if (getcwd(cwdbuf, sizeof(cwdbuf)) != NULL) {
req.cwd = cwdbuf;
}
msg.type_case = INTERCEPT_REQUEST__TYPE_POLICY_CHECK_REQ; msg.type_case = INTERCEPT_REQUEST__TYPE_POLICY_CHECK_REQ;
msg.u.policy_check_req = &req; msg.u.policy_check_req = &req;