[CRIU] [PATCH 1/2 v2] kerndat: check the TCP_REPAIR_WINDOW option

Andrew Vagin avagin at virtuozzo.com
Mon Jul 18 11:04:59 PDT 2016


On Thu, Jul 14, 2016 at 02:04:43PM +0300, Pavel Emelyanov wrote:
> On 07/14/2016 12:11 AM, Andrey Vagin wrote:
> > From: Andrew Vagin <avagin at virtuozzo.com>
> > 
> > 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.
> 
> This needs some kernel patches. What are these and what's their
> state (in netdev@ / in net-next / in Linus' tree)?

It's in the net-next:
http://git.kernel.org/cgit/linux/kernel/git/davem/net-next.git/commit/?id=b1ed4c4fa

> 
> > Signed-off-by: Andrew Vagin <avagin at virtuozzo.com>
> > ---
> >  criu/Makefile.config      |  2 +-
> >  criu/cr-check.c           | 17 +++++++++++++++
> >  criu/include/kerndat.h    |  3 +++
> >  criu/kerndat.c            |  4 ++++
> >  criu/sk-tcp.c             | 53 +++++++++++++++++++++++++++++++++++++++++++++++
> >  scripts/feature-tests.mak | 14 +++++++++++++
> >  6 files changed, 92 insertions(+), 1 deletion(-)
> > 
> > diff --git a/criu/Makefile.config b/criu/Makefile.config
> > index 15af65f..a502dda 100644
> > --- a/criu/Makefile.config
> > +++ b/criu/Makefile.config
> > @@ -15,7 +15,7 @@ ifeq ($(call pkg-config-check,libselinux),y)
> >  endif
> >  
> >  FEATURES_LIST	:= TCP_REPAIR STRLCPY STRLCAT PTRACE_PEEKSIGINFO \
> > -	SETPROCTITLE_INIT MEMFD
> > +	SETPROCTITLE_INIT MEMFD TCP_REPAIR_WINDOW
> >  
> >  # $1 - config name
> >  define gen-feature-test
> > diff --git a/criu/cr-check.c b/criu/cr-check.c
> > index ca506a1..b639afb 100644
> > --- a/criu/cr-check.c
> > +++ b/criu/cr-check.c
> > @@ -917,6 +917,22 @@ static int check_cgroupns(void)
> >  	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);
> >  
> >  /*
> > @@ -1014,6 +1030,7 @@ int cr_check(void)
> >  		ret |= check_fdinfo_lock();
> >  		ret |= check_clone_parent_vs_pid();
> >  		ret |= check_cgroupns();
> > +		ret |= check_tcp_window();
> >  	}
> >  
> >  	/*
> > diff --git a/criu/include/kerndat.h b/criu/include/kerndat.h
> > index 0a5cd4b..860e32d 100644
> > --- a/criu/include/kerndat.h
> > +++ b/criu/include/kerndat.h
> > @@ -31,6 +31,7 @@ struct kerndat_s {
> >  	bool has_dirty_track;
> >  	bool has_memfd;
> >  	bool has_fdinfo_lock;
> > +	bool has_tcp_window;
> >  	unsigned long task_size;
> >  	bool ipv6;
> >  	bool has_loginuid;
> > @@ -57,4 +58,6 @@ enum {
> >   */
> >  extern int kerndat_fs_virtualized(unsigned int which, u32 kdev);
> >  
> > +extern int kerndat_tcp_repair_window();
> > +
> >  #endif /* __CR_KERNDAT_H__ */
> > diff --git a/criu/kerndat.c b/criu/kerndat.c
> > index 04a355b..3cb0a13 100644
> > --- a/criu/kerndat.c
> > +++ b/criu/kerndat.c
> > @@ -485,6 +485,8 @@ int kerndat_init(void)
> >  		ret = kerndat_iptables_has_xtlocks();
> >  	if (!ret)
> >  		ret = kerndat_compat_restore();
> > +	if (!ret)
> > +		ret = kerndat_tcp_repair_window();
> >  
> >  	kerndat_lsm();
> >  
> > @@ -516,6 +518,8 @@ int kerndat_init_rst(void)
> >  		ret = kerndat_iptables_has_xtlocks();
> >  	if (!ret)
> >  		ret = kerndat_compat_restore();
> > +	if (!ret)
> > +		ret = kerndat_tcp_repair_window();
> >  
> >  	kerndat_lsm();
> >  
> > diff --git a/criu/sk-tcp.c b/criu/sk-tcp.c
> > index 13d175a..37bf69c 100644
> > --- a/criu/sk-tcp.c
> > +++ b/criu/sk-tcp.c
> > @@ -33,6 +33,17 @@
> >  #define SIOCOUTQNSD     0x894B
> >  #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
> >  /*
> >   * It's been reported that both tcp_repair_opt
> > @@ -58,6 +69,10 @@ enum {
> >  #define TCP_TIMESTAMP	24
> >  #endif
> >  
> > +#ifndef TCP_REPAIR_WINDOW
> > +#define TCP_REPAIR_WINDOW       29
> > +#endif
> > +
> >  #ifndef TCPOPT_SACK_PERM
> >  #define TCPOPT_SACK_PERM TCPOPT_SACK_PERMITTED
> >  #endif
> > @@ -751,3 +766,41 @@ out:
> >  
> >  	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;
> > +}
> > +
> > diff --git a/scripts/feature-tests.mak b/scripts/feature-tests.mak
> > index e009370..09bbdc8 100644
> > --- a/scripts/feature-tests.mak
> > +++ b/scripts/feature-tests.mak
> > @@ -12,6 +12,20 @@ int main(void)
> >  }
> >  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
> >  #include <bsd/string.h>
> >  
> > 
> 


More information about the CRIU mailing list