-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathprivate_computing_adaptor.cc
186 lines (149 loc) · 6.26 KB
/
private_computing_adaptor.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
// Copyright 2022 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "private_computing/private_computing_adaptor.h"
#include <cstdint>
#include <string>
#include <utility>
#include <vector>
#include <base/check.h>
#include <base/files/file_util.h>
#include <base/location.h>
#include <base/logging.h>
#include <base/strings/strcat.h>
#include <brillo/dbus/dbus_object.h>
#include <brillo/errors/error.h>
#include <dbus/private_computing/dbus-constants.h>
#include <google/protobuf/message_lite.h>
#include "private_computing/proto_bindings/private_computing_service.pb.h"
namespace private_computing {
namespace {
// Path to preserved file used to read the last ping dates after powerwash.
const char kPrivateComputingLastActiveDatesReadPath[] =
"/mnt/stateful_partition/unencrypted/preserve/last_active_dates";
// Path to file storing the last ping dates as serialized object
// private_computing_service::SaveStatusRequest.
const char kPrivateComputingLastActiveDatesWritePath[] =
"/var/lib/private_computing/last_active_dates";
// Serializes |proto| to a vector of bytes.
std::vector<uint8_t> SerializeProto(
const google::protobuf::MessageLite& proto) {
std::vector<uint8_t> proto_blob(proto.ByteSizeLong());
CHECK(proto.SerializeToArray(proto_blob.data(), proto_blob.size()));
return proto_blob;
}
// Parses a proto from an array of bytes |proto_blob|. Returns
// error message or empty string if no error.
std::string ParseProto(const base::Location& from_here,
google::protobuf::MessageLite* proto,
const std::vector<uint8_t>& proto_blob) {
if (!proto->ParseFromArray(proto_blob.data(), proto_blob.size())) {
const std::string error_message = "Failed to parse proto message.";
LOG(ERROR) << from_here.ToString() << " " << error_message;
return error_message;
}
return "";
}
std::optional<std::string> ReadActiveStatusFile(
const base::FilePath& filePath) {
base::File file(filePath, base::File::FLAG_OPEN | base::File::FLAG_READ);
if (!file.IsValid()) {
return std::nullopt;
}
base::File::Info file_info;
if (!file.GetInfo(&file_info) || file_info.size <= 0) {
return std::nullopt;
}
std::string result;
result.resize(file_info.size);
const int read_result =
file.Read(/* offset */ 0, result.data(), file_info.size);
if (read_result != file_info.size) {
return std::nullopt;
}
return result;
}
} // namespace
PrivateComputingAdaptor::PrivateComputingAdaptor(
std::unique_ptr<brillo::dbus_utils::DBusObject> dbus_object)
: org::chromium::PrivateComputingAdaptor(this),
dbus_object_(std::move(dbus_object)),
var_lib_dir_(kPrivateComputingLastActiveDatesWritePath),
preserve_dir_(kPrivateComputingLastActiveDatesReadPath) {}
void PrivateComputingAdaptor::RegisterAsync(
brillo::dbus_utils::AsyncEventSequencer::CompletionAction
completion_callback) {
RegisterWithDBusObject(dbus_object_.get());
dbus_object_->RegisterAsync(std::move(completion_callback));
}
std::vector<uint8_t> PrivateComputingAdaptor::SaveLastPingDatesStatus(
const std::vector<uint8_t>& request_blob) {
LOG(INFO) << "Save the last ping dates to file.";
SaveStatusRequest request;
std::string error_message = ParseProto(FROM_HERE, &request, request_blob);
SaveStatusResponse response;
if (!error_message.empty()) {
response.set_error_message(error_message);
return SerializeProto(response);
}
// Write serialized request to |kPrivateComputingLastActiveDatesWritePath|
base::File file(var_lib_dir_,
base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
if (!file.IsValid()) {
response.set_error_message(
"Failed to retrieve last_active_dates file descriptor.");
return SerializeProto(response);
}
std::string request_str = request.SerializeAsString();
const int write_count =
file.Write(0, request_str.c_str(), request_str.size());
if (write_count < 0 ||
static_cast<size_t>(write_count) < request_str.size()) {
response.set_error_message(
base::StrCat({"Failed to write data file ",
kPrivateComputingLastActiveDatesWritePath,
" write count=", std::to_string(write_count)}));
return SerializeProto(response);
}
LOG(INFO)
<< "Successfully saved last ping date to /var/lib/private_computing.";
return SerializeProto(response);
}
std::vector<uint8_t> PrivateComputingAdaptor::GetLastPingDatesStatus() {
// First try to read from `/var/lib/private_computing` folder.
// Because this file will be updated after every successfully ping.
// If this file exists, then it will be the latest value.
std::optional<std::string> result_string = ReadActiveStatusFile(var_lib_dir_);
GetStatusResponse response;
if (!result_string) {
LOG(ERROR) << "PSM: Cannot read from "
<< kPrivateComputingLastActiveDatesWritePath;
// Next try to read from preserved file if reading from var/lib failed,
// which means the device was powerwashed/recovery/new device. If the
// device was powerwashed, then the preserved file should be existed.
// If the device was recovery/new device, reading from preserved file
// should be failed as well.
result_string = ReadActiveStatusFile(preserve_dir_);
if (!result_string) {
LOG(ERROR) << "PSM: Cannot read from "
<< kPrivateComputingLastActiveDatesReadPath;
// Cannot read neither from /var/lib or preserved file, then return
// the response with error message.
response.set_error_message(
"PSM: Neither from /var/lib or the preserved file");
return SerializeProto(response);
}
}
LOG(INFO) << "PSM: Successfully read from /var/lib or /preserved file.";
// Successfully read file into |result_string|.
SaveStatusRequest request;
if (!request.ParseFromString(result_string.value())) {
response.set_error_message(
base::StrCat({"Failed to parse result string as a SaveStatusRequest ",
kPrivateComputingLastActiveDatesReadPath}));
return SerializeProto(response);
}
*response.mutable_active_status() = request.active_status();
return SerializeProto(response);
}
} // namespace private_computing