[CRIU] Re: [PATCH 1/2] sockets: Restore unbound inet sockets v3

Pavel Emelyanov xemul at parallels.com
Wed Jun 27 13:13:19 EDT 2012


On 06/27/2012 01:52 AM, Cyrill Gorcunov wrote:
> 
> v2:
>  - Use do_dump_opt in dump_socket to not call
>    lookup_socket redundantly
> 
> v3:
>  - use getsockopt to check that unconnected
>    socket has no peername and it's not listening
>  - do test only socket protocol since family and
>    type will be called in dump_one_inet_fd.
> 
> Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
> ---
>  include/sockets.h |    2 +
>  sk-inet.c         |  113 ++++++++++++++++++++++++++++++++++++++++++++++++----
>  sockets.c         |    2 +-
>  3 files changed, 107 insertions(+), 10 deletions(-)
> 

> +static struct inet_sk_desc *gen_uncon_sk(int lfd, const struct fd_parms *p)
> +{
> +	struct inet_sk_desc *sk;
> +	char address[128];
> +	socklen_t aux;
> +	int ret;
> +
> +	sk = xzalloc(sizeof(*sk));
> +	if (!sk)
> +		goto err;
> +
> +	/* It should has no peer name */
> +	aux = sizeof(address);
> +	ret = getsockopt(lfd, SOL_SOCKET, SO_PEERNAME, address, &aux);
> +	if (ret != -1 || errno != ENOTCONN) {
> +		pr_err("Errno %d returned from unconnected socket\n", errno);
> +		goto err;
> +	}
> +
> +	/* It should not be listening */
> +	aux = sizeof(int);
> +	ret = getsockopt(lfd, SOL_SOCKET, SO_ACCEPTCONN, address, &aux);
> +	if (ret) {
> +		pr_perror("getsockopt failed on %d\n", p->fd);
> +		goto err;
> +	}
> +
> +	if (*(int *)address != 0) {
> +		pr_err("socket %d is listening\n", p->fd);
> +		goto err;
> +	}
> +
> +	/*
> +	 * The restored application will pass backlog explicitly
> +	 * on a listen call (if needed) so put some sane value here.

Some sane is not good. For UDP sockets this is useless, for TCP you can request
for TCPINFO sockoption, it will contain the required value and (!) the socket
state, thus you won't have to mess with the SO_ACCEPTCONN above.

> +	 */
> +	sk->sd.ino	= p->stat.st_ino;
> +	sk->state	= TCP_CLOSE;
> +	sk->wqlen	= 16;
> +
> +	ret  = do_dump_opt(lfd, SO_DOMAIN, &sk->sd.family, sizeof(sk->sd.family));
> +	ret |= do_dump_opt(lfd, SO_TYPE, &sk->type, sizeof(sk->type));
> +	ret |= do_dump_opt(lfd, SO_PROTOCOL, &sk->proto, sizeof(sk->proto));
> +	if (ret)
> +		goto err;
> +
> +	/*
> +	 * These are unconnected and uncollected sockets, so we need
> +	 * to check out if the sockets are really those which restore
> +	 * we support. Note the bunch of tests will be done on a caller
> +	 * side so we check the minimum here.
> +	 */
> +	switch (sk->proto) {
> +	case IPPROTO_IP:
> +	case IPPROTO_TCP:
> +	case IPPROTO_UDP:
> +	case IPPROTO_UDPLITE:
> +		break;
> +	default:
> +		pr_err("Unsupported socket proto %d on %d\n",
> +		       sk->proto, p->fd);
> +		goto err;

This should be moved into can_dump_inet_sk.

> +	}
> +
> +	return sk;
> +err:
> +	xfree(sk);
> +	return NULL;
> +}
> +



More information about the CRIU mailing list