-
Notifications
You must be signed in to change notification settings - Fork 531
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Do not TLS close_notify when resetting a TCP connection #1944
Changes from all commits
79fb8d2
ae5ce4b
b141627
2ef9964
fd624e6
67b6f33
46d3f51
c983871
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -783,6 +783,8 @@ commConfigureLinger(const int fd, const OnOff enabled) | |
l.l_onoff = (enabled == OnOff::on ? 1 : 0); | ||
l.l_linger = 0; // how long to linger for, in seconds | ||
|
||
fd_table[fd].flags.harshClosureRequested = (l.l_onoff && !l.l_linger); // close(2) sends TCP RST if true | ||
|
||
if (setsockopt(fd, SOL_SOCKET, SO_LINGER, reinterpret_cast<char*>(&l), sizeof(l)) < 0) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It may be tempting to make new harshClosureRequested flag assignment conditional on this setsockopt() call success, but I do not think we should do that: The caller has requested harsh connection closing; setsockopt() success is pretty much irrelevant. Even if TCP layer closes nicely despite our attempt to close harshly, we still want to close TLS layer harshly... |
||
const auto xerrno = errno; | ||
debugs(50, DBG_CRITICAL, "ERROR: Failed to set closure behavior (SO_LINGER) for FD " << fd << ": " << xstrerr(xerrno)); | ||
|
@@ -877,7 +879,7 @@ _comm_close(int fd, char const *file, int line) | |
// For simplicity sake, we remain in the caller's context while still | ||
// allowing individual advanced callbacks to overwrite it. | ||
|
||
if (F->ssl) { | ||
if (F->ssl && !F->flags.harshClosureRequested) { | ||
const auto startCall = asyncCall(5, 4, "commStartTlsClose", | ||
callDialer(commStartTlsClose, fd)); | ||
Comment on lines
+882
to
884
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To me, it seems fairly obvious that if we are going to send TCP RST to the client, then we do not want to nicely close TLS session either. Our harsh closure reasons that apply to TCP layer ought to apply to TLS layer as well. For example, if Squid is sending the client an unchunked HTTP response without Content-Length header, and Squid has to abort that transaction, then we do not want successful TLS closure to trick that client into thinking that it has gotten the entire response body. If others disagree with this "fairly obvious" assertion, then we should add an explanation to PR description. That explanation may be similar to the above paragraph (sans the "obvious" claim itself, of course). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. While what you write seems reasonable, it is not clear that RST is the only result of this function being called. It can and is also called for the FIN cases where TLS should be completed cleanly. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
FWIW, the function (commStartTlsClose()) is not called for RST cases (F->flags.harshClosureRequested is false) but called for other (i.e., FIN) cases, as you noted. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
If "this function" is commStartTlsClose():
If "this function" is commConfigureLinger():
It is, of course, possible that some code paths that end with commStartTlsClose() are missing a commConfigureLinger() call to RST the connection, but that possible problem is outside this PR scope. This PR does not change and should not change when/where commConfigureLinger() is called. |
||
ScheduleCallHere(startCall); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a low-level private function with callers already checking
fd
, so I think it may be OK to avoid checkingfd
value before accessing fd_table here. If you disagree, consider applying this suggestion:There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We would need also to protect setsockopt() by the same check, i.e., basically this function should immediately return if isOpen() is false. I would just assert(isOpen(fd)) instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not necessarily: Leaving that system call exposed to caller bugs may be better in this case because it will result in level-0 ERROR message, exposing the bug.
I would too, but "The following [isOpen(fd) check] fails because ipc.c is doing calls to pipe() to create sockets" comment in _comm_close() worries me. That old comment may no longer reflect what is actually going on, of course, but it is a red flag.
All these complications/problems are outside this PR scope IMO (as detailed at the beginning of this thread). They are best resolved in a dedicated PR. That is why I did not recommend any changes in my review. Said that, if others insist on an
if
check or assertion, let's add them to make progress.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, let's leave this function as is.