Commit d9d3dc7a authored by Andrei Vagin's avatar Andrei Vagin Committed by Pavel Emelyanov

criu: check whether tcp_repair can be enabled for half-closed sockets

Originally the repair mode could be enable only for sockets
in closed and established states. Starting with the 4.10 kernel,
it is possible to enable the repair mode for all connected sockets
and now we can dump syn-sent and half closed sockets.

travis-ci: success for series starting with [01/21] build: install libnet-dev
Signed-off-by: 's avatarAndrei Vagin <avagin@virtuozzo.com>
Signed-off-by: 's avatarPavel Emelyanov <xemul@virtuozzo.com>
parent aec9eb92
...@@ -921,6 +921,22 @@ static int check_cgroupns(void) ...@@ -921,6 +921,22 @@ static int check_cgroupns(void)
return 0; return 0;
} }
static int check_tcp_halt_closed(void)
{
int ret;
ret = kerndat_tcp_repair();
if (ret < 0)
return -1;
if (!kdat.has_tcp_half_closed) {
pr_err("TCP_REPAIR can't be enabled for half-closed sockets\n");
return -1;
}
return 0;
}
static int check_tcp_window(void) static int check_tcp_window(void)
{ {
int ret; int ret;
...@@ -1037,6 +1053,7 @@ int cr_check(void) ...@@ -1037,6 +1053,7 @@ int cr_check(void)
ret |= check_clone_parent_vs_pid(); ret |= check_clone_parent_vs_pid();
ret |= check_cgroupns(); ret |= check_cgroupns();
ret |= check_tcp_window(); ret |= check_tcp_window();
ret |= check_tcp_halt_closed();
} }
/* /*
...@@ -1116,6 +1133,7 @@ static struct feature_list feature_list[] = { ...@@ -1116,6 +1133,7 @@ static struct feature_list feature_list[] = {
{ "loginuid", check_loginuid }, { "loginuid", check_loginuid },
{ "cgroupns", check_cgroupns }, { "cgroupns", check_cgroupns },
{ "autofs", check_autofs }, { "autofs", check_autofs },
{ "tcp_half_closed", check_tcp_halt_closed },
{ NULL, NULL }, { NULL, NULL },
}; };
......
...@@ -36,6 +36,7 @@ struct kerndat_s { ...@@ -36,6 +36,7 @@ struct kerndat_s {
enum pagemap_func pmap; enum pagemap_func pmap;
unsigned int has_xtlocks; unsigned int has_xtlocks;
unsigned long mmap_min_addr; unsigned long mmap_min_addr;
bool has_tcp_half_closed;
}; };
extern struct kerndat_s kdat; extern struct kerndat_s kdat;
...@@ -57,5 +58,6 @@ enum { ...@@ -57,5 +58,6 @@ enum {
extern int kerndat_fs_virtualized(unsigned int which, u32 kdev); extern int kerndat_fs_virtualized(unsigned int which, u32 kdev);
extern int kerndat_tcp_repair_window(); extern int kerndat_tcp_repair_window();
extern int kerndat_tcp_repair();
#endif /* __CR_KERNDAT_H__ */ #endif /* __CR_KERNDAT_H__ */
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
#include <sys/sysmacros.h> #include <sys/sysmacros.h>
#include <sys/sysmacros.h> #include <sys/sysmacros.h>
#include <stdint.h> #include <stdint.h>
#include <sys/socket.h>
#include <arpa/inet.h> /* for sockaddr_in and inet_ntoa() */
#include "int.h" #include "int.h"
#include "log.h" #include "log.h"
...@@ -25,6 +27,7 @@ ...@@ -25,6 +27,7 @@
#include "proc_parse.h" #include "proc_parse.h"
#include "config.h" #include "config.h"
#include "syscall-codes.h" #include "syscall-codes.h"
#include "sk-inet.h"
struct kerndat_s kdat = { struct kerndat_s kdat = {
}; };
...@@ -491,6 +494,69 @@ static int kerndat_iptables_has_xtlocks(void) ...@@ -491,6 +494,69 @@ static int kerndat_iptables_has_xtlocks(void)
return 0; return 0;
} }
int kerndat_tcp_repair(void)
{
int sock, clnt = -1, yes = 1, exit_code = -1;
struct sockaddr_in addr;
socklen_t aux;
memset(&addr,0,sizeof(addr));
addr.sin_family = AF_INET;
inet_pton(AF_INET, "127.0.0.1", &(addr.sin_addr));
addr.sin_port = 0;
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock < 0) {
pr_perror("Unable to create a socket");
return -1;
}
if (bind(sock, (struct sockaddr *) &addr, sizeof(addr))) {
pr_perror("Unable to bind a socket");
goto err;
}
aux = sizeof(addr);
if (getsockname(sock, (struct sockaddr *) &addr, &aux)) {
pr_perror("Unable to get a socket name");
goto err;
}
if (listen(sock, 1)) {
pr_perror("Unable to listen a socket");
goto err;
}
clnt = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (clnt < 0) {
pr_perror("Unable to create a socket");
goto err;
}
if (connect(clnt, (struct sockaddr *) &addr, sizeof(addr))) {
pr_perror("Unable to connect a socket");
goto err;
}
if (shutdown(clnt, SHUT_WR)) {
pr_perror("Unable to shutdown a socket");
goto err;
}
if (setsockopt(clnt, SOL_TCP, TCP_REPAIR, &yes, sizeof(yes))) {
if (errno != EPERM)
goto err;
kdat.has_tcp_half_closed = false;
} else
kdat.has_tcp_half_closed = true;
exit_code = 0;
err:
close_safe(&clnt);
close(sock);
return exit_code;
}
int kerndat_init(void) int kerndat_init(void)
{ {
int ret; int ret;
...@@ -516,6 +582,8 @@ int kerndat_init(void) ...@@ -516,6 +582,8 @@ int kerndat_init(void)
ret = kerndat_iptables_has_xtlocks(); ret = kerndat_iptables_has_xtlocks();
if (!ret) if (!ret)
ret = kerndat_tcp_repair_window(); ret = kerndat_tcp_repair_window();
if (!ret)
ret = kerndat_tcp_repair();
kerndat_lsm(); kerndat_lsm();
kerndat_mmap_min_addr(); kerndat_mmap_min_addr();
...@@ -548,6 +616,8 @@ int kerndat_init_rst(void) ...@@ -548,6 +616,8 @@ int kerndat_init_rst(void)
ret = kerndat_iptables_has_xtlocks(); ret = kerndat_iptables_has_xtlocks();
if (!ret) if (!ret)
ret = kerndat_tcp_repair_window(); ret = kerndat_tcp_repair_window();
if (!ret)
ret = kerndat_tcp_repair();
kerndat_lsm(); kerndat_lsm();
kerndat_mmap_min_addr(); kerndat_mmap_min_addr();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment