Search in sources :

Example 11 with MappedByteBuffer

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());
    }
}
Also used : Hasher(com.google.common.hash.Hasher) MappedByteBuffer(java.nio.MappedByteBuffer)

Example 12 with MappedByteBuffer

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);
}
Also used : Path(java.nio.file.Path) HashMap(java.util.HashMap) ByteBuffer(java.nio.ByteBuffer) MappedByteBuffer(java.nio.MappedByteBuffer) MappedByteBuffer(java.nio.MappedByteBuffer)

Example 13 with MappedByteBuffer

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);
}
Also used : MappedByteBuffer(java.nio.MappedByteBuffer)

Example 14 with MappedByteBuffer

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);
    }
}
Also used : MappedByteBuffer(java.nio.MappedByteBuffer) FileChannel(java.nio.channels.FileChannel)

Example 15 with MappedByteBuffer

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));
            }
        }
    }
}
Also used : ElfDynamicSection(com.facebook.buck.cxx.elf.ElfDynamicSection) FileChannel(java.nio.channels.FileChannel) ElfSection(com.facebook.buck.cxx.elf.ElfSection) ByteBuffer(java.nio.ByteBuffer) MappedByteBuffer(java.nio.MappedByteBuffer) ProjectWorkspace(com.facebook.buck.testutil.integration.ProjectWorkspace) MappedByteBuffer(java.nio.MappedByteBuffer) ProjectFilesystem(com.facebook.buck.io.ProjectFilesystem) Elf(com.facebook.buck.cxx.elf.Elf) Pair(com.facebook.buck.model.Pair) Test(org.junit.Test)

Aggregations

MappedByteBuffer (java.nio.MappedByteBuffer)147 FileChannel (java.nio.channels.FileChannel)71 IOException (java.io.IOException)40 File (java.io.File)34 RandomAccessFile (java.io.RandomAccessFile)33 FileInputStream (java.io.FileInputStream)27 ByteBuffer (java.nio.ByteBuffer)24 Test (org.junit.Test)18 Path (java.nio.file.Path)11 ProjectWorkspace (com.facebook.buck.testutil.integration.ProjectWorkspace)9 Elf (com.facebook.buck.cxx.elf.Elf)8 FileOutputStream (java.io.FileOutputStream)7 ElfSection (com.facebook.buck.cxx.elf.ElfSection)6 ProjectFilesystem (com.facebook.buck.io.ProjectFilesystem)4 FileNotFoundException (java.io.FileNotFoundException)4 UnsafeBuffer (org.agrona.concurrent.UnsafeBuffer)4 Pair (com.facebook.buck.model.Pair)3 Date (java.util.Date)3 NulTerminatedCharsetDecoder (com.facebook.buck.charset.NulTerminatedCharsetDecoder)2 ElfDynamicSection (com.facebook.buck.cxx.elf.ElfDynamicSection)2