Eryk Sun <eryk...@gmail.com> added the comment:

FYI, here are the access rights applicable to files, including their membership 
in generic (R)ead, (W)rite, and e(X)execute access:

    0x0100_0000 --- ACCESS_SYSTEM_SECURITY
    0x0010_0000 RWX SYNCHRONIZE
    0x0008_0000 --- WRITE_OWNER
    0x0004_0000 --- WRITE_DAC
    0x0002_0000 RWX READ_CONTROL
    0x0001_0000 --- DELETE

    0x0000_0001 R-- FILE_READ_DATA
    0x0000_0002 -W- FILE_WRITE_DATA
    0x0000_0004 -W- FILE_APPEND_DATA
    0x0000_0008 R-- FILE_READ_EA
    0x0000_0010 -W- FILE_WRITE_EA
    0x0000_0020 --X FILE_EXECUTE
    0x0000_0040 --- FILE_DELETE_CHILD
    0x0000_0080 R-X FILE_READ_ATTRIBUTES
    0x0000_0100 -W- FILE_WRITE_ATTRIBUTES

> _wopen() uses GENERIC_READ/GENERIC_WRITE access rights, but 
> _wopen() doesn't have a contractual obligation to do exactly 
> that AFAIU. For example, if it got some extra access rights, 
> then my code would "drop" them while switching FILE_WRITE_DATA off.

I overlooked a case that's a complication. For O_TEMPORARY, the open uses 
FILE_FLAG_DELETE_ON_CLOSE; adds DELETE to the requested access; and adds 
FILE_SHARE_DELETE to the share mode. 

With delete-on-close, a file gets marked as deleted as soon as the last handle 
for the kernel File is closed. This is the classic Windows 'deleted' state in 
which the filename remains linked in the directory but inaccessible for any new 
access (as opposed to the immediate POSIX style delete that DeleteFileW 
attempts in Windows 10). Existing opens (i.e. kernel File objects from 
CreateFileW) are still valid, and, if they have delete access, they can even be 
used to undelete the file via SetFileInformationByHandle: FileDispositionInfo. 

_Py_wopen_noraise() can easily keep the required DELETE access. The 
complication is that you have to be careful not to close the original file 
descriptor until after you've successfully created the duplicate file 
descriptor. If it fails, you have to return the original file descriptor from 
_wopen(). If you close all handles for the kernel File and fail the call, the 
side effect of deleting the file is unacceptable. 

The C runtime itself isn't careful about using O_TEMPORARY in text mode, given 
how it closes the file if truncation fails or has to open the file twice in 
O_WRONLY mode in order to read the BOM. But at least it's reliable in binary 
mode. The file descriptor is pre-allocated with _alloc_osfhnd(), so it won't 
fail after CreateFileW() is called.

> Are you aware of a common scenario when a regular file allows 
> appending but not writing?

It's certainly not common for regular files. (It's more common for directories, 
for which append access corresponds to the right to create a subdirectory.) 
Maybe users are only allowed to append to a given log file. But I think most 
scenarios will be accidental. 

For example, say an admin wants to deny write access to standard users. Denying 
simple or generic write access is wrong, since doing so also denies rights 
required for reading, i.e. synchronize and read-control. So the admin runs the 
following command to deny only write-data access: `icacls filename /deny 
*BU:(WD)`. This forgets about append-data (AD) access. It's still sufficient 
for most applications, which request generic-write access.

----------

_______________________________________
Python tracker <rep...@bugs.python.org>
<https://bugs.python.org/issue42606>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to