@@ -2417,7 +2417,8 @@ static void fs__chmod(uv_fs_t* req) {
2417
2417
/* Skip this EA if it isn't an SID, or it is "Everyone" or our actual group */
2418
2418
if (pOldEAs [ea_idx ].Trustee .TrusteeForm != TRUSTEE_IS_SID ||
2419
2419
EqualSid (pEASid , psidEveryone ) ||
2420
- EqualSid (pEASid , psidGroup )) {
2420
+ EqualSid (pEASid , psidGroup ) ||
2421
+ EqualSid (pEASid , psidOwner )) {
2421
2422
continue ;
2422
2423
}
2423
2424
@@ -2434,43 +2435,52 @@ static void fs__chmod(uv_fs_t* req) {
2434
2435
}
2435
2436
2436
2437
/* Create an ACE for each triplet (user, group, other) */
2437
- numNewEAs = 8 + 3 * numOtherGroups ;
2438
+ numNewEAs = 7 + 3 * numOtherGroups ;
2438
2439
ea = (PEXPLICIT_ACCESS_W ) malloc (sizeof (EXPLICIT_ACCESS_W )* numNewEAs );
2439
2440
u_mode = ((req -> fs .info .mode & S_IRWXU ) >> 6 );
2440
2441
g_mode = ((req -> fs .info .mode & S_IRWXG ) >> 3 );
2441
- o_mode = ((req -> fs .info .mode & S_IRWXO ) >> 0 );
2442
+
2443
+ /*
2444
+ * Because we do not control the ordering of ACE entries within the ACL that
2445
+ * we're building, the `SetNamedSecurityInfoW()` function call below will
2446
+ * place all DENY entries first, and all `ALLOW` entries second. This
2447
+ * makes it impossible to support e.g. 0o757 permissions, because in order
2448
+ * to support an "allow" for "other", then a "deny" for "group", we are
2449
+ * unable to have an "allow" before the "deny" for "group". To address this,
2450
+ * we simply do not allow the "other" entity to have permissions that "group"
2451
+ * itself does not have.
2452
+ */
2453
+ o_mode = ((req -> fs .info .mode & S_IRWXO ) >> 0 ) & g_mode ;
2442
2454
2443
2455
/* We start by revoking previous permissions for trustees we care about */
2444
2456
build_access_struct (& ea [0 ], psidOwner , TRUSTEE_IS_USER , 0 , REVOKE_ACCESS );
2445
2457
build_access_struct (& ea [1 ], psidGroup , TRUSTEE_IS_GROUP , 0 , REVOKE_ACCESS );
2446
2458
build_access_struct (& ea [2 ], psidEveryone , TRUSTEE_IS_GROUP , 0 , REVOKE_ACCESS );
2447
2459
2448
2460
/*
2449
- * We also add explicit denies to user and group if the user shouldn't have
2450
- * a permission but the group or everyone can, for instance.
2461
+ * We also add explicit denies to user if the group shouldn't have a permission.
2451
2462
*/
2452
- u_deny_mode = (~u_mode ) & (g_mode | o_mode );
2453
- g_deny_mode = (~g_mode ) & o_mode ;
2463
+ u_deny_mode = (~u_mode ) & (g_mode );
2454
2464
build_access_struct (& ea [3 ], psidOwner , TRUSTEE_IS_USER , u_deny_mode , DENY_ACCESS );
2455
- build_access_struct (& ea [4 ], psidGroup , TRUSTEE_IS_GROUP , g_deny_mode , DENY_ACCESS );
2456
2465
2457
2466
/* Next, add explicit allows for (owner, group, other) */
2458
- build_access_struct (& ea [5 ], psidOwner , TRUSTEE_IS_USER , u_mode , SET_ACCESS );
2459
- build_access_struct (& ea [6 ], psidGroup , TRUSTEE_IS_GROUP , g_mode , SET_ACCESS );
2460
- build_access_struct (& ea [7 ], psidEveryone , TRUSTEE_IS_GROUP , o_mode , SET_ACCESS );
2467
+ build_access_struct (& ea [4 ], psidOwner , TRUSTEE_IS_USER , u_mode , SET_ACCESS );
2468
+ build_access_struct (& ea [5 ], psidGroup , TRUSTEE_IS_GROUP , g_mode , SET_ACCESS );
2469
+ build_access_struct (& ea [6 ], psidEveryone , TRUSTEE_IS_GROUP , o_mode , SET_ACCESS );
2461
2470
2462
2471
/*
2463
2472
* Iterate over all old ACEs, looking for groups that we belong to, and setting
2464
2473
* the appropriate access bits for those groups (as g_mode)
2465
2474
*/
2466
- ea_write_idx = 8 ;
2475
+ ea_write_idx = 7 ;
2467
2476
for (ea_idx = 0 ; ea_idx < numOldEAs ; ++ ea_idx ) {
2468
2477
BOOL isMember = FALSE;
2469
2478
PSID pEASid = (PSID )pOldEAs [ea_idx ].Trustee .ptstrName ;
2470
2479
/* Skip this EA if it isn't an SID, or it is "Everyone" or our actual group */
2471
2480
if (pOldEAs [ea_idx ].Trustee .TrusteeForm != TRUSTEE_IS_SID ||
2472
2481
EqualSid (pEASid , psidEveryone ) ||
2473
- EqualSid (pEASid , psidGroup )) {
2482
+ EqualSid (pEASid , psidGroup ) ||
2483
+ EqualSid (pEASid , psidOwner )) {
2474
2484
continue ;
2475
2485
}
2476
2486
0 commit comments