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

Added option to use network namespace when connecting to parasite #82

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 57 additions & 3 deletions memcr.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ struct vm_area {

static char *dump_dir;
static char *parasite_socket_dir;
static int parasite_socket_use_netns;
static int no_wait;
static int proc_mem;
static int rss_file;
Expand Down Expand Up @@ -591,16 +592,62 @@ static int unseize_target(void)
return ret;
}

static int parasite_socket_create(pid_t pid)
{
int pid_netns = -1;
int cur_netns = -1;
char netns_path[64];
int cd;

if (parasite_socket_use_netns) {
/* get both current and parasite network namespaces */
snprintf(netns_path, sizeof(netns_path), "/proc/%d/ns/net", pid);
pid_netns = open(netns_path, O_CLOEXEC | O_RDONLY);
if (pid_netns < 0) {
fprintf(stderr, "open('%s', ) failed: %m\n", netns_path);
} else {
cur_netns = open("/proc/self/ns/net", O_CLOEXEC | O_RDONLY);
if (cur_netns < 0) {
fprintf(stderr, "open('/proc/self/ns/net', ) failed: %m\n");
close(pid_netns);
pid_netns = -1;
}
}

/* switch to network namespace of parasite if available */
if (pid_netns >= 0) {
if (setns(pid_netns, CLONE_NEWNET) != 0) {
fprintf(stderr, "setns() failed: %m\n");
}
close(pid_netns);
}
}

cd = socket(PF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
if (cd < 0) {
fprintf(stderr, "socket() failed: %m\n");
}

/* restore original network namespace if available */
if (cur_netns >= 0) {
if (setns(cur_netns, CLONE_NEWNET) != 0) {
fprintf(stderr, "setns() failed: %m\n");
}
close(cur_netns);
}

return cd;
}

static int parasite_connect(pid_t pid)
{
int cd;
struct sockaddr_un addr;
int ret;
int cnt = 0;

cd = socket(PF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0);
cd = parasite_socket_create(pid);
if (cd < 0) {
fprintf(stderr, "socket() failed: %m\n");
return -1;
}

Expand Down Expand Up @@ -2743,6 +2790,8 @@ static void usage(const char *name, int status)
" -d --dir dir where memory dump is stored (defaults to /tmp)\n" \
" -S --parasite-socket-dir dir where socket to communicate with parasite is created\n" \
" (abstract socket will be used if no path specified)\n" \
" -N --parasite-socket-netns use network namespace of parasite when connecting to socket\n" \
" (useful if parasite is running in a container with netns)\n" \
" -l --listen work as a service waiting for requests on a socket\n" \
" -l PORT: TCP port number to listen for requests on\n" \
" -l PATH: filesystem path for UNIX domain socket file (will be created)\n" \
Expand Down Expand Up @@ -2783,6 +2832,7 @@ int main(int argc, char *argv[])
{ "pid", 1, NULL, 'p'},
{ "dir", 1, NULL, 'd'},
{ "parasite-socket-dir", 1, NULL, 'S'},
{ "parasite-socket-netns", 0, NULL, 'N'},
{ "listen", 1, NULL, 'l'},
{ "no-wait", 0, NULL, 'n'},
{ "proc-mem", 0, NULL, 'm'},
Expand All @@ -2795,8 +2845,9 @@ int main(int argc, char *argv[])

dump_dir = "/tmp";
parasite_socket_dir = NULL;
parasite_socket_use_netns = 0;

while ((opt = getopt_long(argc, argv, "hp:d:S:l:nmfzce::", long_options, &option_index)) != -1) {
while ((opt = getopt_long(argc, argv, "hp:d:S:Nl:nmfzce::", long_options, &option_index)) != -1) {
switch (opt) {
case 'h':
usage(argv[0], 0);
Expand All @@ -2810,6 +2861,9 @@ int main(int argc, char *argv[])
case 'S':
parasite_socket_dir = optarg;
break;
case 'N':
parasite_socket_use_netns = 1;
break;
case 'l':
listen_location = optarg;
service = 1;
Expand Down