use of java.nio.MappedByteBuffer in project buck by facebook.
the class LcUuidContentsScrubber method scrubFile.
@Override
public void scrubFile(FileChannel file) throws IOException, ScrubException {
if (!Machos.isMacho(file)) {
return;
}
long size = file.size();
MappedByteBuffer map = file.map(FileChannel.MapMode.READ_WRITE, 0, size);
try {
Machos.setUuid(map, ZERO_UUID);
} catch (Machos.MachoException e) {
throw new ScrubException(e.getMessage());
}
map.rewind();
Hasher hasher = Hashing.sha1().newHasher();
while (map.hasRemaining()) {
hasher.putByte(map.get());
}
map.rewind();
try {
Machos.setUuid(map, Arrays.copyOf(hasher.hash().asBytes(), 16));
} catch (Machos.MachoException e) {
throw new ScrubException(e.getMessage());
}
}
use of java.nio.MappedByteBuffer in project buck by facebook.
the class Machos method relativizeOsoSymbols.
static void relativizeOsoSymbols(FileChannel file, ImmutableCollection<Path> cellRoots) throws IOException, MachoException {
for (Path root : cellRoots) {
Preconditions.checkState(root.isAbsolute());
}
long size = file.size();
MappedByteBuffer map = file.map(FileChannel.MapMode.READ_WRITE, 0, size);
MachoHeader header = getHeader(map);
int symbolTableOffset = 0;
int symbolTableCount = 0;
int stringTableOffset = 0;
int stringTableSizePosition = 0;
int stringTableSize = 0;
boolean symbolTableSegmentFound = false;
int segmentSizePosition = 0;
int segmentSize = 0;
int commandsCount = header.getCommandsCount();
for (int i = 0; i < commandsCount; i++) {
// NOPMD
int commandStart = map.position();
int command = ObjectFileScrubbers.getLittleEndianInt(map);
// NOPMD
int commandSize = ObjectFileScrubbers.getLittleEndianInt(map);
switch(command) {
case LC_SYMTAB:
symbolTableOffset = ObjectFileScrubbers.getLittleEndianInt(map);
symbolTableCount = ObjectFileScrubbers.getLittleEndianInt(map);
stringTableOffset = ObjectFileScrubbers.getLittleEndianInt(map);
stringTableSizePosition = map.position();
stringTableSize = ObjectFileScrubbers.getLittleEndianInt(map);
symbolTableSegmentFound = true;
break;
case LC_SEGMENT:
/* segment name */
ObjectFileScrubbers.getBytes(map, 16);
/* vm address */
ObjectFileScrubbers.getLittleEndianInt(map);
/* vm size */
ObjectFileScrubbers.getLittleEndianInt(map);
int segmentFileOffset = ObjectFileScrubbers.getLittleEndianInt(map);
int segmentFileSizePosition = map.position();
int segmentFileSize = ObjectFileScrubbers.getLittleEndianInt(map);
/* maximum vm protection */
ObjectFileScrubbers.getLittleEndianInt(map);
/* initial vm protection */
ObjectFileScrubbers.getLittleEndianInt(map);
/* number of sections */
ObjectFileScrubbers.getLittleEndianInt(map);
/* flags */
ObjectFileScrubbers.getLittleEndianInt(map);
if (segmentFileOffset + segmentFileSize == size) {
if (segmentSizePosition != 0) {
throw new MachoException("multiple map segment commands map string table");
}
segmentSizePosition = segmentFileSizePosition;
segmentSize = segmentFileSize;
}
break;
case LC_SEGMENT_64:
/* segment name */
ObjectFileScrubbers.getBytes(map, 16);
/* vm address */
ObjectFileScrubbers.getLittleEndianLong(map);
/* vm size */
ObjectFileScrubbers.getLittleEndianLong(map);
long segment64FileOffset = ObjectFileScrubbers.getLittleEndianLong(map);
int segment64FileSizePosition = map.position();
long segment64FileSize = ObjectFileScrubbers.getLittleEndianLong(map);
/* maximum vm protection */
ObjectFileScrubbers.getLittleEndianInt(map);
/* initial vm protection */
ObjectFileScrubbers.getLittleEndianInt(map);
/* number of sections */
ObjectFileScrubbers.getLittleEndianInt(map);
/* flags */
ObjectFileScrubbers.getLittleEndianInt(map);
if (segment64FileOffset + segment64FileSize == size) {
if (segmentSizePosition != 0) {
throw new MachoException("multiple map segment commands map string table");
}
segmentSizePosition = segment64FileSizePosition;
if (segment64FileSize > Ints.MAX_POWER_OF_TWO) {
throw new MachoException("map segment file size too big");
}
segmentSize = (int) segment64FileSize;
}
break;
}
map.position(commandStart + commandSize);
}
if (!symbolTableSegmentFound) {
throw new MachoException("LC_SYMTAB command not found");
}
if (stringTableOffset + stringTableSize != size) {
throw new MachoException("String table does not end at end of file");
}
if (stringTableSize == 0) {
return;
}
if (segmentSizePosition == 0 || segmentSize == 0) {
throw new MachoException("LC_SEGMENT or LC_SEGMENT_64 command for string table not found");
}
map.position(stringTableOffset);
if (map.get() != 0x20) {
throw new MachoException("First character in the string table is not a space");
}
if (map.get() != 0x00) {
throw new MachoException("Second character in the string table is not a NUL");
}
int currentStringTableOffset = map.position();
byte[] stringTableBytes = new byte[stringTableSize];
map.position(stringTableOffset);
map.get(stringTableBytes);
ByteBuffer stringTable = ByteBuffer.wrap(stringTableBytes);
map.position(symbolTableOffset);
Map<Integer, Integer> strings = new HashMap<>();
for (int i = 0; i < symbolTableCount; i++) {
int stringTableIndexPosition = map.position();
int stringTableIndex = ObjectFileScrubbers.getLittleEndianInt(map);
byte type = map.get();
/* section */
map.get();
/* description */
ObjectFileScrubbers.getLittleEndianShort(map);
int valuePosition = map.position();
if (header.getIs64Bit()) {
/* value */
ObjectFileScrubbers.getLittleEndianLong(map);
} else {
/* value */
ObjectFileScrubbers.getLittleEndianInt(map);
}
if (stringTableIndex < 2) {
continue;
}
int position = map.position();
try {
int newStringTableIndex;
if (strings.containsKey(stringTableIndex)) {
newStringTableIndex = strings.get(stringTableIndex);
} else {
stringTable.position(stringTableIndex);
String string = ObjectFileScrubbers.getAsciiString(stringTable);
if (type == N_OSO) {
for (Path root : cellRoots) {
String rootPrefix = root + "/";
Optional<String> fixed = MoreStrings.stripPrefix(string, rootPrefix).map(input -> "./" + input);
if (fixed.isPresent()) {
string = fixed.get();
break;
}
}
map.position(valuePosition);
int lastModifiedValue = ObjectFileCommonModificationDate.COMMON_MODIFICATION_TIME_STAMP;
if (header.getIs64Bit()) {
ObjectFileScrubbers.putLittleEndianLong(map, lastModifiedValue);
} else {
ObjectFileScrubbers.putLittleEndianInt(map, lastModifiedValue);
}
}
map.position(currentStringTableOffset);
ObjectFileScrubbers.putAsciiString(map, string);
newStringTableIndex = currentStringTableOffset - stringTableOffset;
currentStringTableOffset = map.position();
strings.put(stringTableIndex, newStringTableIndex);
}
map.position(stringTableIndexPosition);
ObjectFileScrubbers.putLittleEndianInt(map, newStringTableIndex);
} finally {
map.position(position);
}
}
map.position(stringTableSizePosition);
int newStringTableSize = currentStringTableOffset - stringTableOffset;
ObjectFileScrubbers.putLittleEndianInt(map, newStringTableSize);
map.position(segmentSizePosition);
ObjectFileScrubbers.putLittleEndianInt(map, segmentSize + (newStringTableSize - stringTableSize));
file.truncate(currentStringTableOffset);
}
use of java.nio.MappedByteBuffer in project buck by facebook.
the class Machos method isMacho.
static boolean isMacho(FileChannel file) throws IOException {
MappedByteBuffer map = file.map(FileChannel.MapMode.READ_ONLY, 0, MH_MAGIC.length);
byte[] magic = ObjectFileScrubbers.getBytes(map, MH_MAGIC.length);
return Arrays.equals(MH_MAGIC, magic) || Arrays.equals(MH_CIGAM, magic) || Arrays.equals(MH_MAGIC_64, magic) || Arrays.equals(MH_CIGAM_64, magic);
}
use of java.nio.MappedByteBuffer in project buck by facebook.
the class MungingDebugPathSanitizer method restore.
protected void restore(Path path, ByteBufferReplacer replacer) throws IOException {
try (FileChannel channel = FileChannel.open(path, READ, WRITE)) {
MappedByteBuffer buffer = channel.map(READ_WRITE, 0, channel.size());
restore(buffer, replacer);
}
}
use of java.nio.MappedByteBuffer in project buck by facebook.
the class ElfDynamicSectionScrubberStepTest method test.
@Test
public void test() throws IOException {
ProjectWorkspace workspace = TestDataHelper.createProjectWorkspaceForScenario(this, "elf_shared_lib", tmp);
workspace.setUp();
ElfDynamicSectionScrubberStep step = ElfDynamicSectionScrubberStep.of(new ProjectFilesystem(tmp.getRoot()), tmp.getRoot().getFileSystem().getPath("libfoo.so"));
step.execute(TestExecutionContext.newInstance());
// Verify that the relevant dynamic section tag have been zero'd out.
try (FileChannel channel = FileChannel.open(step.getFilesystem().resolve(step.getPath()), StandardOpenOption.READ)) {
MappedByteBuffer buffer = channel.map(READ_ONLY, 0, channel.size());
Elf elf = new Elf(buffer);
Optional<ElfSection> section = elf.getSectionByName(ElfDynamicSectionScrubberStep.SECTION).map(Pair::getSecond);
for (ByteBuffer body = section.get().body; body.hasRemaining(); ) {
ElfDynamicSection.DTag dTag = ElfDynamicSection.DTag.valueOf(elf.header.ei_class == ElfHeader.EIClass.ELFCLASS32 ? Elf.Elf32.getElf32Sword(body) : (int) Elf.Elf64.getElf64Sxword(body));
long dPtr = elf.header.ei_class == ElfHeader.EIClass.ELFCLASS32 ? Elf.Elf32.getElf32Addr(body) : Elf.Elf64.getElf64Addr(body);
if (!ElfDynamicSectionScrubberStep.WHITELISTED_TAGS.contains(dTag)) {
assertThat(dPtr, Matchers.equalTo(0L));
}
}
}
}
Aggregations