Skip to content

Commit a30cbb2

Browse files
committed
Use language-invariant ACL
1 parent b1d09a7 commit a30cbb2

File tree

1 file changed

+22
-155
lines changed

1 file changed

+22
-155
lines changed

Modules/posixmodule.c

Lines changed: 22 additions & 155 deletions
Original file line numberDiff line numberDiff line change
@@ -4431,147 +4431,6 @@ os__path_splitroot_impl(PyObject *module, path_t *path)
44314431

44324432
#endif /* MS_WINDOWS */
44334433

4434-
4435-
#ifdef MS_WINDOWS
4436-
4437-
/* We centralise SECURITY_ATTRIBUTE initialization based around
4438-
templates that will probably mostly match common POSIX mode settings.
4439-
The _Py_SECURITY_ATTRIBUTE_DATA structure contains temporary data, as
4440-
a constructed SECURITY_ATTRIBUTE structure typically refers to memory
4441-
that has to be alive while it's being used.
4442-
4443-
Typical use will look like:
4444-
SECURITY_ATTRIBUTES *pSecAttr = NULL;
4445-
struct _Py_SECURITY_ATTRIBUTE_DATA secAttrData;
4446-
int error, error2;
4447-
4448-
Py_BEGIN_ALLOW_THREADS
4449-
switch (mode) {
4450-
case 0x1C0: // 0o700
4451-
error = initializeMkdir700SecurityAttributes(&pSecAttr, &secAttrData);
4452-
break;
4453-
...
4454-
default:
4455-
error = initializeDefaultSecurityAttributes(&pSecAttr, &secAttrData);
4456-
break;
4457-
}
4458-
4459-
if (!error) {
4460-
// do operation, passing pSecAttr
4461-
}
4462-
4463-
// Unconditionally clear secAttrData.
4464-
error2 = clearSecurityAttributes(&pSecAttr, &secAttrData);
4465-
if (!error) {
4466-
error = error2;
4467-
}
4468-
Py_END_ALLOW_THREADS
4469-
4470-
if (error) {
4471-
PyErr_SetFromWindowsErr(error);
4472-
return NULL;
4473-
}
4474-
*/
4475-
4476-
struct _Py_SECURITY_ATTRIBUTE_DATA {
4477-
SECURITY_ATTRIBUTES securityAttributes;
4478-
PACL acl;
4479-
SECURITY_DESCRIPTOR sd;
4480-
EXPLICIT_ACCESS_W ea[4];
4481-
char sid[64];
4482-
};
4483-
4484-
static int
4485-
initializeDefaultSecurityAttributes(
4486-
PSECURITY_ATTRIBUTES *securityAttributes,
4487-
struct _Py_SECURITY_ATTRIBUTE_DATA *data
4488-
) {
4489-
assert(securityAttributes);
4490-
assert(data);
4491-
*securityAttributes = NULL;
4492-
memset(data, 0, sizeof(*data));
4493-
return 0;
4494-
}
4495-
4496-
static int
4497-
initializeMkdir700SecurityAttributes(
4498-
PSECURITY_ATTRIBUTES *securityAttributes,
4499-
struct _Py_SECURITY_ATTRIBUTE_DATA *data
4500-
) {
4501-
assert(securityAttributes);
4502-
assert(data);
4503-
*securityAttributes = NULL;
4504-
memset(data, 0, sizeof(*data));
4505-
4506-
if (!InitializeSecurityDescriptor(&data->sd, SECURITY_DESCRIPTOR_REVISION)
4507-
|| !SetSecurityDescriptorGroup(&data->sd, NULL, TRUE)) {
4508-
return GetLastError();
4509-
}
4510-
4511-
int use_alias = 0;
4512-
DWORD cbSid = sizeof(data->sid);
4513-
if (!CreateWellKnownSid(WinCreatorOwnerRightsSid, NULL, (PSID)data->sid, &cbSid)) {
4514-
use_alias = 1;
4515-
}
4516-
4517-
data->securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
4518-
data->ea[0].grfAccessPermissions = GENERIC_ALL;
4519-
data->ea[0].grfAccessMode = SET_ACCESS;
4520-
data->ea[0].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
4521-
if (use_alias) {
4522-
data->ea[0].Trustee.TrusteeForm = TRUSTEE_IS_NAME;
4523-
data->ea[0].Trustee.TrusteeType = TRUSTEE_IS_ALIAS;
4524-
data->ea[0].Trustee.ptstrName = L"CURRENT_USER";
4525-
} else {
4526-
data->ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID;
4527-
data->ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
4528-
data->ea[0].Trustee.ptstrName = (LPWCH)(SID*)data->sid;
4529-
}
4530-
4531-
data->ea[1].grfAccessPermissions = GENERIC_ALL;
4532-
data->ea[1].grfAccessMode = SET_ACCESS;
4533-
data->ea[1].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
4534-
data->ea[1].Trustee.TrusteeForm = TRUSTEE_IS_NAME;
4535-
data->ea[1].Trustee.TrusteeType = TRUSTEE_IS_ALIAS;
4536-
data->ea[1].Trustee.ptstrName = L"SYSTEM";
4537-
4538-
data->ea[2].grfAccessPermissions = GENERIC_ALL;
4539-
data->ea[2].grfAccessMode = SET_ACCESS;
4540-
data->ea[2].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
4541-
data->ea[2].Trustee.TrusteeForm = TRUSTEE_IS_NAME;
4542-
data->ea[2].Trustee.TrusteeType = TRUSTEE_IS_ALIAS;
4543-
data->ea[2].Trustee.ptstrName = L"ADMINISTRATORS";
4544-
4545-
int r = SetEntriesInAclW(3, data->ea, NULL, &data->acl);
4546-
if (r) {
4547-
return r;
4548-
}
4549-
if (!SetSecurityDescriptorDacl(&data->sd, TRUE, data->acl, FALSE)) {
4550-
return GetLastError();
4551-
}
4552-
data->securityAttributes.lpSecurityDescriptor = &data->sd;
4553-
*securityAttributes = &data->securityAttributes;
4554-
return 0;
4555-
}
4556-
4557-
static int
4558-
clearSecurityAttributes(
4559-
PSECURITY_ATTRIBUTES *securityAttributes,
4560-
struct _Py_SECURITY_ATTRIBUTE_DATA *data
4561-
) {
4562-
assert(securityAttributes);
4563-
assert(data);
4564-
*securityAttributes = NULL;
4565-
if (data->acl) {
4566-
if (LocalFree((void *)data->acl)) {
4567-
return GetLastError();
4568-
}
4569-
}
4570-
return 0;
4571-
}
4572-
4573-
#endif
4574-
45754434
/*[clinic input]
45764435
os.mkdir
45774436
@@ -4603,8 +4462,8 @@ os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
46034462
#ifdef MS_WINDOWS
46044463
int error = 0;
46054464
int pathError = 0;
4465+
SECURITY_ATTRIBUTES secAttr = { sizeof(secAttr) };
46064466
SECURITY_ATTRIBUTES *pSecAttr = NULL;
4607-
struct _Py_SECURITY_ATTRIBUTE_DATA secAttrData;
46084467
#endif
46094468
#ifdef HAVE_MKDIRAT
46104469
int mkdirat_unavailable = 0;
@@ -4617,26 +4476,34 @@ os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd)
46174476

46184477
#ifdef MS_WINDOWS
46194478
Py_BEGIN_ALLOW_THREADS
4620-
switch (mode) {
4621-
case 0x1C0: // 0o700
4622-
error = initializeMkdir700SecurityAttributes(&pSecAttr, &secAttrData);
4623-
break;
4624-
default:
4625-
error = initializeDefaultSecurityAttributes(&pSecAttr, &secAttrData);
4626-
break;
4479+
if (mode == 0700 /* 0o700 */) {
4480+
ULONG sdSize;
4481+
pSecAttr = &secAttr;
4482+
// Set a discreationary ACL (D) that is protected (P) and includes
4483+
// inheritable (OICI) entries that allow (A) full control (FA) to
4484+
// SYSTEM (SY), Administrators (BA), and the owner (OW).
4485+
if (!ConvertStringSecurityDescriptorToSecurityDescriptorW(
4486+
L"D:P(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;FA;;;OW)",
4487+
SDDL_REVISION_1,
4488+
&secAttr.lpSecurityDescriptor,
4489+
&sdSize
4490+
)) {
4491+
error = GetLastError();
4492+
}
46274493
}
46284494
if (!error) {
46294495
result = CreateDirectoryW(path->wide, pSecAttr);
4630-
error = clearSecurityAttributes(&pSecAttr, &secAttrData);
4631-
} else {
4632-
// Ignore error from "clear" - we have a more interesting one already
4633-
clearSecurityAttributes(&pSecAttr, &secAttrData);
4496+
if (secAttr.lpSecurityDescriptor &&
4497+
// uncommonly, LocalFree returns non-zero on error, but still uses
4498+
// GetLastError() to see what the error code is
4499+
LocalFree(secAttr.lpSecurityDescriptor)) {
4500+
error = GetLastError();
4501+
}
46344502
}
46354503
Py_END_ALLOW_THREADS
46364504

46374505
if (error) {
4638-
PyErr_SetFromWindowsErr(error);
4639-
return NULL;
4506+
return PyErr_SetFromWindowsErr(error);
46404507
}
46414508
if (!result) {
46424509
return path_error(path);

0 commit comments

Comments
 (0)