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
Fix abstract unix socket name #2235
Conversation
But |
@emmenlau: I think is the other way around: The If for example, you create an abstract unix socket server in thtift: ...
new TServerSocket("\0abstract-socket");
... Searching for it in '/proc' `cat /proc/net/unix | grep abstract-', gives: ... @abstract-socket@ The last '@' is extra, due to the null char |
That actually makes sense. Hmmm... But regardless, I'd not be happy with the patch itself. Could this be solved in a more clear way? Y'know, such that it'd be obviously-correct. |
The other way to do it, is calculating the len of the string based on the type of socket: pathname socket: null terminated This lead to an if in some point of the code. I prefer to do an aritmethic operation instead of adding a conditional jump (for a cpu point of view, the arithmethic way will not lead to control hazards). |
OK, so we have:
The I mean: the |
Take into account that, for the
Maybe a comment could do the job ? |
so you're saying, this would be correct call?
As you can see, there's already one. Is it helpful? |
*edit: sorry I confused this from the other PR. code in master does
so it's fine. |
Not, is 4, but when you will do
The comment is:
Yes, is helpful, it's give the correct way to do. But the code was not the correct, because it uses the variable |
is |
I think its better to copy only Zero-termination is (better?) handled by the |
It's fine for the pathname socket (len includes the null). For abstract socket id not the correct, we don't need to count the null.But if you prefer to copy an additional char, go ahead. The problem is the size passed in |
Let me see if I get everything right:
So the "only" challenge is to agree on a good style to compute #ifdef __linux__
// sun_path is not null-terminated in this case, and structlen must be shortened to the path size
structlen = static_cast<socklen_t>(sizeof(address)) - sizeof(address.sun_path) + path_.size();
#else |
The
The code need to be fixed in 3 files (not 2). and the code is the same in the 3 files, So better to do a refactoring. |
@emmenlau all good as you said, per my understanding. I'd update the comment too, maybe like this. #ifdef __linux__
// sun_path is not null-terminated for abstract sockets, truncate structlen to the path size
structlen = static_cast<socklen_t>(sizeof(address) - sizeof(address.sun_path) + path_.size());
#else Also, maybe move the |
Not, if the string is the same size in bytes as the 'sockaddr_un.sun_path', you will lack the null terminated string, and posibly getting a memory error. |
This won't happen, due to
|
If the path_is for an abstract unix socket, the `size_t len = path_.size() + 1' is not ok, is legal to fill the entire address.sun_path field. |
But then copying the zero-termination would write beyond the end of |
In the case of pathname socket yes, for abstract unix socket is legal, because you don't need to copy the null terminating. is the standard. Is simply, the problem is around checking correctly the size and the terminating null; there's no need for zeroing all the struct and lost some useful cpu cycles (but if you are more confident this way ...). |
Disagreed here. Technically, you're right*, but maintenance-wise and for future-proofing (and not sending stack garbage directly into the kernel — for abstract sockets), it's best to zero it out. *with conditions |
The zeros as the manual states, have no special significance, so they are garbage too, so no point here. And for maintenance point, better to have the correct handling in code, instead of try to fix it, as zeoing something. |
Actually, it sadly is required. See the stackoverflow link from above (and also my own experience). The kernel may use all characters in |
With the correct code handling , (null terminating case ok for pahtname socket, and correct lenght for abstract unix socket) the special caracters will disapear... For me I see zeroing them as an unneed operation, that mask the correct solution that is, better handling of null terminated string. (but c and c++ are always hard), |
But this is more error-prone and complex than to just zero the full struct, and then copy only |
Ok, lets settle for "would you be ok to leave the zeroing in place"? It does not hurt much, if nothing else? :-) |
Yes, more easy, this way, you forget about the terminating string. But the question is: If I go to a fountain because I need one liter of water, and I fill five just in case (is the correct way o not?). Points of view. But if the code need's to handling the null terminating and the size, and the two are correct. Removing the memset, will not make any difference. |
I think, the struct sockaddr_un address;
memset(&address, '\0', sizeof(address));
address.sun_family = AF_UNIX;
if (!path_[0]) { // "abstract" namespace socket (Linux-specific)
// space check
if (path_.size() > sizeof(((sockaddr_un*)nullptr)->sun_path)) {
throw TTransportException(...);
}
// no null termination here
memcpy(address.sun_path, path_.c_str(), path_.size());
addrlen = path._size();
} else { // "pathname" socket
// space check, with additional byte for the terminator
if (path_.size() + 1 > sizeof(((sockaddr_un*)nullptr)->sun_path)) {
throw TTransportException(...);
}
// including the null terminator
strncpy(address.sun_path, path_.c_str(), path_.size() + 1);
addrlen = path._size() + 1;
}
::bind(/*…*/, /*…*/, addrlen);
Yes exactly — that's why I'm saying I'm not totally happy with your patch! |
Make a unique function call for the 3 files, could be good too ... :) And, the memset, for me, is not making nothing :) |
Well, not such a bad idea, haha. Will you do it?
I understand; let's just agree to disagree on this, can we? Also, as a reminder: we have 2 PR's fixing the same thing in different ways. #2234 and #2235. It's best to focus on one and close the other. |
Can take a look tomorrow. If nobody want to do after.
uhm... xD
|
This is actually a subset of a larger section of TServerSocket.cpp and TSocket.cpp that mostly overlaps. For maintenance this would much better be unified. I don't have too much spare time, anyone wants to give it a go? |
The longer I think about it, yes maybe the |
90d56db
to
4fa63e7
Compare
@ulidtko there goes |
4fa63e7
to
52e88cb
Compare
This newest version looks very good to me. Nice work. |
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.
Awesome, this looks pretty good!
do you known when we get a new release ? |
There is no real schedule, and no release plan. So I would not hold my breath for it. If you are very curious or urgently need a release, I would suggest to bring the topic to the mailing list. |
The de-facto truth is: When somebody*) manages some time to start working on one. *) out of a group of certain people, not just anybody |
It build fail in CI. see this AppVeryor log show like this.
Could you build success in your local environment ? |
For the abstract unix socket address type, the string in the 'sun_path' field of the 'sockaddr_un' struct, is a not null-terminated string (see unix(7)). Fix the lentgh calculation of the 'sun_path' field to not add the termination null byte.
52e88cb
to
4750f36
Compare
Fixed, seems that thrift is not ready for compiling unix sockets under windows. I just added some conditional macros. I fixed too, a variable that does not has the correct name ( I added a TODO, to take into account, that windows has support to unix sockets, but the code is not prepared for that. At least it needs to include the windows headers for unix sockets. See af_unix-comes-to-windows I don't have a windows development enviroment, so I can't take a look. |
I have PR #2127 that adds support for Unix sockets under Windows. Generally its positive to have separate PRs for separate functionality, but in this case its not necessarily better that you need to guard against supporting Unix sockets only for me to later add the support in a subsequent PR. So please feel free to cannibalize #2127 and take everything you need to support the Unix sockets on MSVC? |
Hi @emmenlau, I don't have a windows development enviroment, and because, to add support for Unix sockets, is needed a new header (and the checks for it), better to have it in another separate PR. And is needed to remove other windows conditional compilation in sockets sources files, too. Eg:
This one only fix abstract namespace, so better if you can do another PR removing the conditional compilation for windows. Seems more logical to have the new windows unix socket support separated. |
Good, I agree! Then @zeshuai007 please review! |
For the abstract unix socket address type, the string in the
'sun_path' field of the 'sockaddr_un struct', is a not null-terminated
string (see unix(7)).
Fix the lentgh calculation of the 'sun_path' field to don't add
the termination null byte.