Skip to content

Adds support for nested directories#293

Open
msutovsky-r7 wants to merge 1 commit intorapid7:masterfrom
msutovsky-r7:feat/stdapi/mkdir/nested_dirs
Open

Adds support for nested directories#293
msutovsky-r7 wants to merge 1 commit intorapid7:masterfrom
msutovsky-r7:feat/stdapi/mkdir/nested_dirs

Conversation

@msutovsky-r7
Copy link
Contributor

Fixes mkdir inconsistency. This address the inconsistency between mkdir among Meterpreter and other types of sessions.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds “mkdir -p” style behavior to Meterpreter’s mettle stdapi filesystem mkdir handler to align directory creation semantics with other session types.

Changes:

  • Updates fs_mkdir to attempt creation of intermediate path components when given a nested directory path.
  • Switches mkdir handling from a single eio_mkdir call to manual path splitting + per-component existence checks/creation.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +556 to +571
path_dup = strdup(path);

eio_mkdir(path, 0777, 0, fs_cb, ctx);
// take into account null byte at the end of path and the one we add in sprintf
base_dir = malloc(strlen(path_dup)+2);
tmp = malloc(strlen(path_dup)+2);
dir = strtok(path_dup, "/");

//address absolute paths — check original path since strtok modifies path_dup
if (path[0] == '/')
{
sprintf(base_dir, "/%s/", dir);
}
else
{
sprintf(base_dir, "%s/", dir);
}
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fs_mkdir doesn’t validate allocation/tokenization results: strdup()/malloc() can return NULL, and strtok() returns NULL for inputs like "" or "/" (or all-slash paths). In those cases the subsequent sprintf(base_dir, ... , dir) dereferences a NULL dir and will crash. Add checks for allocation failures and for dir == NULL before formatting, and return an appropriate error code (e.g., TLV_RESULT_ENOMEM / TLV_RESULT_EINVAL) instead of proceeding.

Copilot uses AI. Check for mistakes.
Comment on lines +573 to +595
while(dir != NULL)
{
#ifdef _WIN32
if(stat(base_dir, &f_info) != 0)
#else
if(lstat(base_dir, &f_info) != 0)
#endif
{
eio_mkdir(base_dir, 0777, 0, NULL, NULL);
}
memset(&f_info, 0, sizeof(struct stat));
dir = strtok(NULL, "/");
if(dir != NULL)
{
sprintf(tmp, "%s%s/", base_dir, dir);
strcpy(base_dir, tmp);
}
}

struct tlv_packet *p = tlv_packet_response_result(ctx,TLV_RESULT_SUCCESS);

tlv_dispatcher_enqueue_response(ctx->td, p);
tlv_handler_ctx_free(ctx);
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fs_mkdir now enqueues a TLV_RESULT_SUCCESS response immediately and frees ctx without waiting for any mkdir operations to complete or checking their results. Additionally, each missing path component is created via eio_mkdir with a NULL callback, which both prevents error reporting and can schedule nested directory creations out-of-order (e.g., "a/b" mkdir can run before "a"), causing intermittent failures while still returning success. Consider moving the whole recursive mkdir logic into a single eio_custom worker (or chaining eio_mkdir calls with a callback) so directory creation is ordered and the response reflects the actual outcome (including EEXIST/ENOTDIR cases).

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

#mkdir is inconsistent

2 participants