blob: 7fe48501a03941d0b489ec36802ed2ef7a0bda10 [file] [log] [blame]
Håkan Kvist4e13cf42018-01-23 12:57:55 +01001//
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
29namespace chromeos_update_engine {
30void 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
Kelvin Zhang4b280242020-11-06 16:07:45 -050040 if (!utils::ReadAll(
Håkan Kvist4e13cf42018-01-23 12:57:55 +010041 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
Håkan Kvist90560212020-11-26 16:32:29 +010057 // 0x40: len32 Time of last check
58 // 0x108: len32 When the filesystem was created
Håkan Kvist4e13cf42018-01-23 12:57:55 +010059
60 time_t mount_time =
61 *reinterpret_cast<uint32_t*>(&block0_buffer[0x400 + 0x2C]);
Håkan Kvist90560212020-11-26 16:32:29 +010062 time_t write_time =
63 *reinterpret_cast<uint32_t*>(&block0_buffer[0x400 + 0x30]);
Håkan Kvist4e13cf42018-01-23 12:57:55 +010064 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]);
Håkan Kvist90560212020-11-26 16:32:29 +010067 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]);
Håkan Kvist4e13cf42018-01-23 12:57:55 +010071
72 if (magic == 0xEF53) {
Håkan Kvist90560212020-11-26 16:32:29 +010073 // Timestamps can be updated by fsck without updating mount count,
74 // log if any timestamp differ
Colin Cross26b82b12021-12-22 10:09:19 -080075 if (!(write_time == created_time && check_time == created_time)) {
Håkan Kvist90560212020-11-26 16:32:29 +010076 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 }
Håkan Kvist4e13cf42018-01-23 12:57:55 +010084 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