3434#include "pycore_pystate.h" // _PyInterpreterState_GET()
3535#include "pycore_signal.h" // Py_NSIG
3636
37+ #ifdef MS_WINDOWS
38+ # include <aclapi.h> // SetEntriesInAcl
39+ # include <sddl.h> // SDDL_REVISION_1
40+ #endif
41+
3742#include "structmember.h" // PyMemberDef
3843#ifndef MS_WINDOWS
3944# include "posixmodule.h"
@@ -4611,6 +4616,12 @@ os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
46114616/*[clinic end generated code: output=a70446903abe821f input=a61722e1576fab03]*/
46124617{
46134618 int result ;
4619+ #ifdef MS_WINDOWS
4620+ int error = 0 ;
4621+ int pathError = 0 ;
4622+ SECURITY_ATTRIBUTES secAttr = { sizeof (secAttr ) };
4623+ SECURITY_ATTRIBUTES * pSecAttr = NULL ;
4624+ #endif
46144625#ifdef HAVE_MKDIRAT
46154626 int mkdirat_unavailable = 0 ;
46164627#endif
@@ -4622,11 +4633,38 @@ os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
46224633
46234634#ifdef MS_WINDOWS
46244635 Py_BEGIN_ALLOW_THREADS
4625- result = CreateDirectoryW (path -> wide , NULL );
4636+ if (mode == 0700 /* 0o700 */ ) {
4637+ ULONG sdSize ;
4638+ pSecAttr = & secAttr ;
4639+ // Set a discretionary ACL (D) that is protected (P) and includes
4640+ // inheritable (OICI) entries that allow (A) full control (FA) to
4641+ // SYSTEM (SY), Administrators (BA), and the owner (OW).
4642+ if (!ConvertStringSecurityDescriptorToSecurityDescriptorW (
4643+ L"D:P(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;FA;;;OW)" ,
4644+ SDDL_REVISION_1 ,
4645+ & secAttr .lpSecurityDescriptor ,
4646+ & sdSize
4647+ )) {
4648+ error = GetLastError ();
4649+ }
4650+ }
4651+ if (!error ) {
4652+ result = CreateDirectoryW (path -> wide , pSecAttr );
4653+ if (secAttr .lpSecurityDescriptor &&
4654+ // uncommonly, LocalFree returns non-zero on error, but still uses
4655+ // GetLastError() to see what the error code is
4656+ LocalFree (secAttr .lpSecurityDescriptor )) {
4657+ error = GetLastError ();
4658+ }
4659+ }
46264660 Py_END_ALLOW_THREADS
46274661
4628- if (!result )
4662+ if (error ) {
4663+ return PyErr_SetFromWindowsErr (error );
4664+ }
4665+ if (!result ) {
46294666 return path_error (path );
4667+ }
46304668#else
46314669 Py_BEGIN_ALLOW_THREADS
46324670#if HAVE_MKDIRAT
0 commit comments