|
@@ -19,11 +19,14 @@ package org.apache.hadoop.hdfs.server.namenode;
|
|
|
|
|
|
import java.io.IOException;
|
|
import java.io.IOException;
|
|
import java.util.ArrayList;
|
|
import java.util.ArrayList;
|
|
|
|
+import java.util.Arrays;
|
|
import java.util.Collection;
|
|
import java.util.Collection;
|
|
import java.util.List;
|
|
import java.util.List;
|
|
import java.util.Stack;
|
|
import java.util.Stack;
|
|
|
|
|
|
import com.google.common.base.Preconditions;
|
|
import com.google.common.base.Preconditions;
|
|
|
|
+import org.apache.hadoop.fs.Path;
|
|
|
|
+import org.apache.hadoop.hdfs.server.common.HdfsServerConstants;
|
|
import org.apache.hadoop.ipc.CallerContext;
|
|
import org.apache.hadoop.ipc.CallerContext;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
import org.slf4j.LoggerFactory;
|
|
@@ -207,7 +210,7 @@ public class FSPermissionChecker implements AccessControlEnforcer {
|
|
final INodeAttributes[] inodeAttrs = new INodeAttributes[inodes.length];
|
|
final INodeAttributes[] inodeAttrs = new INodeAttributes[inodes.length];
|
|
final byte[][] components = inodesInPath.getPathComponents();
|
|
final byte[][] components = inodesInPath.getPathComponents();
|
|
for (int i = 0; i < inodes.length && inodes[i] != null; i++) {
|
|
for (int i = 0; i < inodes.length && inodes[i] != null; i++) {
|
|
- inodeAttrs[i] = getINodeAttrs(components, i, inodes[i], snapshotId);
|
|
|
|
|
|
+ inodeAttrs[i] = getINodeAttrs(inodes[i], snapshotId);
|
|
}
|
|
}
|
|
|
|
|
|
String path = inodesInPath.getPath();
|
|
String path = inodesInPath.getPath();
|
|
@@ -257,8 +260,7 @@ public class FSPermissionChecker implements AccessControlEnforcer {
|
|
void checkPermission(INode inode, int snapshotId, FsAction access)
|
|
void checkPermission(INode inode, int snapshotId, FsAction access)
|
|
throws AccessControlException {
|
|
throws AccessControlException {
|
|
byte[][] pathComponents = inode.getPathComponents();
|
|
byte[][] pathComponents = inode.getPathComponents();
|
|
- INodeAttributes nodeAttributes = getINodeAttrs(pathComponents,
|
|
|
|
- pathComponents.length - 1, inode, snapshotId);
|
|
|
|
|
|
+ INodeAttributes nodeAttributes = getINodeAttrs(inode, snapshotId);
|
|
try {
|
|
try {
|
|
INodeAttributes[] iNodeAttr = {nodeAttributes};
|
|
INodeAttributes[] iNodeAttr = {nodeAttributes};
|
|
AccessControlEnforcer enforcer = getAccessControlEnforcer();
|
|
AccessControlEnforcer enforcer = getAccessControlEnforcer();
|
|
@@ -367,23 +369,31 @@ public class FSPermissionChecker implements AccessControlEnforcer {
|
|
authzContext.getSubAccess(), authzContext.isIgnoreEmptyDir());
|
|
authzContext.getSubAccess(), authzContext.isIgnoreEmptyDir());
|
|
}
|
|
}
|
|
|
|
|
|
- private INodeAttributes getINodeAttrs(byte[][] pathByNameArr, int pathIdx,
|
|
|
|
- INode inode, int snapshotId) {
|
|
|
|
|
|
+ private INodeAttributes getINodeAttrs(INode inode, int snapshotId) {
|
|
INodeAttributes inodeAttrs = inode.getSnapshotINode(snapshotId);
|
|
INodeAttributes inodeAttrs = inode.getSnapshotINode(snapshotId);
|
|
|
|
+ /**
|
|
|
|
+ * This logic is similar to {@link FSDirectory#getAttributes()} and it
|
|
|
|
+ * ensures that the attribute provider sees snapshot paths resolved to their
|
|
|
|
+ * original location. This means the attributeProvider can apply permissions
|
|
|
|
+ * to the snapshot paths in the same was as the live paths. See HDFS-15372.
|
|
|
|
+ */
|
|
if (getAttributesProvider() != null) {
|
|
if (getAttributesProvider() != null) {
|
|
- String[] elements = new String[pathIdx + 1];
|
|
|
|
/**
|
|
/**
|
|
- * {@link INode#getPathComponents(String)} returns a null component
|
|
|
|
- * for the root only path "/". Assign an empty string if so.
|
|
|
|
|
|
+ * If we have an inode representing a path like /d/.snapshot/snap1
|
|
|
|
+ * then calling inode.getPathComponents returns [null, d, snap1]. If we
|
|
|
|
+ * call inode.getFullPathName() it will return /d/.snapshot/snap1. For
|
|
|
|
+ * this special path (snapshot root) the attribute provider should see:
|
|
|
|
+ *
|
|
|
|
+ * [null, d, .snapshot/snap1]
|
|
|
|
+ *
|
|
|
|
+ * Using IIP.resolveFromRoot, it will take the inode fullPathName and
|
|
|
|
+ * construct an IIP object that give the correct components as above.
|
|
*/
|
|
*/
|
|
- if (pathByNameArr.length == 1 && pathByNameArr[0] == null) {
|
|
|
|
- elements[0] = "";
|
|
|
|
- } else {
|
|
|
|
- for (int i = 0; i < elements.length; i++) {
|
|
|
|
- elements[i] = DFSUtil.bytes2String(pathByNameArr[i]);
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- inodeAttrs = getAttributesProvider().getAttributes(elements, inodeAttrs);
|
|
|
|
|
|
+ INodesInPath iip = INodesInPath.resolveFromRoot(inode);
|
|
|
|
+ byte[][] components = iip.getPathComponents();
|
|
|
|
+ components = Arrays.copyOfRange(components, 1, components.length);
|
|
|
|
+ inodeAttrs = getAttributesProvider()
|
|
|
|
+ .getAttributes(components, inodeAttrs);
|
|
}
|
|
}
|
|
return inodeAttrs;
|
|
return inodeAttrs;
|
|
}
|
|
}
|
|
@@ -439,7 +449,7 @@ public class FSPermissionChecker implements AccessControlEnforcer {
|
|
if (!(cList.isEmpty() && ignoreEmptyDir)) {
|
|
if (!(cList.isEmpty() && ignoreEmptyDir)) {
|
|
//TODO have to figure this out with inodeattribute provider
|
|
//TODO have to figure this out with inodeattribute provider
|
|
INodeAttributes inodeAttr =
|
|
INodeAttributes inodeAttr =
|
|
- getINodeAttrs(components, pathIdx, d, snapshotId);
|
|
|
|
|
|
+ getINodeAttrs(d, snapshotId);
|
|
if (!hasPermission(inodeAttr, access)) {
|
|
if (!hasPermission(inodeAttr, access)) {
|
|
throw new AccessControlException(
|
|
throw new AccessControlException(
|
|
toAccessControlString(inodeAttr, d.getFullPathName(), access));
|
|
toAccessControlString(inodeAttr, d.getFullPathName(), access));
|
|
@@ -457,7 +467,7 @@ public class FSPermissionChecker implements AccessControlEnforcer {
|
|
if (inodeAttr.getFsPermission().getStickyBit()) {
|
|
if (inodeAttr.getFsPermission().getStickyBit()) {
|
|
for (INode child : cList) {
|
|
for (INode child : cList) {
|
|
INodeAttributes childInodeAttr =
|
|
INodeAttributes childInodeAttr =
|
|
- getINodeAttrs(components, pathIdx, child, snapshotId);
|
|
|
|
|
|
+ getINodeAttrs(child, snapshotId);
|
|
if (isStickyBitViolated(inodeAttr, childInodeAttr)) {
|
|
if (isStickyBitViolated(inodeAttr, childInodeAttr)) {
|
|
List<byte[]> allComponentList = new ArrayList<>();
|
|
List<byte[]> allComponentList = new ArrayList<>();
|
|
for (int i = 0; i <= pathIdx; ++i) {
|
|
for (int i = 0; i <= pathIdx; ++i) {
|