Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(43)

Side by Side Diff: chrome/utility/safe_browsing/mac/udif.cc

Issue 2926473002: Mac Archive Type Sniffing (Closed)
Patch Set: added check that ParseTrailer() is only called once Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/utility/safe_browsing/mac/udif.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/utility/safe_browsing/mac/udif.h" 5 #include "chrome/utility/safe_browsing/mac/udif.h"
6 6
7 #include <CoreFoundation/CoreFoundation.h> 7 #include <CoreFoundation/CoreFoundation.h>
8 #include <bzlib.h> 8 #include <bzlib.h>
9 #include <libkern/OSByteOrder.h> 9 #include <libkern/OSByteOrder.h>
10 #include <uuid/uuid.h> 10 #include <uuid/uuid.h>
(...skipping 15 matching lines...) Expand all
26 namespace safe_browsing { 26 namespace safe_browsing {
27 namespace dmg { 27 namespace dmg {
28 28
29 #pragma pack(push, 1) 29 #pragma pack(push, 1)
30 30
31 // The following structures come from the analysis provided by Jonathan Levin 31 // The following structures come from the analysis provided by Jonathan Levin
32 // at <http://newosxbook.com/DMG.html>. 32 // at <http://newosxbook.com/DMG.html>.
33 // 33 //
34 // Note that all fields are stored in big endian. 34 // Note that all fields are stored in big endian.
35 35
36 struct UDIFChecksum {
37 uint32_t type;
38 uint32_t size;
39 uint32_t data[32];
40 };
41
42 static void ConvertBigEndian(UDIFChecksum* checksum) { 36 static void ConvertBigEndian(UDIFChecksum* checksum) {
43 ConvertBigEndian(&checksum->type); 37 ConvertBigEndian(&checksum->type);
44 ConvertBigEndian(&checksum->size); 38 ConvertBigEndian(&checksum->size);
45 for (size_t i = 0; i < arraysize(checksum->data); ++i) { 39 for (size_t i = 0; i < arraysize(checksum->data); ++i) {
46 ConvertBigEndian(&checksum->data[i]); 40 ConvertBigEndian(&checksum->data[i]);
47 } 41 }
48 } 42 }
49 43
50 // The trailer structure for a UDIF file.
51 struct UDIFResourceFile {
52 static const uint32_t kSignature = 'koly';
53 static const uint32_t kVersion = 4;
54
55 uint32_t signature;
56 uint32_t version;
57 uint32_t header_size; // Size of this structure.
58 uint32_t flags;
59 uint64_t running_data_fork_offset;
60 uint64_t data_fork_offset;
61 uint64_t data_fork_length;
62 uint64_t rsrc_fork_offset;
63 uint64_t rsrc_fork_length;
64 uint32_t segment_number;
65 uint32_t segment_count;
66 uuid_t segment_id;
67
68 UDIFChecksum data_checksum;
69
70 uint64_t plist_offset; // Offset and length of the blkx plist.
71 uint64_t plist_length;
72
73 uint8_t reserved1[64];
74
75 uint64_t code_signature_offset;
76 uint64_t code_signature_length;
77
78 uint8_t reserved2[40];
79
80 UDIFChecksum master_checksum;
81
82 uint32_t image_variant;
83 uint64_t sector_count;
84
85 uint32_t reserved3;
86 uint32_t reserved4;
87 uint32_t reserved5;
88 };
89
90 static void ConvertBigEndian(uuid_t* uuid) { 44 static void ConvertBigEndian(uuid_t* uuid) {
91 // UUID is never consulted, so do not swap. 45 // UUID is never consulted, so do not swap.
92 } 46 }
93 47
94 static void ConvertBigEndian(UDIFResourceFile* file) { 48 static void ConvertBigEndian(UDIFResourceFile* file) {
95 ConvertBigEndian(&file->signature); 49 ConvertBigEndian(&file->signature);
96 ConvertBigEndian(&file->version); 50 ConvertBigEndian(&file->version);
97 ConvertBigEndian(&file->flags); 51 ConvertBigEndian(&file->flags);
98 ConvertBigEndian(&file->header_size); 52 ConvertBigEndian(&file->header_size);
99 ConvertBigEndian(&file->running_data_fork_offset); 53 ConvertBigEndian(&file->running_data_fork_offset);
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
341 295
342 DISALLOW_COPY_AND_ASSIGN(UDIFBlockChunkReadStream); 296 DISALLOW_COPY_AND_ASSIGN(UDIFBlockChunkReadStream);
343 }; 297 };
344 298
345 } // namespace 299 } // namespace
346 300
347 UDIFParser::UDIFParser(ReadStream* stream) 301 UDIFParser::UDIFParser(ReadStream* stream)
348 : stream_(stream), 302 : stream_(stream),
349 partition_names_(), 303 partition_names_(),
350 blocks_(), 304 blocks_(),
351 block_size_(kSectorSize) { 305 block_size_(kSectorSize),
306 trailer_successfully_parsed_(false) {
307 trailer_successfully_parsed_ = ParseTrailer();
Jialiu Lin 2017/06/09 18:48:49 A better way to do this: 1. Don't call ParseTraile
mortonm 2017/06/09 19:47:21 As we just discussed, I'm going to leave GetTraile
Robert Sesek 2017/06/09 20:02:32 I'd strongly prefer to not expose the UDIF interna
mortonm 2017/06/09 20:23:11 Ok. I've taken out GetTrailer(). We will add a Get
352 } 308 }
353 309
354 UDIFParser::~UDIFParser() {} 310 UDIFParser::~UDIFParser() {}
355 311
312 bool UDIFParser::ParseTrailer() {
313 // Makes sure that trailer is only ever parsed single time during execution of
314 // constuctor, so position of ReadStream is not moved after constructor runs.
315 if (trailer_successfully_parsed_)
316 return true;
317
318 off_t trailer_start = stream_->Seek(-sizeof(trailer_), SEEK_END);
319 if (trailer_start == -1)
320 return false;
321
322 if (!stream_->ReadType(&trailer_)) {
323 DLOG(ERROR) << "Failed to read UDIFResourceFile";
324 return false;
325 }
326 ConvertBigEndian(&trailer_);
327
328 if (trailer_.signature != trailer_.kSignature) {
329 DLOG(ERROR) << "blkx signature does not match, is 0x" << std::hex
330 << trailer_.signature;
331 return false;
332 }
333 if (trailer_.version != trailer_.kVersion) {
334 DLOG(ERROR) << "blkx version does not match, is " << trailer_.version;
335 return false;
336 }
337
338 auto plist_end = base::CheckedNumeric<size_t>(trailer_.plist_offset) +
339 trailer_.plist_length;
340 if (!plist_end.IsValid() ||
341 plist_end.ValueOrDie() > base::checked_cast<size_t>(trailer_start)) {
342 DLOG(ERROR) << "blkx plist extends past UDIF trailer";
343 return false;
344 }
345
346 return true;
347 }
348
349 UDIFResourceFile* UDIFParser::GetTrailer() {
350 if (!trailer_successfully_parsed_) {
351 return NULL;
352 } else {
353 return &trailer_;
354 }
355 }
356
356 bool UDIFParser::Parse() { 357 bool UDIFParser::Parse() {
357 if (!ParseBlkx()) 358 if (!ParseBlkx())
358 return false; 359 return false;
359 360
360 return true; 361 return true;
361 } 362 }
362 363
363 size_t UDIFParser::GetNumberOfPartitions() { 364 size_t UDIFParser::GetNumberOfPartitions() {
364 return blocks_.size(); 365 return blocks_.size();
365 } 366 }
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
400 } 401 }
401 402
402 std::unique_ptr<ReadStream> UDIFParser::GetPartitionReadStream( 403 std::unique_ptr<ReadStream> UDIFParser::GetPartitionReadStream(
403 size_t part_number) { 404 size_t part_number) {
404 DCHECK_LT(part_number, blocks_.size()); 405 DCHECK_LT(part_number, blocks_.size());
405 return base::MakeUnique<UDIFPartitionReadStream>(stream_, block_size_, 406 return base::MakeUnique<UDIFPartitionReadStream>(stream_, block_size_,
406 blocks_[part_number].get()); 407 blocks_[part_number].get());
407 } 408 }
408 409
409 bool UDIFParser::ParseBlkx() { 410 bool UDIFParser::ParseBlkx() {
410 UDIFResourceFile trailer; 411 if (!trailer_successfully_parsed_)
411 off_t trailer_start = stream_->Seek(-sizeof(trailer), SEEK_END);
412 if (trailer_start == -1)
413 return false; 412 return false;
414 413
415 if (!stream_->ReadType(&trailer)) { 414 std::vector<uint8_t> plist_bytes(trailer_.plist_length, 0);
416 DLOG(ERROR) << "Failed to read UDIFResourceFile";
417 return false;
418 }
419 ConvertBigEndian(&trailer);
420 415
421 if (trailer.signature != trailer.kSignature) { 416 if (stream_->Seek(trailer_.plist_offset, SEEK_SET) == -1)
422 DLOG(ERROR) << "blkx signature does not match, is 0x"
423 << std::hex << trailer.signature;
424 return false;
425 }
426 if (trailer.version != trailer.kVersion) {
427 DLOG(ERROR) << "blkx version does not match, is " << trailer.version;
428 return false;
429 }
430
431 auto plist_end = base::CheckedNumeric<size_t>(trailer.plist_offset) +
432 trailer.plist_length;
433 if (!plist_end.IsValid() ||
434 plist_end.ValueOrDie() > base::checked_cast<size_t>(trailer_start)) {
435 DLOG(ERROR) << "blkx plist extends past UDIF trailer";
436 return false;
437 }
438
439 std::vector<uint8_t> plist_bytes(trailer.plist_length, 0);
440
441 if (stream_->Seek(trailer.plist_offset, SEEK_SET) == -1)
442 return false; 417 return false;
443 418
444 if (!stream_->ReadExact(&plist_bytes[0], trailer.plist_length)) { 419 if (!stream_->ReadExact(&plist_bytes[0], trailer_.plist_length)) {
445 DLOG(ERROR) << "Failed to read blkx plist data"; 420 DLOG(ERROR) << "Failed to read blkx plist data";
446 return false; 421 return false;
447 } 422 }
448 423
449 base::ScopedCFTypeRef<CFDataRef> plist_data( 424 base::ScopedCFTypeRef<CFDataRef> plist_data(
450 CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, 425 CFDataCreateWithBytesNoCopy(kCFAllocatorDefault,
451 &plist_bytes[0], plist_bytes.size(), kCFAllocatorNull)); 426 &plist_bytes[0], plist_bytes.size(), kCFAllocatorNull));
452 if (!plist_data) { 427 if (!plist_data) {
453 DLOG(ERROR) << "Failed to create data from bytes"; 428 DLOG(ERROR) << "Failed to create data from bytes";
454 return false; 429 return false;
(...skipping 410 matching lines...) Expand 10 before | Expand all | Expand 10 after
865 << chunk_->compressed_offset; 840 << chunk_->compressed_offset;
866 return false; 841 return false;
867 } 842 }
868 return true; 843 return true;
869 } 844 }
870 845
871 } // namespace 846 } // namespace
872 847
873 } // namespace dmg 848 } // namespace dmg
874 } // namespace safe_browsing 849 } // namespace safe_browsing
OLDNEW
« no previous file with comments | « chrome/utility/safe_browsing/mac/udif.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698