HDFS-5849. Removing ACL from an inode fails if it has only a default ACL. Contributed by Chris Nauroth.

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/branches/HDFS-4685@1563205 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Chris Nauroth 2014-01-31 18:33:56 +00:00
parent 7a03dc0482
commit c654c2e8b9
3 changed files with 37 additions and 11 deletions

View File

@ -67,3 +67,6 @@ HDFS-4685 (Unreleased)
HADOOP-10277. setfacl -x fails to parse ACL spec if trying to remove the HADOOP-10277. setfacl -x fails to parse ACL spec if trying to remove the
mask entry. (Vinay via cnauroth) mask entry. (Vinay via cnauroth)
HDFS-5849. Removing ACL from an inode fails if it has only a default ACL.
(cnauroth)

View File

@ -26,6 +26,7 @@ import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.fs.permission.AclEntry; import org.apache.hadoop.fs.permission.AclEntry;
import org.apache.hadoop.fs.permission.AclEntryScope; import org.apache.hadoop.fs.permission.AclEntryScope;
import org.apache.hadoop.fs.permission.AclEntryType; import org.apache.hadoop.fs.permission.AclEntryType;
import org.apache.hadoop.fs.permission.FsAction;
import org.apache.hadoop.fs.permission.FsPermission; import org.apache.hadoop.fs.permission.FsPermission;
import org.apache.hadoop.hdfs.protocol.AclException; import org.apache.hadoop.hdfs.protocol.AclException;
import org.apache.hadoop.hdfs.protocol.QuotaExceededException; import org.apache.hadoop.hdfs.protocol.QuotaExceededException;
@ -157,22 +158,27 @@ final class AclStorage {
int snapshotId) throws QuotaExceededException { int snapshotId) throws QuotaExceededException {
FsPermission perm = inode.getPermissionStatus(snapshotId).getPermission(); FsPermission perm = inode.getPermissionStatus(snapshotId).getPermission();
if (perm.getAclBit()) { if (perm.getAclBit()) {
// Restore group permissions from the feature's entry to permission bits,
// overwriting the mask, which is not part of a minimal ACL.
List<AclEntry> featureEntries = inode.getAclFeature().getEntries(); List<AclEntry> featureEntries = inode.getAclFeature().getEntries();
AclEntry groupEntryKey = new AclEntry.Builder() final FsAction groupPerm;
.setScope(AclEntryScope.ACCESS) if (featureEntries.get(0).getScope() == AclEntryScope.ACCESS) {
.setType(AclEntryType.GROUP) // Restore group permissions from the feature's entry to permission
.build(); // bits, overwriting the mask, which is not part of a minimal ACL.
int groupEntryIndex = Collections.binarySearch(featureEntries, AclEntry groupEntryKey = new AclEntry.Builder()
groupEntryKey, AclTransformation.ACL_ENTRY_COMPARATOR); .setScope(AclEntryScope.ACCESS)
assert groupEntryIndex >= 0; .setType(AclEntryType.GROUP)
.build();
int groupEntryIndex = Collections.binarySearch(featureEntries,
groupEntryKey, AclTransformation.ACL_ENTRY_COMPARATOR);
assert groupEntryIndex >= 0;
groupPerm = featureEntries.get(groupEntryIndex).getPermission();
} else {
groupPerm = perm.getGroupAction();
}
// Remove the feature and turn off the ACL bit. // Remove the feature and turn off the ACL bit.
inode.removeAclFeature(); inode.removeAclFeature();
FsPermission newPerm = new FsPermission(perm.getUserAction(), FsPermission newPerm = new FsPermission(perm.getUserAction(),
featureEntries.get(groupEntryIndex).getPermission(), groupPerm, perm.getOtherAction(),
perm.getOtherAction(),
perm.getStickyBit(), false); perm.getStickyBit(), false);
inode.setPermission(newPerm, snapshotId); inode.setPermission(newPerm, snapshotId);
} }

View File

@ -535,6 +535,23 @@ public class TestNameNodeAcl {
assertAclFeature(false); assertAclFeature(false);
} }
@Test
public void testRemoveAclOnlyDefault() throws IOException {
FileSystem.mkdirs(fs, path, FsPermission.createImmutable((short)0750));
List<AclEntry> aclSpec = Lists.newArrayList(
aclEntry(ACCESS, USER, ALL),
aclEntry(ACCESS, GROUP, READ_EXECUTE),
aclEntry(ACCESS, OTHER, NONE),
aclEntry(DEFAULT, USER, "foo", ALL));
fs.setAcl(path, aclSpec);
fs.removeAcl(path);
AclStatus s = fs.getAclStatus(path);
AclEntry[] returned = s.getEntries().toArray(new AclEntry[0]);
assertArrayEquals(new AclEntry[] { }, returned);
assertPermission((short)0750);
assertAclFeature(false);
}
@Test(expected=FileNotFoundException.class) @Test(expected=FileNotFoundException.class)
public void testRemoveAclPathNotFound() throws IOException { public void testRemoveAclPathNotFound() throws IOException {
// Path has not been created. // Path has not been created.