Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include <android/log.h>
8 #include <cutils/android_reboot.h>
9 #include <errno.h>
10 #include <stdlib.h>
11 #include <sys/mount.h>
12 #include <sys/reboot.h>
13 #include <sys/types.h>
14 #include <unistd.h>
16 #include "automounter_gonk.h"
17 #include "updatedefines.h"
18 #include "updatelogging.h"
20 #define LOG_TAG "GonkAutoMounter"
22 #define GONK_LOG(level, format, ...) \
23 LOG((LOG_TAG ": " format "\n", ##__VA_ARGS__)); \
24 __android_log_print(level, LOG_TAG, format, ##__VA_ARGS__)
26 #define LOGI(format, ...) GONK_LOG(ANDROID_LOG_INFO, format, ##__VA_ARGS__)
27 #define LOGE(format, ...) GONK_LOG(ANDROID_LOG_ERROR, format, ##__VA_ARGS__)
29 const char *kGonkMountsPath = "/proc/mounts";
30 const char *kGonkSystemPath = "/system";
32 GonkAutoMounter::GonkAutoMounter() : mDevice(nullptr), mAccess(Unknown)
33 {
34 if (!RemountSystem(ReadWrite)) {
35 LOGE("Could not remount %s as read-write.", kGonkSystemPath);
36 }
37 }
39 GonkAutoMounter::~GonkAutoMounter()
40 {
41 bool result = RemountSystem(ReadOnly);
42 free(mDevice);
44 if (!result) {
45 // Don't take any chances when remounting as read-only fails, just reboot.
46 Reboot();
47 }
48 }
50 void
51 GonkAutoMounter::Reboot()
52 {
53 // The android_reboot wrapper provides more safety, doing fancier read-only
54 // remounting and attempting to sync() the filesystem first. If this fails
55 // our only hope is to force a reboot directly without these protections.
56 // For more, see system/core/libcutils/android_reboot.c
57 LOGE("Could not remount %s as read-only, forcing a system reboot.",
58 kGonkSystemPath);
59 LogFlush();
61 if (android_reboot(ANDROID_RB_RESTART, 0, nullptr) != 0) {
62 LOGE("Safe system reboot failed, attempting to force");
63 LogFlush();
65 if (reboot(RB_AUTOBOOT) != 0) {
66 LOGE("CRITICAL: Failed to force restart");
67 }
68 }
69 }
71 static const char *
72 MountAccessToString(MountAccess access)
73 {
74 switch (access) {
75 case ReadOnly: return "read-only";
76 case ReadWrite: return "read-write";
77 default: return "unknown";
78 }
79 }
81 bool
82 GonkAutoMounter::RemountSystem(MountAccess access)
83 {
84 if (!UpdateMountStatus()) {
85 return false;
86 }
88 if (mAccess == access) {
89 return true;
90 }
92 unsigned long flags = MS_REMOUNT;
93 if (access == ReadOnly) {
94 flags |= MS_RDONLY;
95 // Give the system a chance to flush file buffers
96 sync();
97 }
99 if (!MountSystem(flags)) {
100 return false;
101 }
103 // Check status again to verify /system has been properly remounted
104 if (!UpdateMountStatus()) {
105 return false;
106 }
108 if (mAccess != access) {
109 LOGE("Updated mount status %s should be %s",
110 MountAccessToString(mAccess),
111 MountAccessToString(access));
112 return false;
113 }
115 return true;
116 }
118 bool
119 GonkAutoMounter::UpdateMountStatus()
120 {
121 FILE *mountsFile = NS_tfopen(kGonkMountsPath, "r");
123 if (mountsFile == nullptr) {
124 LOGE("Error opening %s: %s", kGonkMountsPath, strerror(errno));
125 return false;
126 }
128 // /proc/mounts returns a 0 size from fstat, so we use the same
129 // pre-allocated buffer size that ADB does here
130 const int mountsMaxSize = 4096;
131 char mountData[mountsMaxSize];
132 size_t read = fread(mountData, 1, mountsMaxSize - 1, mountsFile);
133 mountData[read + 1] = '\0';
135 if (ferror(mountsFile)) {
136 LOGE("Error reading %s, %s", kGonkMountsPath, strerror(errno));
137 fclose(mountsFile);
138 return false;
139 }
141 char *token, *tokenContext;
142 bool foundSystem = false;
144 for (token = strtok_r(mountData, "\n", &tokenContext);
145 token;
146 token = strtok_r(nullptr, "\n", &tokenContext))
147 {
148 if (ProcessMount(token)) {
149 foundSystem = true;
150 break;
151 }
152 }
154 fclose(mountsFile);
156 if (!foundSystem) {
157 LOGE("Couldn't find %s mount in %s", kGonkSystemPath, kGonkMountsPath);
158 }
159 return foundSystem;
160 }
162 bool
163 GonkAutoMounter::ProcessMount(const char *mount)
164 {
165 const int strSize = 256;
166 char mountDev[strSize];
167 char mountDir[strSize];
168 char mountAccess[strSize];
170 int rv = sscanf(mount, "%255s %255s %*s %255s %*d %*d\n",
171 mountDev, mountDir, mountAccess);
172 mountDev[strSize - 1] = '\0';
173 mountDir[strSize - 1] = '\0';
174 mountAccess[strSize - 1] = '\0';
176 if (rv != 3) {
177 return false;
178 }
180 if (strcmp(kGonkSystemPath, mountDir) != 0) {
181 return false;
182 }
184 free(mDevice);
185 mDevice = strdup(mountDev);
186 mAccess = Unknown;
188 char *option, *optionContext;
189 for (option = strtok_r(mountAccess, ",", &optionContext);
190 option;
191 option = strtok_r(nullptr, ",", &optionContext))
192 {
193 if (strcmp("ro", option) == 0) {
194 mAccess = ReadOnly;
195 break;
196 } else if (strcmp("rw", option) == 0) {
197 mAccess = ReadWrite;
198 break;
199 }
200 }
202 return true;
203 }
205 bool
206 GonkAutoMounter::MountSystem(unsigned long flags)
207 {
208 if (!mDevice) {
209 LOGE("No device was found for %s", kGonkSystemPath);
210 return false;
211 }
213 const char *readOnly = flags & MS_RDONLY ? "read-only" : "read-write";
214 int result = mount(mDevice, kGonkSystemPath, "none", flags, nullptr);
216 if (result != 0) {
217 LOGE("Error mounting %s as %s: %s", kGonkSystemPath, readOnly,
218 strerror(errno));
219 return false;
220 }
222 LOGI("Mounted %s partition as %s", kGonkSystemPath, readOnly);
223 return true;
224 }