Commit f3b730d0 authored by Andrew Vagin's avatar Andrew Vagin Committed by Pavel Emelyanov

kerndat: check the TCP_REPAIR_WINDOW option

It's a new option to get/set window parameters.

v2: don't do this check to unprivileged users, because TCP_REPAIR
    is protected by CAP_NET_ADMIN.
Signed-off-by: 's avatarAndrew Vagin <avagin@virtuozzo.com>
Signed-off-by: 's avatarPavel Emelyanov <xemul@virtuozzo.com>
parent 488fc072
...@@ -13,7 +13,7 @@ ifeq ($(call pkg-config-check,libselinux),y) ...@@ -13,7 +13,7 @@ ifeq ($(call pkg-config-check,libselinux),y)
endif endif
FEATURES_LIST := TCP_REPAIR STRLCPY STRLCAT PTRACE_PEEKSIGINFO \ FEATURES_LIST := TCP_REPAIR STRLCPY STRLCAT PTRACE_PEEKSIGINFO \
SETPROCTITLE_INIT MEMFD SETPROCTITLE_INIT MEMFD TCP_REPAIR_WINDOW
# $1 - config name # $1 - config name
define gen-feature-test define gen-feature-test
......
...@@ -917,6 +917,22 @@ static int check_cgroupns(void) ...@@ -917,6 +917,22 @@ static int check_cgroupns(void)
return 0; return 0;
} }
static int check_tcp_window(void)
{
int ret;
ret = kerndat_tcp_repair_window();
if (ret < 0)
return -1;
if (!kdat.has_tcp_window) {
pr_err("The TCP_REPAIR_WINDOW option isn't supported.\n");
return -1;
}
return 0;
}
static int (*chk_feature)(void); static int (*chk_feature)(void);
/* /*
...@@ -1014,6 +1030,7 @@ int cr_check(void) ...@@ -1014,6 +1030,7 @@ int cr_check(void)
ret |= check_fdinfo_lock(); ret |= check_fdinfo_lock();
ret |= check_clone_parent_vs_pid(); ret |= check_clone_parent_vs_pid();
ret |= check_cgroupns(); ret |= check_cgroupns();
ret |= check_tcp_window();
} }
/* /*
......
...@@ -31,6 +31,7 @@ struct kerndat_s { ...@@ -31,6 +31,7 @@ struct kerndat_s {
bool has_dirty_track; bool has_dirty_track;
bool has_memfd; bool has_memfd;
bool has_fdinfo_lock; bool has_fdinfo_lock;
bool has_tcp_window;
unsigned long task_size; unsigned long task_size;
bool ipv6; bool ipv6;
bool has_loginuid; bool has_loginuid;
...@@ -56,4 +57,6 @@ enum { ...@@ -56,4 +57,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();
#endif /* __CR_KERNDAT_H__ */ #endif /* __CR_KERNDAT_H__ */
...@@ -472,6 +472,8 @@ int kerndat_init(void) ...@@ -472,6 +472,8 @@ int kerndat_init(void)
ret = kerndat_loginuid(true); ret = kerndat_loginuid(true);
if (!ret) if (!ret)
ret = kerndat_iptables_has_xtlocks(); ret = kerndat_iptables_has_xtlocks();
if (!ret)
ret = kerndat_tcp_repair_window();
kerndat_lsm(); kerndat_lsm();
...@@ -501,6 +503,8 @@ int kerndat_init_rst(void) ...@@ -501,6 +503,8 @@ int kerndat_init_rst(void)
ret = kerndat_loginuid(false); ret = kerndat_loginuid(false);
if (!ret) if (!ret)
ret = kerndat_iptables_has_xtlocks(); ret = kerndat_iptables_has_xtlocks();
if (!ret)
ret = kerndat_tcp_repair_window();
kerndat_lsm(); kerndat_lsm();
......
...@@ -33,6 +33,17 @@ ...@@ -33,6 +33,17 @@
#define SIOCOUTQNSD 0x894B #define SIOCOUTQNSD 0x894B
#endif #endif
#ifndef CONFIG_HAS_TCP_REPAIR_WINDOW
struct tcp_repair_window {
u32 snd_wl1;
u32 snd_wnd;
u32 max_window;
u32 rcv_wnd;
u32 rcv_wup;
};
#endif
#ifndef CONFIG_HAS_TCP_REPAIR #ifndef CONFIG_HAS_TCP_REPAIR
/* /*
* It's been reported that both tcp_repair_opt * It's been reported that both tcp_repair_opt
...@@ -58,6 +69,10 @@ enum { ...@@ -58,6 +69,10 @@ enum {
#define TCP_TIMESTAMP 24 #define TCP_TIMESTAMP 24
#endif #endif
#ifndef TCP_REPAIR_WINDOW
#define TCP_REPAIR_WINDOW 29
#endif
#ifndef TCPOPT_SACK_PERM #ifndef TCPOPT_SACK_PERM
#define TCPOPT_SACK_PERM TCPOPT_SACK_PERMITTED #define TCPOPT_SACK_PERM TCPOPT_SACK_PERMITTED
#endif #endif
...@@ -751,3 +766,41 @@ out: ...@@ -751,3 +766,41 @@ out:
return ret; return ret;
} }
int kerndat_tcp_repair_window()
{
struct tcp_repair_window opt;
socklen_t optlen = sizeof(opt);
int sk, val = 1;
sk = socket(AF_INET, SOCK_STREAM, 0);
if (sk < 0) {
pr_perror("Unable to create a netlink socket");
return -1;
}
if (setsockopt(sk, SOL_TCP, TCP_REPAIR, &val, sizeof(val))) {
if (errno == EPERM) {
kdat.has_tcp_window = false;
pr_warn("TCP_REPAIR isn't available to unprivileged users\n");
return 0;
}
pr_perror("Unable to set TCP_REPAIR");
close(sk);
return -1;
}
if (getsockopt(sk, SOL_TCP, TCP_REPAIR_WINDOW, &opt, &optlen)) {
if (errno != ENOPROTOOPT) {
pr_perror("Unable to set TCP_REPAIR_WINDOW");
close(sk);
return -1;
}
kdat.has_tcp_window = false;
} else
kdat.has_tcp_window = true;
close(sk);
return 0;
}
...@@ -12,6 +12,20 @@ int main(void) ...@@ -12,6 +12,20 @@ int main(void)
} }
endef endef
define FEATURE_TEST_TCP_REPAIR_WINDOW
#include <netinet/tcp.h>
int main(void)
{
struct tcp_repair_window opts;
opts.snd_wl1 = 0;
return opts.snd_wl1;
}
endef
define FEATURE_TEST_LIBBSD_DEV define FEATURE_TEST_LIBBSD_DEV
#include <bsd/string.h> #include <bsd/string.h>
......
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