Skip to content

Fix Unix.utimes not working for directories on Win32.#8796

Merged
damiendoligez merged 4 commits intoocaml:trunkfrom
dmbaturin:trunk
Nov 3, 2020
Merged

Fix Unix.utimes not working for directories on Win32.#8796
damiendoligez merged 4 commits intoocaml:trunkfrom
dmbaturin:trunk

Conversation

@dmbaturin
Copy link
Copy Markdown
Contributor

On Win32, Unix.utimes fails with EACCESS.

# Unix.stat "testdir";;
- : Unix.stats =
{Unix.st_dev = 68940724; st_ino = 336654; st_kind = Unix.S_DIR;
 st_perm = 511; st_nlink = 1; st_uid = 0; st_gid = 0; st_rdev = 68940724;
 st_size = 0; st_atime = 1562621282.6993136; st_mtime = 1562621282.6993136;
 st_ctime = 1562621282.6993136}

# Unix.utimes "testdir" 0.0 0.0 ;;
Exception: Unix.Unix_error (Unix.EACCES, "utimes", "testdir").

The cause is that CreateFile* functions need a special flag to work with directories, FILE_FLAG_BACKUP_SEMANTICS. Without it, it returns errno=6 (INVALID_HANDLE).
See https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea#directories

It appears to have no ill effects for normal files, and Python's os.utime implementation on Win32 uses it: https://github.com/python/cpython/blob/master/Modules/posixmodule.c#L4830-L4859

I'm by no means a Windows expert though, so this requires a review from someone who is.

@dmbaturin
Copy link
Copy Markdown
Contributor Author

I see that the Travis build failed due to missing Changes entry. Somehow I have missed that section in CONTRIBUTING.md, sorry.
I'm confused by the process though. If it requires "review by", should it be only added after the PR is reviewed?

@nojb
Copy link
Copy Markdown
Contributor

nojb commented Jul 9, 2019

The change looks reasonable to me. Let's wait and see what @dra27 thinks.

Yes, you need to add an entry to the Changes file (in the Bug fixes section) and fill it out with the names of the reviewers before it is merged.

Thanks!

@dra27
Copy link
Copy Markdown
Member

dra27 commented Jul 9, 2019

I'm afraid using FILE_FLAG_BACKUP_SEMANTICS this way is a bit like embedding a sudo call inside the library - especially for files, it allows the function to access directories and files which should not be accessible without explicit authorisation (the main job of FILE_FLAG_BACKUP_SEMANTICS is to disable security checks). It's a horrible hack that directory handles are also accessed this way - it's necessary to ensure that SeRestorePrivilege is not active for the process during the CreateFile call, so that you can be sure that it's opened a handle to a directory to which you normally have access. I've put a full implementation of it in dra27@128bbb7 which ensures that SeRestorePrivilege is correctly dropped, even in the presence of multiple threads.

I'm mildly surprised that the Python and Go guys weren't more suspicious.

This could be partially mitigated by only specifying FILE_FLAG_BACKUP_SEMANTICS for directories. It's not exploitable, per se, since if the current user has SeRestorePrivilege and has enabled it then several manual steps have already been taken, but I don't think it's great that that's hidden inside a general-purpose function.

@dra27
Copy link
Copy Markdown
Member

dra27 commented Oct 11, 2019

It would be good to have a fix for this in 4.10, but I'm afraid I'm not going to have time to deal with @stedolan's review comment in #8797. I propose one of these two:

  1. Merge this PR as-is
  2. Include a test for whether wpath is a directory and specify FILE_FLAG_BACKUP_SEMANTICS only for a directory, and not a file

I prefer the second, since it makes utimes behave in the same slightly incorrect way as stat and readlink presently do. I will give some time to some of my outstanding PRs after the 4.10 branch and then the proper fix should be in 4.11.0.

What do you think @nojb?

@nojb
Copy link
Copy Markdown
Contributor

nojb commented Oct 11, 2019

It would be good to have a fix for this in 4.10, but I'm afraid I'm not going to have time to deal with @stedolan's review comment in #8797. I propose one of these two:

  1. Merge this PR as-is
  2. Include a test for whether wpath is a directory and specify FILE_FLAG_BACKUP_SEMANTICS only for a directory, and not a file

I prefer the second, since it makes utimes behave in the same slightly incorrect way as stat and readlink presently do. I will give some time to some of my outstanding PRs after the 4.10 branch and then the proper fix should be in 4.11.0.

What do you think @nojb?

Since this is a bug fix, wouldn't it be possible to get it into 4.10 even after the freeze ? In any case, 2 sounds OK as well. Unfortunately I am overloaded at the moment so I can't help getting this in shape for merging.

@dmbaturin
Copy link
Copy Markdown
Contributor Author

@nojb If option 2 is agreed upon, I can do it myself. I haven't abandoned my PR.

@nojb
Copy link
Copy Markdown
Contributor

nojb commented Oct 11, 2019

@nojb If option 2 is agreed upon, I can do it myself. I haven't abandoned my PR.

I didn't mean to imply that :)

Please go ahead and do that if you can, we can merge @dra27's more complete fix in a later PR.

@damiendoligez
Copy link
Copy Markdown
Member

This and #8797 are both bug fixes and can be merged after the (imminent) branching of 4.10.

@gasche
Copy link
Copy Markdown
Member

gasche commented Nov 7, 2019

We still need people to converge on this PR and carefully review @dra27' #8797 if we want to have them in 4.10.

@damiendoligez
Copy link
Copy Markdown
Member

@dmbaturin are you still willing to work on this? #8797 seems to be stalled as well.

@dra27
Copy link
Copy Markdown
Member

dra27 commented May 4, 2020

@damiendoligez / @Octachron - #8797 is too invasive to risk putting in 4.11 (but I'm gradually working through my backlog so I will be looking for its being merged before 4.12). However, the change here fixes a real bug in the same way as many other language libraries already do, so could we put this into 4.11 and then replace it with the comprehensive version in 4.12?

@dmbaturin
Copy link
Copy Markdown
Contributor Author

@damiendoligez Sorry, I've neglected this indeed. I'm ready to get back to it if we have a course of action agreed upon. Do we? :)

This proposal is no worse than mainstream, and to me it seems like security issues it may cause are mostly theoretical. However, I'm not a Windows expert by any means so I'd rather leave the final decision to @dra27. If there's anything you want me to change in this PR before it can be merged, I'm ready to do that.

@damiendoligez
Copy link
Copy Markdown
Member

It seems to me that we have a course of action: merge this now and delay #8797 to 4.12.

@dmbaturin if you could add a Changes entry, I'll merge this PR.

@damiendoligez damiendoligez self-assigned this Jun 3, 2020
@dmbaturin
Copy link
Copy Markdown
Contributor Author

@damiendoligez Done. Could you check?

@damiendoligez damiendoligez merged commit 0280127 into ocaml:trunk Nov 3, 2020
@damiendoligez
Copy link
Copy Markdown
Member

Merged to trunk and cherry-picked to 4.12 (commit f3ff689). I guess #8797 will wait for 4.13.

@damiendoligez
Copy link
Copy Markdown
Member

Thank you @dmbaturin for your contribution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants