1 //
2 // Copyright (C) 2018 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16
17 #include "update_engine/payload_consumer/mount_history.h"
18
19 #include <inttypes.h>
20
21 #include <string>
22 #include <vector>
23
24 #include <base/logging.h>
25 #include <base/time/time.h>
26
27 #include "update_engine/common/utils.h"
28
29 namespace chromeos_update_engine {
LogMountHistory(const FileDescriptorPtr blockdevice_fd)30 void LogMountHistory(const FileDescriptorPtr blockdevice_fd) {
31 static constexpr ssize_t kBlockSize = 4096;
32
33 if (blockdevice_fd == nullptr) {
34 return;
35 }
36
37 brillo::Blob block0_buffer(kBlockSize);
38 ssize_t bytes_read;
39
40 if (!utils::ReadAll(
41 blockdevice_fd, block0_buffer.data(), kBlockSize, 0, &bytes_read)) {
42 LOG(WARNING) << "PReadAll failed";
43 return;
44 }
45
46 if (bytes_read != kBlockSize) {
47 LOG(WARNING) << "Could not read an entire block";
48 return;
49 }
50
51 // https://ext4.wiki.kernel.org/index.php/Ext4_Disk_Layout
52 // Super block starts from block 0, offset 0x400
53 // 0x2C: len32 Mount time
54 // 0x30: len32 Write time
55 // 0x34: len16 Number of mounts since the last fsck
56 // 0x38: len16 Magic signature 0xEF53
57 // 0x40: len32 Time of last check
58 // 0x108: len32 When the filesystem was created
59
60 time_t mount_time =
61 *reinterpret_cast<uint32_t*>(&block0_buffer[0x400 + 0x2C]);
62 time_t write_time =
63 *reinterpret_cast<uint32_t*>(&block0_buffer[0x400 + 0x30]);
64 uint16_t mount_count =
65 *reinterpret_cast<uint16_t*>(&block0_buffer[0x400 + 0x34]);
66 uint16_t magic = *reinterpret_cast<uint16_t*>(&block0_buffer[0x400 + 0x38]);
67 time_t check_time =
68 *reinterpret_cast<uint32_t*>(&block0_buffer[0x400 + 0x40]);
69 time_t created_time =
70 *reinterpret_cast<uint32_t*>(&block0_buffer[0x400 + 0x108]);
71
72 if (magic == 0xEF53) {
73 // Timestamps can be updated by fsck without updating mount count,
74 // log if any timestamp differ
75 if (! (write_time == created_time && check_time == created_time)) {
76 LOG(WARNING) << "Device have been modified after being created. "
77 << "Filesystem created on "
78 << base::Time::FromTimeT(created_time) << ", "
79 << "last written on "
80 << base::Time::FromTimeT(write_time) << ", "
81 << "last checked on "
82 << base::Time::FromTimeT(check_time) << ".";
83 }
84 if (mount_count > 0) {
85 LOG(WARNING) << "Device was remounted R/W " << mount_count << " times. "
86 << "Last remount happened on "
87 << base::Time::FromTimeT(mount_time) << ".";
88 }
89 }
90 }
91 } // namespace chromeos_update_engine
92