@@ -5541,146 +5541,6 @@ os__path_normpath_impl(PyObject *module, PyObject *path)
55415541return result ;
55425542}
55435543
5544- #ifdef MS_WINDOWS
5545-
5546- /* We centralise SECURITY_ATTRIBUTE initialization based around
5547- templates that will probably mostly match common POSIX mode settings.
5548- The _Py_SECURITY_ATTRIBUTE_DATA structure contains temporary data, as
5549- a constructed SECURITY_ATTRIBUTE structure typically refers to memory
5550- that has to be alive while it's being used.
5551-
5552- Typical use will look like:
5553- SECURITY_ATTRIBUTES *pSecAttr = NULL;
5554- struct _Py_SECURITY_ATTRIBUTE_DATA secAttrData;
5555- int error, error2;
5556-
5557- Py_BEGIN_ALLOW_THREADS
5558- switch (mode) {
5559- case 0x1C0: // 0o700
5560- error = initializeMkdir700SecurityAttributes(&pSecAttr, &secAttrData);
5561- break;
5562- ...
5563- default:
5564- error = initializeDefaultSecurityAttributes(&pSecAttr, &secAttrData);
5565- break;
5566- }
5567-
5568- if (!error) {
5569- // do operation, passing pSecAttr
5570- }
5571-
5572- // Unconditionally clear secAttrData.
5573- error2 = clearSecurityAttributes(&pSecAttr, &secAttrData);
5574- if (!error) {
5575- error = error2;
5576- }
5577- Py_END_ALLOW_THREADS
5578-
5579- if (error) {
5580- PyErr_SetFromWindowsErr(error);
5581- return NULL;
5582- }
5583- */
5584-
5585- struct _Py_SECURITY_ATTRIBUTE_DATA {
5586- SECURITY_ATTRIBUTES securityAttributes ;
5587- PACL acl ;
5588- SECURITY_DESCRIPTOR sd ;
5589- EXPLICIT_ACCESS_W ea [4 ];
5590- char sid [64 ];
5591- };
5592-
5593- static int
5594- initializeDefaultSecurityAttributes (
5595- PSECURITY_ATTRIBUTES * securityAttributes ,
5596- struct _Py_SECURITY_ATTRIBUTE_DATA * data
5597- ) {
5598- assert (securityAttributes );
5599- assert (data );
5600- * securityAttributes = NULL ;
5601- memset (data ,0 ,sizeof (* data ));
5602- return 0 ;
5603- }
5604-
5605- static int
5606- initializeMkdir700SecurityAttributes (
5607- PSECURITY_ATTRIBUTES * securityAttributes ,
5608- struct _Py_SECURITY_ATTRIBUTE_DATA * data
5609- ) {
5610- assert (securityAttributes );
5611- assert (data );
5612- * securityAttributes = NULL ;
5613- memset (data ,0 ,sizeof (* data ));
5614-
5615- if (!InitializeSecurityDescriptor (& data -> sd ,SECURITY_DESCRIPTOR_REVISION )
5616- || !SetSecurityDescriptorGroup (& data -> sd ,NULL , TRUE)) {
5617- return GetLastError ();
5618- }
5619-
5620- int use_alias = 0 ;
5621- DWORD cbSid = sizeof (data -> sid );
5622- if (!CreateWellKnownSid (WinCreatorOwnerRightsSid ,NULL , (PSID )data -> sid ,& cbSid )) {
5623- use_alias = 1 ;
5624- }
5625-
5626- data -> securityAttributes .nLength = sizeof (SECURITY_ATTRIBUTES );
5627- data -> ea [0 ].grfAccessPermissions = GENERIC_ALL ;
5628- data -> ea [0 ].grfAccessMode = SET_ACCESS ;
5629- data -> ea [0 ].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT ;
5630- if (use_alias ) {
5631- data -> ea [0 ].Trustee .TrusteeForm = TRUSTEE_IS_NAME ;
5632- data -> ea [0 ].Trustee .TrusteeType = TRUSTEE_IS_ALIAS ;
5633- data -> ea [0 ].Trustee .ptstrName = L"CURRENT_USER" ;
5634- }else {
5635- data -> ea [0 ].Trustee .TrusteeForm = TRUSTEE_IS_SID ;
5636- data -> ea [0 ].Trustee .TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP ;
5637- data -> ea [0 ].Trustee .ptstrName = (LPWCH )(SID * )data -> sid ;
5638- }
5639-
5640- data -> ea [1 ].grfAccessPermissions = GENERIC_ALL ;
5641- data -> ea [1 ].grfAccessMode = SET_ACCESS ;
5642- data -> ea [1 ].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT ;
5643- data -> ea [1 ].Trustee .TrusteeForm = TRUSTEE_IS_NAME ;
5644- data -> ea [1 ].Trustee .TrusteeType = TRUSTEE_IS_ALIAS ;
5645- data -> ea [1 ].Trustee .ptstrName = L"SYSTEM" ;
5646-
5647- data -> ea [2 ].grfAccessPermissions = GENERIC_ALL ;
5648- data -> ea [2 ].grfAccessMode = SET_ACCESS ;
5649- data -> ea [2 ].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT ;
5650- data -> ea [2 ].Trustee .TrusteeForm = TRUSTEE_IS_NAME ;
5651- data -> ea [2 ].Trustee .TrusteeType = TRUSTEE_IS_ALIAS ;
5652- data -> ea [2 ].Trustee .ptstrName = L"ADMINISTRATORS" ;
5653-
5654- int r = SetEntriesInAclW (3 ,data -> ea ,NULL ,& data -> acl );
5655- if (r ) {
5656- return r ;
5657- }
5658- if (!SetSecurityDescriptorDacl (& data -> sd , TRUE,data -> acl , FALSE)) {
5659- return GetLastError ();
5660- }
5661- data -> securityAttributes .lpSecurityDescriptor = & data -> sd ;
5662- * securityAttributes = & data -> securityAttributes ;
5663- return 0 ;
5664- }
5665-
5666- static int
5667- clearSecurityAttributes (
5668- PSECURITY_ATTRIBUTES * securityAttributes ,
5669- struct _Py_SECURITY_ATTRIBUTE_DATA * data
5670- ) {
5671- assert (securityAttributes );
5672- assert (data );
5673- * securityAttributes = NULL ;
5674- if (data -> acl ) {
5675- if (LocalFree ((void * )data -> acl )) {
5676- return GetLastError ();
5677- }
5678- }
5679- return 0 ;
5680- }
5681-
5682- #endif
5683-
56845544/*[clinic input]
56855545os.mkdir
56865546
@@ -5713,8 +5573,8 @@ os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
57135573#ifdef MS_WINDOWS
57145574int error = 0 ;
57155575int pathError = 0 ;
5576+ SECURITY_ATTRIBUTES secAttr = {sizeof (secAttr ) };
57165577SECURITY_ATTRIBUTES * pSecAttr = NULL ;
5717- struct _Py_SECURITY_ATTRIBUTE_DATA secAttrData ;
57185578#endif
57195579#ifdef HAVE_MKDIRAT
57205580int mkdirat_unavailable = 0 ;
@@ -5727,26 +5587,34 @@ os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
57275587
57285588#ifdef MS_WINDOWS
57295589Py_BEGIN_ALLOW_THREADS
5730- switch (mode ) {
5731- case 0x1C0 :// 0o700
5732- error = initializeMkdir700SecurityAttributes (& pSecAttr ,& secAttrData );
5733- break ;
5734- default :
5735- error = initializeDefaultSecurityAttributes (& pSecAttr ,& secAttrData );
5736- break ;
5590+ if (mode == 0700 /* 0o700 */ ) {
5591+ ULONG sdSize ;
5592+ pSecAttr = & secAttr ;
5593+ // Set a discreationary ACL (D) that is protected (P) and includes
5594+ // inheritable (OICI) entries that allow (A) full control (FA) to
5595+ // SYSTEM (SY), Administrators (BA), and the owner (OW).
5596+ if (!ConvertStringSecurityDescriptorToSecurityDescriptorW (
5597+ L"D:P(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;FA;;;OW)" ,
5598+ SDDL_REVISION_1 ,
5599+ & secAttr .lpSecurityDescriptor ,
5600+ & sdSize
5601+ )) {
5602+ error = GetLastError ();
5603+ }
57375604 }
57385605if (!error ) {
57395606result = CreateDirectoryW (path -> wide ,pSecAttr );
5740- error = clearSecurityAttributes (& pSecAttr ,& secAttrData );
5741- }else {
5742- // Ignore error from "clear" - we have a more interesting one already
5743- clearSecurityAttributes (& pSecAttr ,& secAttrData );
5607+ if (secAttr .lpSecurityDescriptor &&
5608+ // uncommonly, LocalFree returns non-zero on error, but still uses
5609+ // GetLastError() to see what the error code is
5610+ LocalFree (secAttr .lpSecurityDescriptor )) {
5611+ error = GetLastError ();
5612+ }
57445613 }
57455614Py_END_ALLOW_THREADS
57465615
57475616if (error ) {
5748- PyErr_SetFromWindowsErr (error );
5749- return NULL ;
5617+ return PyErr_SetFromWindowsErr (error );
57505618 }
57515619if (!result ) {
57525620return path_error (path );