1 /*
2  * Copyright (C) 2020 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 "snapuserd_transition.h"
18 
19 #include <sys/mman.h>
20 #include <sys/socket.h>
21 #include <sys/syscall.h>
22 #include <sys/xattr.h>
23 #include <unistd.h>
24 
25 #include <filesystem>
26 #include <string>
27 #include <string_view>
28 #include <thread>
29 
30 #include <android-base/file.h>
31 #include <android-base/logging.h>
32 #include <android-base/parseint.h>
33 #include <android-base/stringprintf.h>
34 #include <android-base/strings.h>
35 #include <android-base/unique_fd.h>
36 #include <cutils/sockets.h>
37 #include <fs_avb/fs_avb.h>
38 #include <libsnapshot/snapshot.h>
39 #include <private/android_filesystem_config.h>
40 #include <procinfo/process_map.h>
41 #include <selinux/android.h>
42 #include <snapuserd/snapuserd_client.h>
43 
44 #include "block_dev_initializer.h"
45 #include "lmkd_service.h"
46 #include "service_utils.h"
47 #include "util.h"
48 
49 namespace android {
50 namespace init {
51 
52 using namespace std::string_literals;
53 
54 using android::base::unique_fd;
55 using android::snapshot::SnapshotManager;
56 using android::snapshot::SnapuserdClient;
57 
58 static constexpr char kSnapuserdPath[] = "/system/bin/snapuserd";
59 static constexpr char kSnapuserdFirstStagePidVar[] = "FIRST_STAGE_SNAPUSERD_PID";
60 static constexpr char kSnapuserdFirstStageFdVar[] = "FIRST_STAGE_SNAPUSERD_FD";
61 static constexpr char kSnapuserdFirstStageInfoVar[] = "FIRST_STAGE_SNAPUSERD_INFO";
62 static constexpr char kSnapuserdLabel[] = "u:object_r:snapuserd_exec:s0";
63 static constexpr char kSnapuserdSocketLabel[] = "u:object_r:snapuserd_socket:s0";
64 
LaunchFirstStageSnapuserd()65 void LaunchFirstStageSnapuserd() {
66     SocketDescriptor socket_desc;
67     socket_desc.name = android::snapshot::kSnapuserdSocket;
68     socket_desc.type = SOCK_STREAM;
69     socket_desc.perm = 0660;
70     socket_desc.uid = AID_SYSTEM;
71     socket_desc.gid = AID_SYSTEM;
72 
73     // We specify a label here even though it technically is not needed. During
74     // first_stage_mount there is no sepolicy loaded. Once sepolicy is loaded,
75     // we bypass the socket entirely.
76     auto socket = socket_desc.Create(kSnapuserdSocketLabel);
77     if (!socket.ok()) {
78         LOG(FATAL) << "Could not create snapuserd socket: " << socket.error();
79     }
80 
81     pid_t pid = fork();
82     if (pid < 0) {
83         PLOG(FATAL) << "Cannot launch snapuserd; fork failed";
84     }
85     if (pid == 0) {
86         socket->Publish();
87 
88         char arg0[] = "/system/bin/snapuserd";
89         char arg1[] = "-user_snapshot";
90         char* const argv[] = {arg0, arg1, nullptr};
91         if (execv(arg0, argv) < 0) {
92             PLOG(FATAL) << "Cannot launch snapuserd; execv failed";
93         }
94         _exit(127);
95     }
96 
97     auto client = SnapuserdClient::Connect(android::snapshot::kSnapuserdSocket, 10s);
98     if (!client) {
99         LOG(FATAL) << "Could not connect to first-stage snapuserd";
100     }
101     if (client->SupportsSecondStageSocketHandoff()) {
102         setenv(kSnapuserdFirstStageInfoVar, "socket", 1);
103     }
104 
105     setenv(kSnapuserdFirstStagePidVar, std::to_string(pid).c_str(), 1);
106 
107     if (!client->RemoveTransitionedDaemonIndicator()) {
108         LOG(ERROR) << "RemoveTransitionedDaemonIndicator failed";
109     }
110 
111     LOG(INFO) << "Relaunched snapuserd with pid: " << pid;
112 }
113 
GetSnapuserdFirstStagePid()114 std::optional<pid_t> GetSnapuserdFirstStagePid() {
115     const char* pid_str = getenv(kSnapuserdFirstStagePidVar);
116     if (!pid_str) {
117         return {};
118     }
119 
120     int pid = 0;
121     if (!android::base::ParseInt(pid_str, &pid)) {
122         LOG(FATAL) << "Could not parse pid in environment, " << kSnapuserdFirstStagePidVar << "="
123                    << pid_str;
124     }
125     return {pid};
126 }
127 
RelabelLink(const std::string & link)128 static void RelabelLink(const std::string& link) {
129     selinux_android_restorecon(link.c_str(), 0);
130 
131     std::string path;
132     if (android::base::Readlink(link, &path)) {
133         selinux_android_restorecon(path.c_str(), 0);
134     }
135 }
136 
RelabelDeviceMapper()137 static void RelabelDeviceMapper() {
138     selinux_android_restorecon("/dev/device-mapper", 0);
139 
140     std::error_code ec;
141     for (auto& iter : std::filesystem::directory_iterator("/dev/block", ec)) {
142         const auto& path = iter.path();
143         if (android::base::StartsWith(path.string(), "/dev/block/dm-")) {
144             selinux_android_restorecon(path.string().c_str(), 0);
145         }
146     }
147 }
148 
GetRamdiskSnapuserdFd()149 static std::optional<int> GetRamdiskSnapuserdFd() {
150     const char* fd_str = getenv(kSnapuserdFirstStageFdVar);
151     if (!fd_str) {
152         return {};
153     }
154 
155     int fd;
156     if (!android::base::ParseInt(fd_str, &fd)) {
157         LOG(FATAL) << "Could not parse fd in environment, " << kSnapuserdFirstStageFdVar << "="
158                    << fd_str;
159     }
160     return {fd};
161 }
162 
RestoreconRamdiskSnapuserd(int fd)163 void RestoreconRamdiskSnapuserd(int fd) {
164     if (fsetxattr(fd, XATTR_NAME_SELINUX, kSnapuserdLabel, strlen(kSnapuserdLabel) + 1, 0) < 0) {
165         PLOG(FATAL) << "fsetxattr snapuserd failed";
166     }
167 }
168 
SnapuserdSelinuxHelper(std::unique_ptr<SnapshotManager> && sm,pid_t old_pid)169 SnapuserdSelinuxHelper::SnapuserdSelinuxHelper(std::unique_ptr<SnapshotManager>&& sm, pid_t old_pid)
170     : sm_(std::move(sm)), old_pid_(old_pid) {
171     // Only dm-user device names change during transitions, so the other
172     // devices are expected to be present.
173     sm_->SetUeventRegenCallback([this](const std::string& device) -> bool {
174         if (android::base::StartsWith(device, "/dev/dm-user/")) {
175             return block_dev_init_.InitDmUser(android::base::Basename(device));
176         }
177         return true;
178     });
179 }
180 
LockAllSystemPages()181 static void LockAllSystemPages() {
182     bool ok = true;
183     auto callback = [&](const android::procinfo::MapInfo& map) -> void {
184         if (!ok || android::base::StartsWith(map.name, "/dev/") ||
185             !android::base::StartsWith(map.name, "/")) {
186             return;
187         }
188         auto start = reinterpret_cast<const void*>(map.start);
189         uint64_t len = android::procinfo::MappedFileSize(map);
190         if (!len) {
191             return;
192         }
193 
194         if (mlock(start, len) < 0) {
195             PLOG(ERROR) << "\"" << map.name << "\": mlock(" << start << ", " << len
196                         << ") failed: pgoff = " << map.pgoff;
197             ok = false;
198         }
199     };
200 
201     if (!android::procinfo::ReadProcessMaps(getpid(), callback) || !ok) {
202         LOG(FATAL) << "Could not process /proc/" << getpid() << "/maps file for init";
203     }
204 }
205 
StartTransition()206 void SnapuserdSelinuxHelper::StartTransition() {
207     LOG(INFO) << "Starting SELinux transition of snapuserd";
208 
209     // The restorecon path reads from /system etc, so make sure any reads have
210     // been cached before proceeding.
211     auto handle = selinux_android_file_context_handle();
212     if (!handle) {
213         LOG(FATAL) << "Could not create SELinux file context handle";
214     }
215     selinux_android_set_sehandle(handle);
216 
217     // We cannot access /system after the transition, so make sure init is
218     // pinned in memory.
219     LockAllSystemPages();
220 
221     argv_.emplace_back("snapuserd");
222     argv_.emplace_back("-no_socket");
223     if (!sm_->PrepareSnapuserdArgsForSelinux(&argv_)) {
224         LOG(FATAL) << "Could not perform selinux transition";
225     }
226 }
227 
FinishTransition()228 void SnapuserdSelinuxHelper::FinishTransition() {
229     RelabelLink("/dev/block/by-name/super");
230     RelabelDeviceMapper();
231 
232     selinux_android_restorecon("/dev/null", 0);
233     selinux_android_restorecon("/dev/urandom", 0);
234     selinux_android_restorecon("/dev/kmsg", 0);
235     selinux_android_restorecon("/dev/dm-user", SELINUX_ANDROID_RESTORECON_RECURSE);
236 
237     RelaunchFirstStageSnapuserd();
238 
239     if (munlockall() < 0) {
240         PLOG(ERROR) << "munlockall failed";
241     }
242 }
243 
244 /*
245  * Before starting init second stage, we will wait
246  * for snapuserd daemon to be up and running; bionic libc
247  * may read /system/etc/selinux/plat_property_contexts file
248  * before invoking main() function. This will happen if
249  * init initializes property during second stage. Any access
250  * to /system without snapuserd daemon will lead to a deadlock.
251  *
252  * Thus, we do a simple probe by reading system partition. This
253  * read will eventually be serviced by daemon confirming that
254  * daemon is up and running. Furthermore, we are still in the kernel
255  * domain and sepolicy has not been enforced yet. Thus, access
256  * to these device mapper block devices are ok even though
257  * we may see audit logs.
258  */
TestSnapuserdIsReady()259 bool SnapuserdSelinuxHelper::TestSnapuserdIsReady() {
260     // Wait for the daemon to be fully up. Daemon will write to path
261     // /metadata/ota/daemon-alive-indicator only when all the threads
262     // are ready and attached to dm-user.
263     //
264     // This check will fail for GRF devices with vendor on Android S.
265     // snapuserd binary from Android S won't be able to communicate
266     // and hence, we will fallback and issue I/O to verify
267     // the presence of daemon.
268     auto client = std::make_unique<SnapuserdClient>();
269     if (!client->IsTransitionedDaemonReady()) {
270         LOG(ERROR) << "IsTransitionedDaemonReady failed";
271     }
272 
273     std::string dev = "/dev/block/mapper/system"s + fs_mgr_get_slot_suffix();
274     android::base::unique_fd fd(open(dev.c_str(), O_RDONLY | O_DIRECT));
275     if (fd < 0) {
276         PLOG(ERROR) << "open " << dev << " failed";
277         return false;
278     }
279 
280     void* addr;
281     ssize_t page_size = getpagesize();
282     if (posix_memalign(&addr, page_size, page_size) < 0) {
283         PLOG(ERROR) << "posix_memalign with page size " << page_size;
284         return false;
285     }
286 
287     std::unique_ptr<void, decltype(&::free)> buffer(addr, ::free);
288 
289     int iter = 0;
290     while (iter < 10) {
291         ssize_t n = TEMP_FAILURE_RETRY(pread(fd.get(), buffer.get(), page_size, 0));
292         if (n < 0) {
293             // Wait for sometime before retry
294             std::this_thread::sleep_for(100ms);
295         } else if (n == page_size) {
296             return true;
297         } else {
298             LOG(ERROR) << "pread returned: " << n << " from: " << dev << " expected: " << page_size;
299         }
300 
301         iter += 1;
302     }
303 
304     return false;
305 }
306 
RelaunchFirstStageSnapuserd()307 void SnapuserdSelinuxHelper::RelaunchFirstStageSnapuserd() {
308     if (!sm_->DetachFirstStageSnapuserdForSelinux()) {
309         LOG(FATAL) << "Could not perform selinux transition";
310     }
311 
312     KillFirstStageSnapuserd(old_pid_);
313 
314     auto fd = GetRamdiskSnapuserdFd();
315     if (!fd) {
316         LOG(FATAL) << "Environment variable " << kSnapuserdFirstStageFdVar << " was not set!";
317     }
318     unsetenv(kSnapuserdFirstStageFdVar);
319 
320     RestoreconRamdiskSnapuserd(fd.value());
321 
322     pid_t pid = fork();
323     if (pid < 0) {
324         PLOG(FATAL) << "Fork to relaunch snapuserd failed";
325     }
326     if (pid > 0) {
327         // We don't need the descriptor anymore, and it should be closed to
328         // avoid leaking into subprocesses.
329         close(fd.value());
330 
331         setenv(kSnapuserdFirstStagePidVar, std::to_string(pid).c_str(), 1);
332 
333         LOG(INFO) << "Relaunched snapuserd with pid: " << pid;
334 
335         // Since daemon is not started as a service, we have
336         // to explicitly set the OOM score to default which is unkillable
337         std::string oom_str = std::to_string(DEFAULT_OOM_SCORE_ADJUST);
338         std::string oom_file = android::base::StringPrintf("/proc/%d/oom_score_adj", pid);
339         if (!android::base::WriteStringToFile(oom_str, oom_file)) {
340             PLOG(ERROR) << "couldn't write oom_score_adj to snapuserd daemon with pid: " << pid;
341         }
342 
343         if (!TestSnapuserdIsReady()) {
344             PLOG(FATAL) << "snapuserd daemon failed to launch";
345         } else {
346             LOG(INFO) << "snapuserd daemon is up and running";
347         }
348 
349         return;
350     }
351 
352     // Make sure the descriptor is gone after we exec.
353     if (fcntl(fd.value(), F_SETFD, FD_CLOEXEC) < 0) {
354         PLOG(FATAL) << "fcntl FD_CLOEXEC failed for snapuserd fd";
355     }
356 
357     std::vector<char*> argv;
358     for (auto& arg : argv_) {
359         argv.emplace_back(arg.data());
360     }
361     argv.emplace_back(nullptr);
362 
363     int rv = syscall(SYS_execveat, fd.value(), "", reinterpret_cast<char* const*>(argv.data()),
364                      nullptr, AT_EMPTY_PATH);
365     if (rv < 0) {
366         PLOG(FATAL) << "Failed to execveat() snapuserd";
367     }
368 }
369 
CreateIfNeeded()370 std::unique_ptr<SnapuserdSelinuxHelper> SnapuserdSelinuxHelper::CreateIfNeeded() {
371     if (IsRecoveryMode()) {
372         return nullptr;
373     }
374 
375     auto old_pid = GetSnapuserdFirstStagePid();
376     if (!old_pid) {
377         return nullptr;
378     }
379 
380     auto sm = SnapshotManager::NewForFirstStageMount();
381     if (!sm) {
382         LOG(FATAL) << "Unable to create SnapshotManager";
383     }
384     return std::make_unique<SnapuserdSelinuxHelper>(std::move(sm), old_pid.value());
385 }
386 
KillFirstStageSnapuserd(pid_t pid)387 void KillFirstStageSnapuserd(pid_t pid) {
388     if (kill(pid, SIGTERM) < 0 && errno != ESRCH) {
389         LOG(ERROR) << "Kill snapuserd pid failed: " << pid;
390     } else {
391         LOG(INFO) << "Sent SIGTERM to snapuserd process " << pid;
392     }
393 }
394 
CleanupSnapuserdSocket()395 void CleanupSnapuserdSocket() {
396     auto socket_path = ANDROID_SOCKET_DIR "/"s + android::snapshot::kSnapuserdSocket;
397     if (access(socket_path.c_str(), F_OK) != 0) {
398         return;
399     }
400 
401     // Tell the daemon to stop accepting connections and to gracefully exit
402     // once all outstanding handlers have terminated.
403     if (auto client = SnapuserdClient::Connect(android::snapshot::kSnapuserdSocket, 3s)) {
404         client->DetachSnapuserd();
405     }
406 
407     // Unlink the socket so we can create it again in second-stage.
408     if (unlink(socket_path.c_str()) < 0) {
409         PLOG(FATAL) << "unlink " << socket_path << " failed";
410     }
411 }
412 
SaveRamdiskPathToSnapuserd()413 void SaveRamdiskPathToSnapuserd() {
414     int fd = open(kSnapuserdPath, O_PATH);
415     if (fd < 0) {
416         PLOG(FATAL) << "Unable to open snapuserd: " << kSnapuserdPath;
417     }
418 
419     auto value = std::to_string(fd);
420     if (setenv(kSnapuserdFirstStageFdVar, value.c_str(), 1) < 0) {
421         PLOG(FATAL) << "setenv failed: " << kSnapuserdFirstStageFdVar << "=" << value;
422     }
423 }
424 
IsFirstStageSnapuserdRunning()425 bool IsFirstStageSnapuserdRunning() {
426     return GetSnapuserdFirstStagePid().has_value();
427 }
428 
GetSnapuserdFirstStageInfo()429 std::vector<std::string> GetSnapuserdFirstStageInfo() {
430     const char* pid_str = getenv(kSnapuserdFirstStageInfoVar);
431     if (!pid_str) {
432         return {};
433     }
434     return android::base::Split(pid_str, ",");
435 }
436 
437 }  // namespace init
438 }  // namespace android
439