Re: [PATCH v4 09/12] unix-socket: disallow chdir() when creating unix domain sockets
- From
Jeff King <peff@peff.net>
- Date
- Mar 5, 2021, 09:02 UTC
- Message-ID
- <YEHzmIOYgRtI1Ak1@coredump.intra.peff.net>
- In-Reply-To
- <xmqqtupqbij4.fsf@gitster.c.googlers.com>
On Thu, Mar 04, 2021 at 03:34:07PM -0800, Junio C Hamano wrote:
Show 27 quoted lines
> Junio C Hamano <gitster@pobox.com> writes: > > >> So I dunno. I'd be OK to just rip the feature out in favor of doing > >> those chdir()s. But that seems like a non-zero amount of work versus > >> leaving, and the existing code has the benefit that if another caller > >> shows up, it could benefit from the feature. > > > > I am OK to keep the series as-is, and leave it to a possible future > > work to remove the need for chdir even for long paths and not having > > to return an error with ENAMETOOLONG; when such an update happens, > > the "fail if need to chdir" feature this patch is adding will become > > a no-op. > > For example, as this is UNIX-only codepath, I wonder if something > like this would be a good way to avoid chdir() that would cause > trouble. > > - obtain a fd from socket(2) > - check if path is too long to fit in sa->sun_path > - if it does, bind(2) the fd to the address > - if it does not, fork(2) a child and > - in the child, chdir(2) there and use the shortened path > to bind(2), and exit(3) > - the parents just wait(2)s for the child to return. By the > time it dies, the fd would be successfully bound to the > path. > - now we have a file descriptor that is bound at that path.
If the trouble is that chdir() isn't thread-safe, I wonder if fork() creates its own headaches. :) I guess libc usually takes care of the basics with pthread_atfork(), etc, and the child otherwise would not need to access much data.
I don't know offhand if this trick actually works. I can imagine it does, but it hinges on the subtlety between an integer descriptor and the underlying "file description" (the term used in POSIX). Does binding a socket operate on the former (like close() does not close the parent's descriptor) or the latter (like lseek() impacts other descriptors).
I'd guess the latter, but I wasn't sure if you were suggesting this from experience or if you just invented the technique. ;)
-Peff