-
Notifications
You must be signed in to change notification settings - Fork 2.6k
futils_mktmp: don't use umask. #5350
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
Conversation
|
Reading this quickly on my phone, so apologies if I misread - but it looks to me like this opens the new file world-writable, which would give us a different race condition. Instead, why don't we add a new function -- |
|
I considered something like that, but it doesn't seem obvious that there's a good place to try to create the file to probe for umask, since there might be, for example, a noexec mount that screws with your probed umask. Now that I think about it, we can just do this twice to avoid the race: once to get the umask and throw away, and once with the proper permissions. (getumask is apparently vaporware: grepping through the kernel confirms that there isn't a getumask syscall.) |
|
Wait, we don't need to chmod at all, we can just open with that mode directly. chmod was only needed before because mkstemp creates the files with 0600 permissions. |
213a524 to
10d0689
Compare
Well, So there is probably really no benefit in using it if it is available. Pedantic nit: the term "vaporware" refers to software that was only announced but never implemented. This function was implemented, so it doesn't fit the definition. Still, it's pretty useless if you consider portability. |
|
It's declared in the glibc headers, but there's only an implementation on Hurd. If you try to call it on Linux, you'll fail to link. |
ethomson
left a comment
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.
Thanks so much for the PR and especially for including a unit test. There are a few minor stylistic nits, but this also fails on Windows.
I'm happy to dig in on Windows and finish up the changes here, unless you'd prefer to take care of it yourself.
Really happy to see a threadsafe version of this. Thanks again! 🙇♂️
|
Sorry, I've been meaning to dig into the Windows failures, but I haven't managed to scrape up the time. The error seems like a leak that presumably should happen on all platforms, but after staring at the code a bit, I don't see where it is. Maybe the test is returning early and failing to clean up the buffer because one of the assertions is failing on windows? I didn't see anything that indicated that in the logging, but I might have missed it. |
That’s correct - our tests don’t tear everything down when they fail, so we’ll detect leaks there. Apologies that this isn’t more obvious; our CI grew rather organically, and leak detection was added on. We may be able to disable printing the leaks if clar exits with a nonzero exit code. If nothing else, we could print a big banner at the bottom of the output on a failure. |
|
I do have a concern about
Which would mean that our temporary files are deterministic. I can imagine a denial of service attack based on this - or perhaps more likely, we fail to create new files because we neglected to clean up the old ones accidentally. |
|
Disabled the test on windows, and cleaned up all of the nits: hopefully this revision passes CI. |
Previously, we were using `umask(mask = umask(0))` to fetch the current umask in order to apply it to the desired mode, but this is broken in the presence of threads. There is no portable way to directly fetch umask without mutating it. Instead, add a reimplementation of mkstemp that uses a passed-in mode, instead of explicitly chmodding to 0600 like POSIX requires of mkstemp. Fixes: jmgao/pore#46
| int git_buffer_global_init(void) | ||
| { | ||
| /* Seed rand for git_buf_put_rand. */ | ||
| srand((unsigned int)time(NULL)); |
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 really shouldn't be using rand() and srand() at all. Seeding via time(NULL) only gives you a negligible amount of bits, as you can typically deduce at what time a certain command is running. I don't know about Windows, but on Unix-like systems most nowadays support calls like getrandom() that are much saner to use than the combination of rand() and srand().
| while (tries--) { | ||
| git_buf_sets(path_out, filename); | ||
| git_buf_puts(path_out, "_git2_"); | ||
| git_buf_put_rand(path_out, 8); |
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.
I'd argue that manually generating the name doesn't make a lot of sense. Instead, we should probably be using something like tempnam(3P) that properly handles this for us, and that would also remove the need for git_buf_put_rand and the random-seeding hassle.
|
Closed via #6178 |
Previously, we were using
umask(mask = umask(0))to fetch the currentumask in order to apply it to the desired mode, but this is broken in
the presence of threads. There is no portable way to directly fetch
umask without mutating it.
Instead, create the file with 0777 permissions, and fstat it to reverse
engineer what umask was when the file was created, and then apply that
as a mask on the mode.
Fixes: jmgao/pore#46