All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH net] sctp: Free connecting association if there is a pending signal
@ 2018-07-09 10:11 Petr Malat
  2018-07-09 12:15 ` Neil Horman
                   ` (8 more replies)
  0 siblings, 9 replies; 10+ messages in thread
From: Petr Malat @ 2018-07-09 10:11 UTC (permalink / raw)
  To: linux-sctp

[-- Attachment #1: Type: text/plain, Size: 832 bytes --]

Hi!
I believe signal handling in the connect path is not implemented properly
as connect() terminates with EINPROGRESS instead of being restarted after
the signal handler returns (see attached sctp_connect_intr_bug.c).
I went through the POSIX manual pages and it seems EINPROGRESS can be
returned only if the socket is nonblocking. Linux documentation also
mention connect() could fail with EINPROGRESS if SO_SNDTIMEO expires (this
option is not discussed by POSIX manual pages). This is also how TCP
behaves.
I was able to solve the issue by freeing the association in the signal
handling path, see the attached sctp_connect_intr.patch, which also contains
the rationale for the change.
Please, review the change as I based it on code comments which may be obsolete
and I do not have knowledge of SCTP stack internals.
BR,
  Petr

[-- Attachment #2: sctp_connect_intr_bug.c --]
[-- Type: text/x-csrc, Size: 1177 bytes --]

#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>

#define DEAD_IP "127.16.0.1"
#define fail_if(arg) if (0 != (arg)) { \
	fprintf(stderr, "Failed at %d: %s\n", __LINE__, #arg);\
	return 1; }

void handler(int sig)
{
	printf("Got signal %d\n", sig);
}

int main(int argc, char *argv[])
{
	struct sockaddr_in addr4 = { .sin_family = AF_INET, .sin_port = htons(5555) };
	struct sockaddr *deadaddr = (struct sockaddr *)&addr4;
	struct sigaction sa = { .sa_handler = handler, .sa_flags = SA_RESTART }; 
	int sk, rtn;

	fail_if(1 != inet_pton(AF_INET, DEAD_IP, &addr4.sin_addr));

	fail_if(system("iptables -I OUTPUT -d " DEAD_IP "/32 -j DROP"));

	fail_if(0 > (sk = socket(PF_INET, SOCK_SEQPACKET, IPPROTO_SCTP)));
	fail_if(sigaction(SIGALRM, &sa, NULL));
	fail_if(alarm(3) < 0);

	rtn = connect(sk, deadaddr, sizeof *deadaddr);

	// The call should either resume the operation of fail with EINTR
	printf("rtn: %d errno: %d (%s)\n", rtn, errno, strerror(errno));

	fail_if(system("iptables -D OUTPUT -d " DEAD_IP "/32 -j DROP"));

	return 0;
}

[-- Attachment #3: sctp_connect_intr.patch --]
[-- Type: text/x-diff, Size: 1239 bytes --]

sctp: Free connecting association if there is a pending signal

When a connection attempt is interrupted by a signal, there are two
possibilities how the process can continue:
 - There has been a timeout specified through SO_SNDTIMEO, in that case
   the call must terminate the association and return -EINTR, because
   it's not possible to restart the call safely as the timeout is
   not an argument of the connect or SCTP_SOCKOPT_CONNECTX call.
 - If the connect timeout has not been limited, it's possible to restart
   the call, however the association must be freed as well to make that
   possible. Theoretically, one could pick up the ongoing association in
   the restart path, but the problem is we can't esily detect if
   the syscall restarting wasn't disabled by the user.
As a result, it's sensible to free the association independently if the
connect attempt is being restarted or not.

Signed-off-by: Petr Malat <oss@malat.biz>
--- linux-4.18-rc3.orig/net/sctp/socket.c	2018-07-09 11:46:51.991717457 +0200
+++ linux-4.18-rc3/net/sctp/socket.c	2018-07-05 15:17:29.292657471 +0200
@@ -8456,6 +8456,7 @@ do_error:
 	goto out;
 
 do_interrupted:
+	sctp_association_free(asoc);
 	err = sock_intr_errno(*timeo_p);
 	goto out;
 

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2018-07-12 10:27 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-07-09 10:11 [PATCH net] sctp: Free connecting association if there is a pending signal Petr Malat
2018-07-09 12:15 ` Neil Horman
2018-07-09 15:37 ` Petr Malat
2018-07-09 19:08 ` Neil Horman
2018-07-11  9:12 ` Petr Malat
2018-07-11 10:43 ` Neil Horman
2018-07-11 11:09 ` David Laight
2018-07-11 17:20 ` Petr Malat
2018-07-11 23:43 ` Neil Horman
2018-07-12 10:27 ` Petr Malat

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.