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

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

Issue 2926473002: Mac Archive Type Sniffing (Closed)
Patch Set: adding tester for download protection service 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
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>
11 11
12 #include <algorithm> 12 #include <algorithm>
13 #include <utility> 13 #include <utility>
14 14
15 #include "base/logging.h" 15 #include "base/logging.h"
16 #include "base/mac/foundation_util.h" 16 #include "base/mac/foundation_util.h"
17 #include "base/mac/scoped_cftyperef.h" 17 #include "base/mac/scoped_cftyperef.h"
18 #include "base/macros.h" 18 #include "base/macros.h"
19 #include "base/memory/ptr_util.h" 19 #include "base/memory/ptr_util.h"
20 #include "base/numerics/safe_math.h" 20 #include "base/numerics/safe_math.h"
21 #include "base/strings/sys_string_conversions.h" 21 #include "base/strings/sys_string_conversions.h"
22 #include "chrome/utility/safe_browsing/mac/convert_big_endian.h" 22 #include "chrome/utility/safe_browsing/mac/convert_big_endian.h"
23 #include "chrome/utility/safe_browsing/mac/read_stream.h" 23 #include "chrome/utility/safe_browsing/mac/read_stream.h"
24 #include "third_party/zlib/zlib.h" 24 #include "third_party/zlib/zlib.h"
25 25
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)
vakh (use Gerrit instead) 2017/06/12 16:20:28 Do we still need this preprocessor directive here?
mortonm 2017/06/12 16:35:54 Yes -- I've moved the struct definition back into
30 30
31 // The following structures come from the analysis provided by Jonathan Levin
32 // at <http://newosxbook.com/DMG.html>.
33 //
34 // Note that all fields are stored in big endian.
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) { 31 static void ConvertBigEndian(UDIFChecksum* checksum) {
43 ConvertBigEndian(&checksum->type); 32 ConvertBigEndian(&checksum->type);
44 ConvertBigEndian(&checksum->size); 33 ConvertBigEndian(&checksum->size);
45 for (size_t i = 0; i < arraysize(checksum->data); ++i) { 34 for (size_t i = 0; i < arraysize(checksum->data); ++i) {
46 ConvertBigEndian(&checksum->data[i]); 35 ConvertBigEndian(&checksum->data[i]);
47 } 36 }
48 } 37 }
49 38
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) { 39 static void ConvertBigEndian(uuid_t* uuid) {
91 // UUID is never consulted, so do not swap. 40 // UUID is never consulted, so do not swap.
92 } 41 }
93 42
94 static void ConvertBigEndian(UDIFResourceFile* file) { 43 static void ConvertBigEndian(UDIFResourceFile* file) {
95 ConvertBigEndian(&file->signature); 44 ConvertBigEndian(&file->signature);
96 ConvertBigEndian(&file->version); 45 ConvertBigEndian(&file->version);
97 ConvertBigEndian(&file->flags); 46 ConvertBigEndian(&file->flags);
98 ConvertBigEndian(&file->header_size); 47 ConvertBigEndian(&file->header_size);
99 ConvertBigEndian(&file->running_data_fork_offset); 48 ConvertBigEndian(&file->running_data_fork_offset);
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
341 290
342 DISALLOW_COPY_AND_ASSIGN(UDIFBlockChunkReadStream); 291 DISALLOW_COPY_AND_ASSIGN(UDIFBlockChunkReadStream);
343 }; 292 };
344 293
345 } // namespace 294 } // namespace
346 295
347 UDIFParser::UDIFParser(ReadStream* stream) 296 UDIFParser::UDIFParser(ReadStream* stream)
348 : stream_(stream), 297 : stream_(stream),
349 partition_names_(), 298 partition_names_(),
350 blocks_(), 299 blocks_(),
351 block_size_(kSectorSize) { 300 block_size_(kSectorSize),
352 } 301 trailer_successfully_parsed_(false) {}
353 302
354 UDIFParser::~UDIFParser() {} 303 UDIFParser::~UDIFParser() {}
355 304
305 bool UDIFParser::ParseTrailer() {
306 // Makes sure that trailer is only ever parsed single time during execution of
307 // constuctor, so position of ReadStream is not moved after constructor runs.
308 if (trailer_successfully_parsed_)
309 return true;
310
311 off_t trailer_start = stream_->Seek(-sizeof(trailer_), SEEK_END);
312 if (trailer_start == -1)
313 return false;
314
315 if (!stream_->ReadType(&trailer_)) {
316 DLOG(ERROR) << "Failed to read UDIFResourceFile";
317 return false;
318 }
319 ConvertBigEndian(&trailer_);
320
321 if (trailer_.signature != trailer_.kSignature) {
322 DLOG(ERROR) << "blkx signature does not match, is 0x" << std::hex
323 << trailer_.signature;
324 return false;
325 }
326 if (trailer_.version != trailer_.kVersion) {
327 DLOG(ERROR) << "blkx version does not match, is " << trailer_.version;
328 return false;
329 }
330
331 auto plist_end = base::CheckedNumeric<size_t>(trailer_.plist_offset) +
332 trailer_.plist_length;
333 if (!plist_end.IsValid() ||
334 plist_end.ValueOrDie() > base::checked_cast<size_t>(trailer_start)) {
335 DLOG(ERROR) << "blkx plist extends past UDIF trailer";
336 return false;
337 }
338
339 return true;
340 }
341
356 bool UDIFParser::Parse() { 342 bool UDIFParser::Parse() {
357 if (!ParseBlkx()) 343 // First parses trailer and then parses blocks.
344 trailer_successfully_parsed_ = ParseTrailer();
345 if (!trailer_successfully_parsed_ || !ParseBlkx())
vakh (use Gerrit instead) 2017/06/12 16:20:28 shortcut this as: return trailer_successfully_pars
mortonm 2017/06/12 16:35:54 Done.
358 return false; 346 return false;
359 347
360 return true; 348 return true;
361 } 349 }
362 350
363 size_t UDIFParser::GetNumberOfPartitions() { 351 size_t UDIFParser::GetNumberOfPartitions() {
364 return blocks_.size(); 352 return blocks_.size();
365 } 353 }
366 354
367 std::string UDIFParser::GetPartitionName(size_t part_number) { 355 std::string UDIFParser::GetPartitionName(size_t part_number) {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
400 } 388 }
401 389
402 std::unique_ptr<ReadStream> UDIFParser::GetPartitionReadStream( 390 std::unique_ptr<ReadStream> UDIFParser::GetPartitionReadStream(
403 size_t part_number) { 391 size_t part_number) {
404 DCHECK_LT(part_number, blocks_.size()); 392 DCHECK_LT(part_number, blocks_.size());
405 return base::MakeUnique<UDIFPartitionReadStream>(stream_, block_size_, 393 return base::MakeUnique<UDIFPartitionReadStream>(stream_, block_size_,
406 blocks_[part_number].get()); 394 blocks_[part_number].get());
407 } 395 }
408 396
409 bool UDIFParser::ParseBlkx() { 397 bool UDIFParser::ParseBlkx() {
410 UDIFResourceFile trailer; 398 if (!trailer_successfully_parsed_)
411 off_t trailer_start = stream_->Seek(-sizeof(trailer), SEEK_END);
412 if (trailer_start == -1)
413 return false; 399 return false;
414 400
415 if (!stream_->ReadType(&trailer)) { 401 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 402
421 if (trailer.signature != trailer.kSignature) { 403 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; 404 return false;
443 405
444 if (!stream_->ReadExact(&plist_bytes[0], trailer.plist_length)) { 406 if (!stream_->ReadExact(&plist_bytes[0], trailer_.plist_length)) {
445 DLOG(ERROR) << "Failed to read blkx plist data"; 407 DLOG(ERROR) << "Failed to read blkx plist data";
446 return false; 408 return false;
447 } 409 }
448 410
449 base::ScopedCFTypeRef<CFDataRef> plist_data( 411 base::ScopedCFTypeRef<CFDataRef> plist_data(
450 CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, 412 CFDataCreateWithBytesNoCopy(kCFAllocatorDefault,
451 &plist_bytes[0], plist_bytes.size(), kCFAllocatorNull)); 413 &plist_bytes[0], plist_bytes.size(), kCFAllocatorNull));
452 if (!plist_data) { 414 if (!plist_data) {
453 DLOG(ERROR) << "Failed to create data from bytes"; 415 DLOG(ERROR) << "Failed to create data from bytes";
454 return false; 416 return false;
(...skipping 410 matching lines...) Expand 10 before | Expand all | Expand 10 after
865 << chunk_->compressed_offset; 827 << chunk_->compressed_offset;
866 return false; 828 return false;
867 } 829 }
868 return true; 830 return true;
869 } 831 }
870 832
871 } // namespace 833 } // namespace
872 834
873 } // namespace dmg 835 } // namespace dmg
874 } // namespace safe_browsing 836 } // namespace safe_browsing
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698