Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow for detach operation from host directly into container #1094

Merged
merged 1 commit into from Oct 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
75 changes: 67 additions & 8 deletions src/ns.c
Expand Up @@ -48,6 +48,11 @@ extractMemToChildNamespace(char *inputMem, size_t inputSize, const char *outFile
return status;
}

/*
* Reassociate process identified with pid with a specific namespace described by ns.
*
* Returns TRUE if operation was success, FALSE otherwise.
*/
static bool
setNamespace(pid_t pid, const char *ns)
{
Expand All @@ -71,8 +76,13 @@ setNamespace(pid_t pid, const char *ns)
return TRUE;
}

/*
* Joins the child PID and mount namespace.
*
* Returns TRUE if operation was success, FALSE otherwise.
*/
static bool
join_namespace(pid_t hostPid)
joinNamespace(pid_t hostPid)
{
bool status = FALSE;
size_t ldscopeSize = 0;
Expand Down Expand Up @@ -219,6 +229,38 @@ nsConfigure(pid_t pid, void *scopeCfgFilterMem, size_t filterFileSize)

return EXIT_SUCCESS;
}

/*
* Check if libscope.so is loaded in specified PID
* Returns TRUE if library is loaded, FALSE otherwise.
*/
static bool
isLibScopeLoaded(pid_t pid)
{
char mapsPath[PATH_MAX] = {0};
char buffer[9076];
FILE *fd;
bool status = FALSE;

if (scope_snprintf(mapsPath, sizeof(mapsPath), "/proc/%d/maps", pid) < 0) {
return status;
}

if ((fd = scope_fopen(mapsPath, "r")) == NULL) {
return status;
}

while (scope_fgets(buffer, sizeof(buffer), fd)) {
if (scope_strstr(buffer, "libscope.so")) {
status = TRUE;
break;
}
}

scope_fclose(fd);
return status;
}


/*
* Perform fork and exec which cause that direct children
Expand All @@ -232,12 +274,30 @@ nsConfigure(pid_t pid, void *scopeCfgFilterMem, size_t filterFileSize)
* Returns status of operation
*/
int
nsForkAndExec(pid_t parentPid, pid_t nsPid)
nsForkAndExec(pid_t parentPid, pid_t nsPid, char attachType)
{
if (join_namespace(parentPid) == FALSE) {
char *opStatus = "Detach";
char *childOp = "-d";
bool libLoaded = isLibScopeLoaded(parentPid);

if (attachType == 'a') {
childOp = "-a";
opStatus = (libLoaded == FALSE) ? "Attach" : "Reattach";
} else if (libLoaded == FALSE) {
scope_fprintf(scope_stderr, "error: PID: %d has never been attached\n", parentPid);
return EXIT_FAILURE;
}
/*
* TODO In case of Reattach/Detach - when libLoaded = TRUE
* We only need the mount namespace to /dev/shm but currently ldscopedyn
* also check the pid namespace
*/

if (joinNamespace(parentPid) == FALSE) {
scope_fprintf(scope_stderr, "error: join_namespace failed\n");
return EXIT_FAILURE;
}

pid_t child = fork();
if (child < 0) {
scope_fprintf(scope_stderr, "error: fork() failed\n");
Expand All @@ -257,8 +317,7 @@ nsForkAndExec(pid_t parentPid, pid_t nsPid)
}

execArgv[execArgc++] = LDSCOPE_IN_CHILD_NS;

execArgv[execArgc++] = "-a";
execArgv[execArgc++] = childOp;
execArgv[execArgc++] = nsAttachPidStr;

return execve(LDSCOPE_IN_CHILD_NS, execArgv, environ);
Expand All @@ -269,12 +328,12 @@ nsForkAndExec(pid_t parentPid, pid_t nsPid)
if (WIFEXITED(status)) {
int exitChildStatus = WEXITSTATUS(status);
if (exitChildStatus == 0) {
scope_fprintf(scope_stderr, "Attach to process %d in child process succeeded\n", parentPid);
scope_fprintf(scope_stderr, "%s to process %d in child process succeeded\n", opStatus, parentPid);
} else {
scope_fprintf(scope_stderr, "Attach to process %d in child process failed\n", parentPid);
scope_fprintf(scope_stderr, "%s to process %d in child process failed\n", opStatus, parentPid);
}
return exitChildStatus;
}
scope_fprintf(scope_stderr, "error: attach failed() failed\n");
scope_fprintf(scope_stderr, "error: %s failed() failed\n", opStatus);
return EXIT_FAILURE;
}
2 changes: 1 addition & 1 deletion src/ns.h
Expand Up @@ -4,7 +4,7 @@
#include "scopetypes.h"

bool nsIsPidInChildNs(pid_t, pid_t *);
int nsForkAndExec(pid_t, pid_t);
int nsForkAndExec(pid_t, pid_t, char);
int nsConfigure(pid_t, void *, size_t);
service_status_t nsService(pid_t, const char *);

Expand Down
2 changes: 1 addition & 1 deletion src/scope_static.c
Expand Up @@ -786,7 +786,7 @@ main(int argc, char **argv, char **env)
scope_printf("error: --attach requires root\n");
return EXIT_FAILURE;
}
return nsForkAndExec(pid, nsAttachPid);
return nsForkAndExec(pid, nsAttachPid, attachType);
}
}

Expand Down