Merge "Refactor the DwarfSection classes."
diff --git a/adb/Android.bp b/adb/Android.bp
index 97c9762..c0e4c57 100644
--- a/adb/Android.bp
+++ b/adb/Android.bp
@@ -19,17 +19,13 @@
"-Wall",
"-Wextra",
"-Werror",
+ "-Wexit-time-destructors",
"-Wno-unused-parameter",
"-Wno-missing-field-initializers",
"-Wvla",
],
rtti: true,
- clang_cflags: [
- "-Wexit-time-destructors",
- "-Wthread-safety",
- ],
-
use_version_lib: true,
compile_multilib: "first",
@@ -85,6 +81,12 @@
"-luserenv",
],
},
+
+ not_windows: {
+ cflags: [
+ "-Wthread-safety",
+ ],
+ },
},
}
diff --git a/adb/adb.h b/adb/adb.h
index ede55da..c884166 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -124,8 +124,6 @@
void print_packet(const char* label, apacket* p);
-// These use the system (v)fprintf, not the adb prefixed ones defined in sysdeps.h, so they
-// shouldn't be tagged with ADB_FORMAT_ARCHETYPE.
void fatal(const char* fmt, ...) __attribute__((noreturn, format(__printf__, 1, 2)));
void fatal_errno(const char* fmt, ...) __attribute__((noreturn, format(__printf__, 1, 2)));
diff --git a/adb/client/file_sync_client.cpp b/adb/client/file_sync_client.cpp
index 26f8d83..1275641 100644
--- a/adb/client/file_sync_client.cpp
+++ b/adb/client/file_sync_client.cpp
@@ -510,8 +510,7 @@
return false;
}
-
- void Printf(const char* fmt, ...) __attribute__((__format__(ADB_FORMAT_ARCHETYPE, 2, 3))) {
+ void Printf(const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))) {
std::string s;
va_list ap;
@@ -522,7 +521,7 @@
line_printer_.Print(s, LinePrinter::INFO);
}
- void Println(const char* fmt, ...) __attribute__((__format__(ADB_FORMAT_ARCHETYPE, 2, 3))) {
+ void Println(const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))) {
std::string s;
va_list ap;
@@ -534,7 +533,7 @@
line_printer_.KeepInfoLine();
}
- void Error(const char* fmt, ...) __attribute__((__format__(ADB_FORMAT_ARCHETYPE, 2, 3))) {
+ void Error(const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))) {
std::string s = "adb: error: ";
va_list ap;
@@ -545,7 +544,7 @@
line_printer_.Print(s, LinePrinter::ERROR);
}
- void Warning(const char* fmt, ...) __attribute__((__format__(ADB_FORMAT_ARCHETYPE, 2, 3))) {
+ void Warning(const char* fmt, ...) __attribute__((__format__(__printf__, 2, 3))) {
std::string s = "adb: warning: ";
va_list ap;
diff --git a/adb/sysdeps.h b/adb/sysdeps.h
index 3be99f6..f1197d7 100644
--- a/adb/sysdeps.h
+++ b/adb/sysdeps.h
@@ -39,19 +39,6 @@
#include "sysdeps/network.h"
#include "sysdeps/stat.h"
-// Some printf-like functions are implemented in terms of
-// android::base::StringAppendV, so they should use the same attribute for
-// compile-time format string checking. On Windows, if the mingw version of
-// vsnprintf is used in StringAppendV, use `gnu_printf' which allows z in %zd
-// and PRIu64 (and related) to be recognized by the compile-time checking.
-#define ADB_FORMAT_ARCHETYPE __printf__
-#ifdef __USE_MINGW_ANSI_STDIO
-#if __USE_MINGW_ANSI_STDIO
-#undef ADB_FORMAT_ARCHETYPE
-#define ADB_FORMAT_ARCHETYPE gnu_printf
-#endif
-#endif
-
#ifdef _WIN32
// Clang-only nullability specifiers
@@ -212,14 +199,12 @@
extern int adb_utime(const char *, struct utimbuf *);
extern int adb_chmod(const char *, int);
-extern int adb_vfprintf(FILE *stream, const char *format, va_list ap)
- __attribute__((__format__(ADB_FORMAT_ARCHETYPE, 2, 0)));
-extern int adb_vprintf(const char *format, va_list ap)
- __attribute__((__format__(ADB_FORMAT_ARCHETYPE, 1, 0)));
-extern int adb_fprintf(FILE *stream, const char *format, ...)
- __attribute__((__format__(ADB_FORMAT_ARCHETYPE, 2, 3)));
-extern int adb_printf(const char *format, ...)
- __attribute__((__format__(ADB_FORMAT_ARCHETYPE, 1, 2)));
+extern int adb_vfprintf(FILE* stream, const char* format, va_list ap)
+ __attribute__((__format__(__printf__, 2, 0)));
+extern int adb_vprintf(const char* format, va_list ap) __attribute__((__format__(__printf__, 1, 0)));
+extern int adb_fprintf(FILE* stream, const char* format, ...)
+ __attribute__((__format__(__printf__, 2, 3)));
+extern int adb_printf(const char* format, ...) __attribute__((__format__(__printf__, 1, 2)));
extern int adb_fputs(const char* buf, FILE* stream);
extern int adb_fputc(int ch, FILE* stream);
diff --git a/adb/sysdeps_win32.cpp b/adb/sysdeps_win32.cpp
index bfac342..52f586c 100644
--- a/adb/sysdeps_win32.cpp
+++ b/adb/sysdeps_win32.cpp
@@ -2455,9 +2455,8 @@
}
// Function prototype because attributes cannot be placed on func definitions.
-static int _console_vfprintf(const HANDLE console, FILE* stream,
- const char *format, va_list ap)
- __attribute__((__format__(ADB_FORMAT_ARCHETYPE, 3, 0)));
+static int _console_vfprintf(const HANDLE console, FILE* stream, const char* format, va_list ap)
+ __attribute__((__format__(__printf__, 3, 0)));
// Internal function to format a UTF-8 string and write it to a Win32 console.
// Returns -1 on error.
diff --git a/base/include/android-base/chrono_utils.h b/base/include/android-base/chrono_utils.h
index c3396ee..11fcf71 100644
--- a/base/include/android-base/chrono_utils.h
+++ b/base/include/android-base/chrono_utils.h
@@ -14,13 +14,12 @@
* limitations under the License.
*/
-#ifndef ANDROID_BASE_CHRONO_UTILS_H
-#define ANDROID_BASE_CHRONO_UTILS_H
+#pragma once
#include <chrono>
#include <sstream>
-#if __cplusplus > 201103L // C++14
+#if __cplusplus > 201103L && !defined(__WIN32) // C++14
using namespace std::chrono_literals;
#endif
@@ -52,5 +51,3 @@
} // namespace base
} // namespace android
-
-#endif // ANDROID_BASE_CHRONO_UTILS_H
diff --git a/base/include/android-base/endian.h b/base/include/android-base/endian.h
index 6eb677c..cbbd8c9 100644
--- a/base/include/android-base/endian.h
+++ b/base/include/android-base/endian.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef ANDROID_BASE_ENDIAN_H
-#define ANDROID_BASE_ENDIAN_H
+#pragma once
/* A cross-platform equivalent of bionic's <sys/endian.h>. */
@@ -86,5 +85,3 @@
#define le64toh(x) (x)
#endif
-
-#endif // ANDROID_BASE_ENDIAN_H
diff --git a/base/include/android-base/errors.h b/base/include/android-base/errors.h
index 04c299c..06f29fc 100644
--- a/base/include/android-base/errors.h
+++ b/base/include/android-base/errors.h
@@ -27,8 +27,7 @@
// special handling to get the error string. Refer to Microsoft documentation
// to determine which error code to check for each function.
-#ifndef ANDROID_BASE_ERRORS_H
-#define ANDROID_BASE_ERRORS_H
+#pragma once
#include <string>
@@ -42,5 +41,3 @@
} // namespace base
} // namespace android
-
-#endif // ANDROID_BASE_ERRORS_H
diff --git a/base/include/android-base/file.h b/base/include/android-base/file.h
index 667d6fb..908690b 100644
--- a/base/include/android-base/file.h
+++ b/base/include/android-base/file.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef ANDROID_BASE_FILE_H
-#define ANDROID_BASE_FILE_H
+#pragma once
#include <sys/stat.h>
#include <sys/types.h>
@@ -78,5 +77,3 @@
} // namespace base
} // namespace android
-
-#endif // ANDROID_BASE_FILE_H
diff --git a/base/include/android-base/logging.h b/base/include/android-base/logging.h
index 05a12e7..7f0801f 100644
--- a/base/include/android-base/logging.h
+++ b/base/include/android-base/logging.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef ANDROID_BASE_LOGGING_H
-#define ANDROID_BASE_LOGGING_H
+#pragma once
//
// Google-style C++ logging.
@@ -506,5 +505,3 @@
#undef OSTREAM_STRING_POINTER_USAGE_WARNING
} // namespace std
-
-#endif // ANDROID_BASE_LOGGING_H
diff --git a/base/include/android-base/macros.h b/base/include/android-base/macros.h
index fd6efb2..0c8eac0 100644
--- a/base/include/android-base/macros.h
+++ b/base/include/android-base/macros.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef ANDROID_BASE_MACROS_H
-#define ANDROID_BASE_MACROS_H
+#pragma once
#include <stddef.h> // for size_t
#include <unistd.h> // for TEMP_FAILURE_RETRY
@@ -197,5 +196,3 @@
#elif defined(__mips__) && defined(__LP64__)
#define ABI_STRING "mips64"
#endif
-
-#endif // ANDROID_BASE_MACROS_H
diff --git a/base/include/android-base/memory.h b/base/include/android-base/memory.h
index 9971226..0277a03 100644
--- a/base/include/android-base/memory.h
+++ b/base/include/android-base/memory.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef ANDROID_BASE_MEMORY_H
-#define ANDROID_BASE_MEMORY_H
+#pragma once
namespace android {
namespace base {
@@ -37,5 +36,3 @@
} // namespace base
} // namespace android
-
-#endif // ANDROID_BASE_MEMORY_H
diff --git a/base/include/android-base/parsedouble.h b/base/include/android-base/parsedouble.h
index daa6902..c273c61 100644
--- a/base/include/android-base/parsedouble.h
+++ b/base/include/android-base/parsedouble.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef ANDROID_BASE_PARSEDOUBLE_H
-#define ANDROID_BASE_PARSEDOUBLE_H
+#pragma once
#include <errno.h>
#include <stdlib.h>
@@ -46,5 +45,3 @@
} // namespace base
} // namespace android
-
-#endif // ANDROID_BASE_PARSEDOUBLE_H
diff --git a/base/include/android-base/parseint.h b/base/include/android-base/parseint.h
index 1b7cc5f..b0fc7c3 100644
--- a/base/include/android-base/parseint.h
+++ b/base/include/android-base/parseint.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef ANDROID_BASE_PARSEINT_H
-#define ANDROID_BASE_PARSEINT_H
+#pragma once
#include <errno.h>
#include <stdlib.h>
@@ -104,5 +103,3 @@
} // namespace base
} // namespace android
-
-#endif // ANDROID_BASE_PARSEINT_H
diff --git a/base/include/android-base/parsenetaddress.h b/base/include/android-base/parsenetaddress.h
index b4ac025..47f8b5f 100644
--- a/base/include/android-base/parsenetaddress.h
+++ b/base/include/android-base/parsenetaddress.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef ANDROID_BASE_PARSENETADDRESS_H
-#define ANDROID_BASE_PARSENETADDRESS_H
+#pragma once
#include <string>
@@ -34,5 +33,3 @@
} // namespace base
} // namespace android
-
-#endif // ANDROID_BASE_PARSENETADDRESS_H
diff --git a/base/include/android-base/properties.h b/base/include/android-base/properties.h
index 3a05143..31e5273 100644
--- a/base/include/android-base/properties.h
+++ b/base/include/android-base/properties.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef ANDROID_BASE_PROPERTIES_H
-#define ANDROID_BASE_PROPERTIES_H
+#pragma once
#include <sys/cdefs.h>
@@ -73,5 +72,3 @@
} // namespace base
} // namespace android
-
-#endif // ANDROID_BASE_PROPERTIES_H
diff --git a/base/include/android-base/scopeguard.h b/base/include/android-base/scopeguard.h
index c314e02..e6a9d10 100644
--- a/base/include/android-base/scopeguard.h
+++ b/base/include/android-base/scopeguard.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef ANDROID_BASE_SCOPEGUARD_H
-#define ANDROID_BASE_SCOPEGUARD_H
+#pragma once
#include <utility> // for std::move, std::forward
@@ -66,5 +65,3 @@
} // namespace base
} // namespace android
-
-#endif // ANDROID_BASE_SCOPEGUARD_H
diff --git a/base/include/android-base/stringprintf.h b/base/include/android-base/stringprintf.h
index 1fd6297..93c56af 100644
--- a/base/include/android-base/stringprintf.h
+++ b/base/include/android-base/stringprintf.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef ANDROID_BASE_STRINGPRINTF_H
-#define ANDROID_BASE_STRINGPRINTF_H
+#pragma once
#include <stdarg.h>
#include <string>
@@ -24,33 +23,18 @@
namespace base {
// These printf-like functions are implemented in terms of vsnprintf, so they
-// use the same attribute for compile-time format string checking. On Windows,
-// if the mingw version of vsnprintf is used, use `gnu_printf' which allows z
-// in %zd and PRIu64 (and related) to be recognized by the compile-time
-// checking.
-#define ANDROID_BASE_FORMAT_ARCHETYPE __printf__
-#ifdef __USE_MINGW_ANSI_STDIO
-#if __USE_MINGW_ANSI_STDIO
-#undef ANDROID_BASE_FORMAT_ARCHETYPE
-#define ANDROID_BASE_FORMAT_ARCHETYPE gnu_printf
-#endif
-#endif
+// use the same attribute for compile-time format string checking.
// Returns a string corresponding to printf-like formatting of the arguments.
-std::string StringPrintf(const char* fmt, ...)
- __attribute__((__format__(ANDROID_BASE_FORMAT_ARCHETYPE, 1, 2)));
+std::string StringPrintf(const char* fmt, ...) __attribute__((__format__(__printf__, 1, 2)));
// Appends a printf-like formatting of the arguments to 'dst'.
void StringAppendF(std::string* dst, const char* fmt, ...)
- __attribute__((__format__(ANDROID_BASE_FORMAT_ARCHETYPE, 2, 3)));
+ __attribute__((__format__(__printf__, 2, 3)));
// Appends a printf-like formatting of the arguments to 'dst'.
void StringAppendV(std::string* dst, const char* format, va_list ap)
- __attribute__((__format__(ANDROID_BASE_FORMAT_ARCHETYPE, 2, 0)));
-
-#undef ANDROID_BASE_FORMAT_ARCHETYPE
+ __attribute__((__format__(__printf__, 2, 0)));
} // namespace base
} // namespace android
-
-#endif // ANDROID_BASE_STRINGPRINTF_H
diff --git a/base/include/android-base/strings.h b/base/include/android-base/strings.h
index 4d9fa34..9c35560 100644
--- a/base/include/android-base/strings.h
+++ b/base/include/android-base/strings.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef ANDROID_BASE_STRINGS_H
-#define ANDROID_BASE_STRINGS_H
+#pragma once
#include <sstream>
#include <string>
@@ -75,5 +74,3 @@
} // namespace base
} // namespace android
-
-#endif // ANDROID_BASE_STRINGS_H
diff --git a/base/include/android-base/test_utils.h b/base/include/android-base/test_utils.h
index b29676f..9e2ea97 100644
--- a/base/include/android-base/test_utils.h
+++ b/base/include/android-base/test_utils.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef ANDROID_BASE_TEST_UTILS_H
-#define ANDROID_BASE_TEST_UTILS_H
+#pragma once
#include <regex>
#include <string>
@@ -114,5 +113,3 @@
ADD_FAILURE() << "regex mismatch: expected to not find " << (pattern) << " in:\n" << (str); \
} \
} while (0)
-
-#endif // ANDROID_BASE_TEST_UTILS_H
diff --git a/base/include/android-base/thread_annotations.h b/base/include/android-base/thread_annotations.h
index 1307f0e..d56e935 100644
--- a/base/include/android-base/thread_annotations.h
+++ b/base/include/android-base/thread_annotations.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef ANDROID_BASE_THREAD_ANNOTATIONS_H
-#define ANDROID_BASE_THREAD_ANNOTATIONS_H
+#pragma once
#if defined(__SUPPORT_TS_ANNOTATION__) || defined(__clang__)
#define THREAD_ANNOTATION_ATTRIBUTE__(x) __attribute__((x))
@@ -109,5 +108,3 @@
#define NO_THREAD_SAFETY_ANALYSIS \
THREAD_ANNOTATION_ATTRIBUTE__(no_thread_safety_analysis)
-
-#endif // ANDROID_BASE_THREAD_ANNOTATIONS_H
diff --git a/base/include/android-base/threads.h b/base/include/android-base/threads.h
index 85e65ba..f4ba809 100644
--- a/base/include/android-base/threads.h
+++ b/base/include/android-base/threads.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef ANDROID_BASE_THREADS_H
-#define ANDROID_BASE_THREADS_H
+#pragma once
#include <stdint.h>
@@ -24,5 +23,3 @@
uint64_t GetThreadId();
}
} // namespace android
-
-#endif
diff --git a/base/include/android-base/unique_fd.h b/base/include/android-base/unique_fd.h
index 5d89271..d334e30 100644
--- a/base/include/android-base/unique_fd.h
+++ b/base/include/android-base/unique_fd.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef ANDROID_BASE_UNIQUE_FD_H
-#define ANDROID_BASE_UNIQUE_FD_H
+#pragma once
#include <fcntl.h>
@@ -150,5 +149,3 @@
#endif
"close called on unique_fd"
)));
-
-#endif // ANDROID_BASE_UNIQUE_FD_H
diff --git a/base/include/android-base/utf8.h b/base/include/android-base/utf8.h
index c9cc1ab..4b91623 100755
--- a/base/include/android-base/utf8.h
+++ b/base/include/android-base/utf8.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef ANDROID_BASE_UTF8_H
-#define ANDROID_BASE_UTF8_H
+#pragma once
#ifdef _WIN32
#include <string>
@@ -102,5 +101,3 @@
} // namespace utf8
} // namespace base
} // namespace android
-
-#endif // ANDROID_BASE_UTF8_H
diff --git a/fastboot/fastboot.h b/fastboot/fastboot.h
index 2935eb5..50c70f3 100644
--- a/fastboot/fastboot.h
+++ b/fastboot/fastboot.h
@@ -78,21 +78,10 @@
void set_verbose();
// These printf-like functions are implemented in terms of vsnprintf, so they
-// use the same attribute for compile-time format string checking. On Windows,
-// if the mingw version of vsnprintf is used, use `gnu_printf' which allows z
-// in %zd and PRIu64 (and related) to be recognized by the compile-time
-// checking.
-#define FASTBOOT_FORMAT_ARCHETYPE __printf__
-#ifdef __USE_MINGW_ANSI_STDIO
-#if __USE_MINGW_ANSI_STDIO
-#undef FASTBOOT_FORMAT_ARCHETYPE
-#define FASTBOOT_FORMAT_ARCHETYPE gnu_printf
-#endif
-#endif
+// use the same attribute for compile-time format string checking.
void die(const char* fmt, ...) __attribute__((__noreturn__))
-__attribute__((__format__(FASTBOOT_FORMAT_ARCHETYPE, 1, 2)));
-void verbose(const char* fmt, ...) __attribute__((__format__(FASTBOOT_FORMAT_ARCHETYPE, 1, 2)));
-#undef FASTBOOT_FORMAT_ARCHETYPE
+__attribute__((__format__(__printf__, 1, 2)));
+void verbose(const char* fmt, ...) __attribute__((__format__(__printf__, 1, 2)));
/* Current product */
extern char cur_product[FB_RESPONSE_SZ + 1];
diff --git a/fs_mgr/Android.bp b/fs_mgr/Android.bp
index b0b4839..a3ce879 100644
--- a/fs_mgr/Android.bp
+++ b/fs_mgr/Android.bp
@@ -38,7 +38,6 @@
include_dirs: ["system/vold"],
srcs: [
"fs_mgr.cpp",
- "fs_mgr_dm_ioctl.cpp",
"fs_mgr_format.cpp",
"fs_mgr_verity.cpp",
"fs_mgr_avb.cpp",
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp
index 9856126..b3df811 100644
--- a/fs_mgr/fs_mgr.cpp
+++ b/fs_mgr/fs_mgr.cpp
@@ -31,6 +31,7 @@
#include <time.h>
#include <unistd.h>
+#include <functional>
#include <memory>
#include <string>
#include <thread>
@@ -50,6 +51,7 @@
#include <ext4_utils/ext4_sb.h>
#include <ext4_utils/ext4_utils.h>
#include <ext4_utils/wipe.h>
+#include <libdm/dm.h>
#include <linux/fs.h>
#include <linux/loop.h>
#include <linux/magic.h>
@@ -59,7 +61,6 @@
#include "fs_mgr.h"
#include "fs_mgr_avb.h"
#include "fs_mgr_priv.h"
-#include "fs_mgr_priv_dm_ioctl.h"
#define KEY_LOC_PROP "ro.crypto.keyfile.userdata"
#define KEY_IN_FOOTER "footer"
@@ -76,6 +77,8 @@
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
+using DeviceMapper = android::dm::DeviceMapper;
+
// record fs stat
enum FsStatFlags {
FS_STAT_IS_EXT4 = 0x0001,
@@ -802,14 +805,9 @@
return true;
}
- android::base::unique_fd dm_fd(open("/dev/device-mapper", O_RDONLY));
- if (dm_fd < 0) {
- PLOG(ERROR) << "open /dev/device-mapper failed";
- return false;
- }
- struct dm_ioctl io;
+ DeviceMapper& dm = DeviceMapper::Instance();
std::string device_name;
- if (!fs_mgr_dm_get_device_name(&io, rec->blk_device, dm_fd, &device_name)) {
+ if (!dm.GetDmDevicePathByName(rec->blk_device, &device_name)) {
return false;
}
free(rec->blk_device);
@@ -1359,7 +1357,7 @@
return true;
}
-bool fs_mgr_update_verity_state(fs_mgr_verity_state_callback callback) {
+bool fs_mgr_update_verity_state(std::function<fs_mgr_verity_state_callback> callback) {
if (!callback) {
return false;
}
@@ -1369,12 +1367,6 @@
return false;
}
- android::base::unique_fd fd(TEMP_FAILURE_RETRY(open("/dev/device-mapper", O_RDWR | O_CLOEXEC)));
- if (fd == -1) {
- PERROR << "Error opening device mapper";
- return false;
- }
-
std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_default(),
fs_mgr_free_fstab);
if (!fstab) {
@@ -1382,8 +1374,8 @@
return false;
}
- alignas(dm_ioctl) char buffer[DM_BUF_SIZE];
- struct dm_ioctl* io = (struct dm_ioctl*)buffer;
+ DeviceMapper& dm = DeviceMapper::Instance();
+
bool system_root = android::base::GetProperty("ro.build.system_root_image", "") == "true";
for (int i = 0; i < fstab->num_entries; i++) {
@@ -1399,20 +1391,20 @@
mount_point = basename(fstab->recs[i].mount_point);
}
- fs_mgr_dm_ioctl_init(io, DM_BUF_SIZE, mount_point);
+ const char* status = nullptr;
- const char* status;
- if (ioctl(fd, DM_TABLE_STATUS, io)) {
+ std::vector<DeviceMapper::TargetInfo> table;
+ if (!dm.GetTableStatus(mount_point, &table) || table.empty() || table[0].data.empty()) {
if (fstab->recs[i].fs_mgr_flags & MF_VERIFYATBOOT) {
status = "V";
} else {
PERROR << "Failed to query DM_TABLE_STATUS for " << mount_point.c_str();
continue;
}
+ } else {
+ status = table[0].data.c_str();
}
- status = &buffer[io->data_start + sizeof(struct dm_target_spec)];
-
// To be consistent in vboot 1.0 and vboot 2.0 (AVB), change the mount_point
// back to 'system' for the callback. So it has property [partition.system.verified]
// instead of [partition.vroot.verified].
diff --git a/fs_mgr/fs_mgr_avb.cpp b/fs_mgr/fs_mgr_avb.cpp
index 2020fa6..7c6093e 100644
--- a/fs_mgr/fs_mgr_avb.cpp
+++ b/fs_mgr/fs_mgr_avb.cpp
@@ -33,11 +33,11 @@
#include <android-base/strings.h>
#include <android-base/unique_fd.h>
#include <libavb/libavb.h>
+#include <libdm/dm.h>
#include "fs_mgr.h"
#include "fs_mgr_priv.h"
#include "fs_mgr_priv_avb_ops.h"
-#include "fs_mgr_priv_dm_ioctl.h"
#include "fs_mgr_priv_sha.h"
static inline bool nibble_value(const char& c, uint8_t* value) {
@@ -218,9 +218,9 @@
// Constructs dm-verity arguments for sending DM_TABLE_LOAD ioctl to kernel.
// See the following link for more details:
// https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity
-static std::string construct_verity_table(const AvbHashtreeDescriptor& hashtree_desc,
- const std::string& salt, const std::string& root_digest,
- const std::string& blk_device) {
+static bool construct_verity_table(const AvbHashtreeDescriptor& hashtree_desc,
+ const std::string& salt, const std::string& root_digest,
+ const std::string& blk_device, android::dm::DmTable* table) {
// Loads androidboot.veritymode from kernel cmdline.
std::string verity_mode;
if (!fs_mgr_get_boot_config("veritymode", &verity_mode)) {
@@ -235,145 +235,56 @@
dm_verity_mode = "ignore_corruption";
} else if (verity_mode != "eio") { // Default dm_verity_mode is eio.
LERROR << "Unknown androidboot.veritymode: " << verity_mode;
- return "";
+ return false;
}
- // dm-verity construction parameters:
- // <version> <dev> <hash_dev>
- // <data_block_size> <hash_block_size>
- // <num_data_blocks> <hash_start_block>
- // <algorithm> <digest> <salt>
- // [<#opt_params> <opt_params>]
- std::ostringstream verity_table;
- verity_table << hashtree_desc.dm_verity_version << " " << blk_device << " " << blk_device << " "
- << hashtree_desc.data_block_size << " " << hashtree_desc.hash_block_size << " "
- << hashtree_desc.image_size / hashtree_desc.data_block_size << " "
- << hashtree_desc.tree_offset / hashtree_desc.hash_block_size << " "
- << hashtree_desc.hash_algorithm << " " << root_digest << " " << salt;
+ std::ostringstream hash_algorithm;
+ hash_algorithm << hashtree_desc.hash_algorithm;
- // Continued from the above optional parameters:
- // [<#opt_params> <opt_params>]
- int optional_argc = 0;
- std::ostringstream optional_args;
-
- // dm-verity optional parameters for FEC (forward error correction):
- // use_fec_from_device <fec_dev>
- // fec_roots <num>
- // fec_blocks <num>
- // fec_start <offset>
+ android::dm::DmTargetVerity target(0, hashtree_desc.image_size / 512,
+ hashtree_desc.dm_verity_version, blk_device, blk_device,
+ hashtree_desc.data_block_size, hashtree_desc.hash_block_size,
+ hashtree_desc.image_size / hashtree_desc.data_block_size,
+ hashtree_desc.tree_offset / hashtree_desc.hash_block_size,
+ hash_algorithm.str(), root_digest, salt);
if (hashtree_desc.fec_size > 0) {
- // Note that fec_blocks is the size that FEC covers, *NOT* the
- // size of the FEC data. Since we use FEC for everything up until
- // the FEC data, it's the same as the offset (fec_start).
- optional_argc += 8;
- // clang-format off
- optional_args << "use_fec_from_device " << blk_device
- << " fec_roots " << hashtree_desc.fec_num_roots
- << " fec_blocks " << hashtree_desc.fec_offset / hashtree_desc.data_block_size
- << " fec_start " << hashtree_desc.fec_offset / hashtree_desc.data_block_size
- << " ";
- // clang-format on
+ target.UseFec(blk_device, hashtree_desc.fec_num_roots,
+ hashtree_desc.fec_offset / hashtree_desc.data_block_size,
+ hashtree_desc.fec_offset / hashtree_desc.data_block_size);
}
-
if (!dm_verity_mode.empty()) {
- optional_argc += 1;
- optional_args << dm_verity_mode << " ";
+ target.SetVerityMode(dm_verity_mode);
}
-
// Always use ignore_zero_blocks.
- optional_argc += 1;
- optional_args << "ignore_zero_blocks";
+ target.IgnoreZeroBlocks();
- verity_table << " " << optional_argc << " " << optional_args.str();
- return verity_table.str();
-}
+ LINFO << "Built verity table: '" << target.GetParameterString() << "'";
-static bool load_verity_table(struct dm_ioctl* io, const std::string& dm_device_name, int fd,
- uint64_t image_size, const std::string& verity_table) {
- fs_mgr_dm_ioctl_init(io, DM_BUF_SIZE, dm_device_name);
-
- // The buffer consists of [dm_ioctl][dm_target_spec][verity_params].
- char* buffer = (char*)io;
-
- // Builds the dm_target_spec arguments.
- struct dm_target_spec* dm_target = (struct dm_target_spec*)&buffer[sizeof(struct dm_ioctl)];
- io->flags = DM_READONLY_FLAG;
- io->target_count = 1;
- dm_target->status = 0;
- dm_target->sector_start = 0;
- dm_target->length = image_size / 512;
- strcpy(dm_target->target_type, "verity");
-
- // Builds the verity params.
- char* verity_params = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec);
- size_t bufsize = DM_BUF_SIZE - (verity_params - buffer);
-
- LINFO << "Loading verity table: '" << verity_table << "'";
-
- // Copies verity_table to verity_params (including the terminating null byte).
- if (verity_table.size() > bufsize - 1) {
- LERROR << "Verity table size too large: " << verity_table.size()
- << " (max allowable size: " << bufsize - 1 << ")";
- return false;
- }
- memcpy(verity_params, verity_table.c_str(), verity_table.size() + 1);
-
- // Sets ext target boundary.
- verity_params += verity_table.size() + 1;
- verity_params = (char*)(((unsigned long)verity_params + 7) & ~7);
- dm_target->next = verity_params - buffer;
-
- // Sends the ioctl to load the verity table.
- if (ioctl(fd, DM_TABLE_LOAD, io)) {
- PERROR << "Error loading verity table";
- return false;
- }
-
- return true;
+ return table->AddTarget(std::make_unique<android::dm::DmTargetVerity>(target));
}
static bool hashtree_dm_verity_setup(struct fstab_rec* fstab_entry,
const AvbHashtreeDescriptor& hashtree_desc,
const std::string& salt, const std::string& root_digest,
bool wait_for_verity_dev) {
- // Gets the device mapper fd.
- android::base::unique_fd fd(open("/dev/device-mapper", O_RDWR));
- if (fd < 0) {
- PERROR << "Error opening device mapper";
+ android::dm::DmTable table;
+ if (!construct_verity_table(hashtree_desc, salt, root_digest, fstab_entry->blk_device, &table) ||
+ !table.valid()) {
+ LERROR << "Failed to construct verity table.";
return false;
}
+ table.set_readonly(true);
- // Creates the device.
- alignas(dm_ioctl) char buffer[DM_BUF_SIZE];
- struct dm_ioctl* io = (struct dm_ioctl*)buffer;
const std::string mount_point(basename(fstab_entry->mount_point));
- if (!fs_mgr_dm_create_device(io, mount_point, fd)) {
+ android::dm::DeviceMapper& dm = android::dm::DeviceMapper::Instance();
+ if (!dm.CreateDevice(mount_point, table)) {
LERROR << "Couldn't create verity device!";
return false;
}
- // Gets the name of the device file.
- std::string verity_blk_name;
- if (!fs_mgr_dm_get_device_name(io, mount_point, fd, &verity_blk_name)) {
- LERROR << "Couldn't get verity device number!";
- return false;
- }
-
- std::string verity_table =
- construct_verity_table(hashtree_desc, salt, root_digest, fstab_entry->blk_device);
- if (verity_table.empty()) {
- LERROR << "Failed to construct verity table.";
- return false;
- }
-
- // Loads the verity mapping table.
- if (!load_verity_table(io, mount_point, fd, hashtree_desc.image_size, verity_table)) {
- LERROR << "Couldn't load verity table!";
- return false;
- }
-
- // Activates the device.
- if (!fs_mgr_dm_resume_table(io, mount_point, fd)) {
+ std::string dev_path;
+ if (!dm.GetDmDevicePathByName(mount_point, &dev_path)) {
+ LERROR << "Couldn't get verity device path!";
return false;
}
@@ -382,10 +293,10 @@
// Updates fstab_rec->blk_device to verity device name.
free(fstab_entry->blk_device);
- fstab_entry->blk_device = strdup(verity_blk_name.c_str());
+ fstab_entry->blk_device = strdup(dev_path.c_str());
// Makes sure we've set everything up properly.
- if (wait_for_verity_dev && !fs_mgr_wait_for_file(verity_blk_name, 1s)) {
+ if (wait_for_verity_dev && !fs_mgr_wait_for_file(dev_path, 1s)) {
return false;
}
diff --git a/fs_mgr/fs_mgr_dm_ioctl.cpp b/fs_mgr/fs_mgr_dm_ioctl.cpp
deleted file mode 100644
index 3a7fae4..0000000
--- a/fs_mgr/fs_mgr_dm_ioctl.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <errno.h>
-#include <string.h>
-
-#include <android-base/logging.h>
-#include <sys/ioctl.h>
-
-#include "fs_mgr_priv.h"
-#include "fs_mgr_priv_dm_ioctl.h"
-
-void fs_mgr_dm_ioctl_init(struct dm_ioctl* io, size_t size, const std::string& name) {
- memset(io, 0, size);
- io->data_size = size;
- io->data_start = sizeof(struct dm_ioctl);
- io->version[0] = 4;
- io->version[1] = 0;
- io->version[2] = 0;
- if (!name.empty()) {
- strlcpy(io->name, name.c_str(), sizeof(io->name));
- }
-}
-
-bool fs_mgr_dm_create_device(struct dm_ioctl* io, const std::string& name, int fd) {
- fs_mgr_dm_ioctl_init(io, sizeof(*io), name);
- if (ioctl(fd, DM_DEV_CREATE, io)) {
- PERROR << "Error creating device mapping";
- return false;
- }
- return true;
-}
-
-bool fs_mgr_dm_destroy_device(struct dm_ioctl* io, const std::string& name, int fd) {
- fs_mgr_dm_ioctl_init(io, sizeof(*io), name);
- if (ioctl(fd, DM_DEV_REMOVE, io)) {
- PERROR << "Error removing device mapping";
- return false;
- }
- return true;
-}
-
-bool fs_mgr_dm_get_device_name(struct dm_ioctl* io, const std::string& name, int fd,
- std::string* out_dev_name) {
- FS_MGR_CHECK(out_dev_name != nullptr);
-
- fs_mgr_dm_ioctl_init(io, sizeof(*io), name);
- if (ioctl(fd, DM_DEV_STATUS, io)) {
- PERROR << "Error fetching device-mapper device number";
- return false;
- }
-
- int dev_num = (io->dev & 0xff) | ((io->dev >> 12) & 0xfff00);
- *out_dev_name = "/dev/block/dm-" + std::to_string(dev_num);
-
- return true;
-}
-
-bool fs_mgr_dm_resume_table(struct dm_ioctl* io, const std::string& name, int fd) {
- fs_mgr_dm_ioctl_init(io, sizeof(*io), name);
- if (ioctl(fd, DM_DEV_SUSPEND, io)) {
- PERROR << "Error activating device table";
- return false;
- }
- return true;
-}
diff --git a/fs_mgr/fs_mgr_dm_linear.cpp b/fs_mgr/fs_mgr_dm_linear.cpp
index ed42d40..5159b4c 100644
--- a/fs_mgr/fs_mgr_dm_linear.cpp
+++ b/fs_mgr/fs_mgr_dm_linear.cpp
@@ -40,93 +40,32 @@
#include <liblp/reader.h>
#include "fs_mgr_priv.h"
-#include "fs_mgr_priv_dm_ioctl.h"
namespace android {
namespace fs_mgr {
-std::string LogicalPartitionExtent::Serialize() const {
- // Note: we need to include an explicit null-terminator.
- std::string argv =
- android::base::StringPrintf("%s %" PRIu64, block_device_.c_str(), first_sector_);
- argv.push_back(0);
+using DeviceMapper = android::dm::DeviceMapper;
+using DmTable = android::dm::DmTable;
+using DmTarget = android::dm::DmTarget;
+using DmTargetZero = android::dm::DmTargetZero;
+using DmTargetLinear = android::dm::DmTargetLinear;
- // The kernel expects each target to be aligned.
- size_t spec_bytes = sizeof(struct dm_target_spec) + argv.size();
- size_t padding = ((spec_bytes + 7) & ~7) - spec_bytes;
- for (size_t i = 0; i < padding; i++) {
- argv.push_back(0);
- }
-
- struct dm_target_spec spec;
- spec.sector_start = logical_sector_;
- spec.length = num_sectors_;
- spec.status = 0;
- strcpy(spec.target_type, "linear");
- spec.next = sizeof(struct dm_target_spec) + argv.size();
-
- return std::string((char*)&spec, sizeof(spec)) + argv;
-}
-
-static bool LoadDmTable(int dm_fd, const LogicalPartition& partition) {
- // Combine all dm_target_spec buffers together.
- std::string target_string;
+static bool CreateDmDeviceForPartition(DeviceMapper& dm, const LogicalPartition& partition) {
+ DmTable table;
for (const auto& extent : partition.extents) {
- target_string += extent.Serialize();
+ table.AddTarget(std::make_unique<DmTargetLinear>(extent));
}
-
- // Allocate the ioctl buffer.
- size_t buffer_size = sizeof(struct dm_ioctl) + target_string.size();
- std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(buffer_size);
-
- // Initialize the ioctl buffer header, then copy our target specs in.
- struct dm_ioctl* io = reinterpret_cast<struct dm_ioctl*>(buffer.get());
- fs_mgr_dm_ioctl_init(io, buffer_size, partition.name);
- io->target_count = partition.extents.size();
- if (partition.attributes & kPartitionReadonly) {
- io->flags |= DM_READONLY_FLAG;
- }
- memcpy(io + 1, target_string.c_str(), target_string.size());
-
- if (ioctl(dm_fd, DM_TABLE_LOAD, io)) {
- PERROR << "Failed ioctl() on DM_TABLE_LOAD, partition " << partition.name;
+ if (!dm.CreateDevice(partition.name, table)) {
return false;
}
- return true;
-}
-
-static bool LoadTablesAndActivate(int dm_fd, const LogicalPartition& partition) {
- if (!LoadDmTable(dm_fd, partition)) {
- return false;
- }
-
- struct dm_ioctl io;
- return fs_mgr_dm_resume_table(&io, partition.name, dm_fd);
-}
-
-static bool CreateDmDeviceForPartition(int dm_fd, const LogicalPartition& partition) {
- struct dm_ioctl io;
- if (!fs_mgr_dm_create_device(&io, partition.name, dm_fd)) {
- return false;
- }
- if (!LoadTablesAndActivate(dm_fd, partition)) {
- // Remove the device rather than leave it in an inactive state.
- fs_mgr_dm_destroy_device(&io, partition.name, dm_fd);
- return false;
- }
-
LINFO << "Created device-mapper device: " << partition.name;
return true;
}
bool CreateLogicalPartitions(const LogicalPartitionTable& table) {
- android::base::unique_fd dm_fd(open("/dev/device-mapper", O_RDWR));
- if (dm_fd < 0) {
- PLOG(ERROR) << "failed to open /dev/device-mapper";
- return false;
- }
+ DeviceMapper& dm = DeviceMapper::Instance();
for (const auto& partition : table.partitions) {
- if (!CreateDmDeviceForPartition(dm_fd, partition)) {
+ if (!CreateDmDeviceForPartition(dm, partition)) {
LOG(ERROR) << "could not create dm-linear device for partition: " << partition.name;
return false;
}
@@ -138,6 +77,35 @@
return nullptr;
}
+static bool CreateDmTable(const std::string& block_device, const LpMetadata& metadata,
+ const LpMetadataPartition& partition, DmTable* table) {
+ uint64_t sector = 0;
+ for (size_t i = 0; i < partition.num_extents; i++) {
+ const auto& extent = metadata.extents[partition.first_extent_index + i];
+ std::unique_ptr<DmTarget> target;
+ switch (extent.target_type) {
+ case LP_TARGET_TYPE_ZERO:
+ target = std::make_unique<DmTargetZero>(sector, extent.num_sectors);
+ break;
+ case LP_TARGET_TYPE_LINEAR:
+ target = std::make_unique<DmTargetLinear>(sector, extent.num_sectors, block_device,
+ extent.target_data);
+ break;
+ default:
+ LOG(ERROR) << "Unknown target type in metadata: " << extent.target_type;
+ return false;
+ }
+ if (!table->AddTarget(std::move(target))) {
+ return false;
+ }
+ sector += extent.num_sectors;
+ }
+ if (partition.attributes & LP_PARTITION_ATTR_READONLY) {
+ table->set_readonly(true);
+ }
+ return true;
+}
+
bool CreateLogicalPartitions(const std::string& block_device) {
uint32_t slot = SlotNumberForSlotSuffix(fs_mgr_get_slot_suffix());
auto metadata = ReadMetadata(block_device.c_str(), slot);
@@ -146,21 +114,21 @@
return true;
}
- LogicalPartitionTable table;
+ DeviceMapper& dm = DeviceMapper::Instance();
for (const auto& partition : metadata->partitions) {
- LogicalPartition new_partition;
- new_partition.name = GetPartitionName(partition);
- new_partition.attributes = partition.attributes;
- for (size_t i = 0; i < partition.num_extents; i++) {
- const auto& extent = metadata->extents[partition.first_extent_index + i];
- new_partition.extents.emplace_back(new_partition.num_sectors, extent.target_data,
- extent.num_sectors, block_device.c_str());
- new_partition.num_sectors += extent.num_sectors;
+ DmTable table;
+ if (!CreateDmTable(block_device, *metadata.get(), partition, &table)) {
+ return false;
}
- table.partitions.push_back(new_partition);
+ std::string name = GetPartitionName(partition);
+ if (!dm.CreateDevice(name, table)) {
+ return false;
+ }
+ std::string path;
+ dm.GetDmDevicePathByName(partition.name, &path);
+ LINFO << "Created logical partition " << name << " on device " << path;
}
-
- return CreateLogicalPartitions(table);
+ return true;
}
} // namespace fs_mgr
diff --git a/fs_mgr/fs_mgr_fstab.cpp b/fs_mgr/fs_mgr_fstab.cpp
index a14dba3..a5b3fe8 100644
--- a/fs_mgr/fs_mgr_fstab.cpp
+++ b/fs_mgr/fs_mgr_fstab.cpp
@@ -235,41 +235,46 @@
* If not found, the loop exits with fl[i].name being null.
*/
for (i = 0; fl[i].name; i++) {
- if (!strncmp(p, fl[i].name, strlen(fl[i].name))) {
+ auto name = fl[i].name;
+ auto len = strlen(name);
+ auto end = len;
+ if (name[end - 1] == '=') --end;
+ if (!strncmp(p, name, len) && (p[end] == name[end])) {
f |= fl[i].flag;
- if ((fl[i].flag == MF_CRYPT) && flag_vals) {
+ if (!flag_vals) break;
+ if (p[end] != '=') break;
+ char* arg = p + end + 1;
+ auto flag = fl[i].flag;
+ if (flag == MF_CRYPT) {
/* The encryptable flag is followed by an = and the
* location of the keys. Get it and return it.
*/
- flag_vals->key_loc = strdup(strchr(p, '=') + 1);
- } else if ((fl[i].flag == MF_VERIFY) && flag_vals) {
+ flag_vals->key_loc = strdup(arg);
+ } else if (flag == MF_VERIFY) {
/* If the verify flag is followed by an = and the
* location for the verity state, get it and return it.
*/
- char *start = strchr(p, '=');
- if (start) {
- flag_vals->verity_loc = strdup(start + 1);
- }
- } else if ((fl[i].flag == MF_FORCECRYPT) && flag_vals) {
+ flag_vals->verity_loc = strdup(arg);
+ } else if (flag == MF_FORCECRYPT) {
/* The forceencrypt flag is followed by an = and the
* location of the keys. Get it and return it.
*/
- flag_vals->key_loc = strdup(strchr(p, '=') + 1);
- } else if ((fl[i].flag == MF_FORCEFDEORFBE) && flag_vals) {
+ flag_vals->key_loc = strdup(arg);
+ } else if (flag == MF_FORCEFDEORFBE) {
/* The forcefdeorfbe flag is followed by an = and the
* location of the keys. Get it and return it.
*/
- flag_vals->key_loc = strdup(strchr(p, '=') + 1);
+ flag_vals->key_loc = strdup(arg);
flag_vals->file_contents_mode = EM_AES_256_XTS;
flag_vals->file_names_mode = EM_AES_256_CTS;
- } else if ((fl[i].flag == MF_FILEENCRYPTION) && flag_vals) {
+ } else if (flag == MF_FILEENCRYPTION) {
/* The fileencryption flag is followed by an = and
* the mode of contents encryption, then optionally a
* : and the mode of filenames encryption (defaults
* to aes-256-cts). Get it and return it.
*/
- char *mode = strchr(p, '=') + 1;
- char *colon = strchr(mode, ':');
+ auto mode = arg;
+ auto colon = strchr(mode, ':');
if (colon) {
*colon = '\0';
}
@@ -283,33 +288,30 @@
} else {
flag_vals->file_names_mode = EM_AES_256_CTS;
}
- } else if ((fl[i].flag == MF_KEYDIRECTORY) && flag_vals) {
+ } else if (flag == MF_KEYDIRECTORY) {
/* The metadata flag is followed by an = and the
* directory for the keys. Get it and return it.
*/
- flag_vals->key_dir = strdup(strchr(p, '=') + 1);
- } else if ((fl[i].flag == MF_LENGTH) && flag_vals) {
+ flag_vals->key_dir = strdup(arg);
+ } else if (flag == MF_LENGTH) {
/* The length flag is followed by an = and the
* size of the partition. Get it and return it.
*/
- flag_vals->part_length = strtoll(strchr(p, '=') + 1, NULL, 0);
- } else if ((fl[i].flag == MF_VOLDMANAGED) && flag_vals) {
+ flag_vals->part_length = strtoll(arg, NULL, 0);
+ } else if (flag == MF_VOLDMANAGED) {
/* The voldmanaged flag is followed by an = and the
* label, a colon and the partition number or the
* word "auto", e.g.
* voldmanaged=sdcard:3
* Get and return them.
*/
- char *label_start;
- char *label_end;
- char *part_start;
+ auto label_start = arg;
+ auto label_end = strchr(label_start, ':');
- label_start = strchr(p, '=') + 1;
- label_end = strchr(p, ':');
if (label_end) {
flag_vals->label = strndup(label_start,
(int) (label_end - label_start));
- part_start = strchr(p, ':') + 1;
+ auto part_start = label_end + 1;
if (!strcmp(part_start, "auto")) {
flag_vals->partnum = -1;
} else {
@@ -318,41 +320,41 @@
} else {
LERROR << "Warning: voldmanaged= flag malformed";
}
- } else if ((fl[i].flag == MF_SWAPPRIO) && flag_vals) {
- flag_vals->swap_prio = strtoll(strchr(p, '=') + 1, NULL, 0);
- } else if ((fl[i].flag == MF_MAX_COMP_STREAMS) && flag_vals) {
- flag_vals->max_comp_streams = strtoll(strchr(p, '=') + 1, NULL, 0);
- } else if ((fl[i].flag == MF_ZRAMSIZE) && flag_vals) {
- int is_percent = !!strrchr(p, '%');
- unsigned int val = strtoll(strchr(p, '=') + 1, NULL, 0);
+ } else if (flag == MF_SWAPPRIO) {
+ flag_vals->swap_prio = strtoll(arg, NULL, 0);
+ } else if (flag == MF_MAX_COMP_STREAMS) {
+ flag_vals->max_comp_streams = strtoll(arg, NULL, 0);
+ } else if (flag == MF_ZRAMSIZE) {
+ auto is_percent = !!strrchr(arg, '%');
+ auto val = strtoll(arg, NULL, 0);
if (is_percent)
flag_vals->zram_size = calculate_zram_size(val);
else
flag_vals->zram_size = val;
- } else if ((fl[i].flag == MF_RESERVEDSIZE) && flag_vals) {
+ } else if (flag == MF_RESERVEDSIZE) {
/* The reserved flag is followed by an = and the
* reserved size of the partition. Get it and return it.
*/
- flag_vals->reserved_size = parse_size(strchr(p, '=') + 1);
- } else if ((fl[i].flag == MF_ERASEBLKSIZE) && flag_vals) {
+ flag_vals->reserved_size = parse_size(arg);
+ } else if (flag == MF_ERASEBLKSIZE) {
/* The erase block size flag is followed by an = and the flash
* erase block size. Get it, check that it is a power of 2 and
* at least 4096, and return it.
*/
- unsigned int val = strtoul(strchr(p, '=') + 1, NULL, 0);
+ auto val = strtoul(arg, NULL, 0);
if (val >= 4096 && (val & (val - 1)) == 0)
flag_vals->erase_blk_size = val;
- } else if ((fl[i].flag == MF_LOGICALBLKSIZE) && flag_vals) {
+ } else if (flag == MF_LOGICALBLKSIZE) {
/* The logical block size flag is followed by an = and the flash
* logical block size. Get it, check that it is a power of 2 and
* at least 4096, and return it.
*/
- unsigned int val = strtoul(strchr(p, '=') + 1, NULL, 0);
+ auto val = strtoul(arg, NULL, 0);
if (val >= 4096 && (val & (val - 1)) == 0)
flag_vals->logical_blk_size = val;
- } else if ((fl[i].flag == MF_SYSFS) && flag_vals) {
+ } else if (flag == MF_SYSFS) {
/* The path to trigger device gc by idle-maint of vold. */
- flag_vals->sysfs_path = strdup(strchr(p, '=') + 1);
+ flag_vals->sysfs_path = strdup(arg);
}
break;
}
@@ -506,8 +508,7 @@
return false;
}
-static struct fstab *fs_mgr_read_fstab_file(FILE *fstab_file)
-{
+static struct fstab* fs_mgr_read_fstab_file(FILE* fstab_file, bool proc_mounts) {
int cnt, entries;
ssize_t len;
size_t alloc_len = 0;
@@ -607,7 +608,10 @@
fstab->recs[cnt].fs_options = NULL;
}
- if (!(p = strtok_r(NULL, delim, &save_ptr))) {
+ // For /proc/mounts, ignore everything after mnt_freq and mnt_passno
+ if (proc_mounts) {
+ p += strlen(p);
+ } else if (!(p = strtok_r(NULL, delim, &save_ptr))) {
LERROR << "Error parsing fs_mgr_options";
goto err;
}
@@ -739,7 +743,7 @@
return nullptr;
}
- fstab = fs_mgr_read_fstab_file(fstab_file);
+ fstab = fs_mgr_read_fstab_file(fstab_file, !strcmp("/proc/mounts", fstab_path));
if (!fstab) {
LERROR << __FUNCTION__ << "(): failed to load fstab from : '" << fstab_path << "'";
}
@@ -767,7 +771,7 @@
return nullptr;
}
- struct fstab *fstab = fs_mgr_read_fstab_file(fstab_file.get());
+ struct fstab* fstab = fs_mgr_read_fstab_file(fstab_file.get(), false);
if (!fstab) {
LERROR << __FUNCTION__ << "(): failed to load fstab from kernel:"
<< std::endl << fstab_buf;
diff --git a/fs_mgr/fs_mgr_priv_dm_ioctl.h b/fs_mgr/fs_mgr_priv_dm_ioctl.h
deleted file mode 100644
index 792475d..0000000
--- a/fs_mgr/fs_mgr_priv_dm_ioctl.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef __CORE_FS_MGR_PRIV_DM_IOCTL_H
-#define __CORE_FS_MGR_PRIV_DM_IOCTL_H
-
-#include <linux/dm-ioctl.h>
-#include <string>
-
-void fs_mgr_dm_ioctl_init(struct dm_ioctl* io, size_t size, const std::string& name);
-
-bool fs_mgr_dm_create_device(struct dm_ioctl* io, const std::string& name, int fd);
-
-bool fs_mgr_dm_destroy_device(struct dm_ioctl* io, const std::string& name, int fd);
-
-bool fs_mgr_dm_get_device_name(struct dm_ioctl* io, const std::string& name, int fd,
- std::string* out_dev_name);
-
-bool fs_mgr_dm_resume_table(struct dm_ioctl* io, const std::string& name, int fd);
-
-#endif /* __CORE_FS_MGR_PRIV_DM_IOCTL_H */
diff --git a/fs_mgr/fs_mgr_verity.cpp b/fs_mgr/fs_mgr_verity.cpp
index fe41f8a..5fb4ebb 100644
--- a/fs_mgr/fs_mgr_verity.cpp
+++ b/fs_mgr/fs_mgr_verity.cpp
@@ -35,6 +35,7 @@
#include <android-base/unique_fd.h>
#include <crypto_utils/android_pubkey.h>
#include <cutils/properties.h>
+#include <libdm/dm.h>
#include <logwrap/logwrap.h>
#include <openssl/obj_mac.h>
#include <openssl/rsa.h>
@@ -44,7 +45,6 @@
#include "fs_mgr.h"
#include "fs_mgr_priv.h"
-#include "fs_mgr_priv_dm_ioctl.h"
#define VERITY_TABLE_RSA_KEY "/verity_key"
#define VERITY_TABLE_HASH_IDX 8
@@ -250,48 +250,27 @@
return true;
}
-static int load_verity_table(struct dm_ioctl *io, const std::string &name,
- uint64_t device_size, int fd,
- const struct verity_table_params *params, format_verity_table_func format)
-{
- char *verity_params;
- char *buffer = (char*) io;
- size_t bufsize;
+static int load_verity_table(android::dm::DeviceMapper& dm, const std::string& name,
+ uint64_t device_size, const struct verity_table_params* params,
+ format_verity_table_func format) {
+ android::dm::DmTable table;
+ table.set_readonly(true);
- fs_mgr_dm_ioctl_init(io, DM_BUF_SIZE, name);
-
- struct dm_target_spec *tgt = (struct dm_target_spec *) &buffer[sizeof(struct dm_ioctl)];
-
- // set tgt arguments
- io->target_count = 1;
- io->flags = DM_READONLY_FLAG;
- tgt->status = 0;
- tgt->sector_start = 0;
- tgt->length = device_size / 512;
- strcpy(tgt->target_type, "verity");
-
- // build the verity params
- verity_params = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec);
- bufsize = DM_BUF_SIZE - (verity_params - buffer);
-
- if (!format(verity_params, bufsize, params)) {
+ char buffer[DM_BUF_SIZE];
+ if (!format(buffer, sizeof(buffer), params)) {
LERROR << "Failed to format verity parameters";
return -1;
}
- LINFO << "loading verity table: '" << verity_params << "'";
-
- // set next target boundary
- verity_params += strlen(verity_params) + 1;
- verity_params = (char*)(((uintptr_t)verity_params + 7) & ~7);
- tgt->next = verity_params - buffer;
-
- // send the ioctl to load the verity table
- if (ioctl(fd, DM_TABLE_LOAD, io)) {
- PERROR << "Error loading verity table";
+ android::dm::DmTargetVerityString target(0, device_size / 512, buffer);
+ if (!table.AddTarget(std::make_unique<decltype(target)>(target))) {
+ LERROR << "Failed to add verity target";
return -1;
}
-
+ if (!dm.CreateDevice(name, table)) {
+ LERROR << "Failed to create verity device \"" << name << "\"";
+ return -1;
+ }
return 0;
}
@@ -761,11 +740,11 @@
struct fec_verity_metadata verity;
struct verity_table_params params = { .table = NULL };
- alignas(dm_ioctl) char buffer[DM_BUF_SIZE];
- struct dm_ioctl *io = (struct dm_ioctl *) buffer;
const std::string mount_point(basename(fstab->mount_point));
bool verified_at_boot = false;
+ android::dm::DeviceMapper& dm = android::dm::DeviceMapper::Instance();
+
if (fec_open(&f, fstab->blk_device, O_RDONLY, FEC_VERITY_DISABLE,
FEC_DEFAULT_ROOTS) < 0) {
PERROR << "Failed to open '" << fstab->blk_device << "'";
@@ -798,24 +777,6 @@
params.ecc_dev = fstab->blk_device;
- // get the device mapper fd
- if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) {
- PERROR << "Error opening device mapper";
- goto out;
- }
-
- // create the device
- if (!fs_mgr_dm_create_device(io, mount_point, fd)) {
- LERROR << "Couldn't create verity device!";
- goto out;
- }
-
- // get the name of the device file
- if (!fs_mgr_dm_get_device_name(io, mount_point, fd, &verity_blk_name)) {
- LERROR << "Couldn't get verity device number!";
- goto out;
- }
-
if (load_verity_state(fstab, ¶ms.mode) < 0) {
/* if accessing or updating the state failed, switch to the default
* safe mode. This makes sure the device won't end up in an endless
@@ -861,8 +822,7 @@
fstab->fs_mgr_flags & MF_SLOTSELECT);
// load the verity mapping table
- if (load_verity_table(io, mount_point, verity.data_size, fd, ¶ms,
- format_verity_table) == 0) {
+ if (load_verity_table(dm, mount_point, verity.data_size, ¶ms, format_verity_table) == 0) {
goto loaded;
}
@@ -871,15 +831,14 @@
LINFO << "Disabling error correction for " << mount_point.c_str();
params.ecc.valid = false;
- if (load_verity_table(io, mount_point, verity.data_size, fd, ¶ms,
- format_verity_table) == 0) {
+ if (load_verity_table(dm, mount_point, verity.data_size, ¶ms, format_verity_table) == 0) {
goto loaded;
}
}
// try the legacy format for backwards compatibility
- if (load_verity_table(io, mount_point, verity.data_size, fd, ¶ms,
- format_legacy_verity_table) == 0) {
+ if (load_verity_table(dm, mount_point, verity.data_size, ¶ms, format_legacy_verity_table) ==
+ 0) {
goto loaded;
}
@@ -888,8 +847,8 @@
LINFO << "Falling back to EIO mode for " << mount_point.c_str();
params.mode = VERITY_MODE_EIO;
- if (load_verity_table(io, mount_point, verity.data_size, fd, ¶ms,
- format_legacy_verity_table) == 0) {
+ if (load_verity_table(dm, mount_point, verity.data_size, ¶ms,
+ format_legacy_verity_table) == 0) {
goto loaded;
}
}
@@ -898,9 +857,8 @@
goto out;
loaded:
-
- // activate the device
- if (!fs_mgr_dm_resume_table(io, mount_point, fd)) {
+ if (!dm.GetDmDevicePathByName(mount_point, &verity_blk_name)) {
+ LERROR << "Couldn't get verity device number!";
goto out;
}
@@ -923,7 +881,7 @@
if (!verified_at_boot) {
free(fstab->blk_device);
fstab->blk_device = strdup(verity_blk_name.c_str());
- } else if (!fs_mgr_dm_destroy_device(io, mount_point, fd)) {
+ } else if (!dm.DeleteDevice(mount_point)) {
LERROR << "Failed to remove verity device " << mount_point.c_str();
goto out;
}
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index c1b2ed9..1049fb6 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -22,6 +22,8 @@
#include <stdbool.h>
#include <linux/dm-ioctl.h>
+#include <functional>
+
#include <fstab/fstab.h>
// Magic number at start of verity metadata
@@ -48,8 +50,8 @@
};
// Callback function for verity status
-typedef void (*fs_mgr_verity_state_callback)(struct fstab_rec *fstab,
- const char *mount_point, int mode, int status);
+typedef void fs_mgr_verity_state_callback(struct fstab_rec* fstab, const char* mount_point,
+ int mode, int status);
#define FS_MGR_MNTALL_DEV_IS_METADATA_ENCRYPTED 7
#define FS_MGR_MNTALL_DEV_NEEDS_METADATA_ENCRYPTION 6
@@ -73,7 +75,7 @@
struct fstab_rec const* fs_mgr_get_crypt_entry(struct fstab const* fstab);
void fs_mgr_get_crypt_info(struct fstab* fstab, char* key_loc, char* real_blk_device, size_t size);
bool fs_mgr_load_verity_state(int* mode);
-bool fs_mgr_update_verity_state(fs_mgr_verity_state_callback callback);
+bool fs_mgr_update_verity_state(std::function<fs_mgr_verity_state_callback> callback);
int fs_mgr_swapon_all(struct fstab *fstab);
bool fs_mgr_update_logical_partition(struct fstab_rec* rec);
diff --git a/fs_mgr/include/fs_mgr_dm_linear.h b/fs_mgr/include/fs_mgr_dm_linear.h
index 9772c4b..3b0c791 100644
--- a/fs_mgr/include/fs_mgr_dm_linear.h
+++ b/fs_mgr/include/fs_mgr_dm_linear.h
@@ -26,53 +26,20 @@
#define __CORE_FS_MGR_DM_LINEAR_H
#include <stdint.h>
+
#include <memory>
#include <string>
#include <vector>
+#include <libdm/dm.h>
+#include <liblp/metadata_format.h>
+
namespace android {
namespace fs_mgr {
-static const uint32_t kPartitionReadonly = 0x1;
-
-class LogicalPartitionExtent {
- public:
- LogicalPartitionExtent() : logical_sector_(0), first_sector_(0), num_sectors_(0) {}
- LogicalPartitionExtent(uint64_t logical_sector, uint64_t first_sector, uint64_t num_sectors,
- const std::string& block_device)
- : logical_sector_(logical_sector),
- first_sector_(first_sector),
- num_sectors_(num_sectors),
- block_device_(block_device) {}
-
- // Return a string containing the dm_target_spec buffer needed to use this
- // extent in a device-mapper table.
- std::string Serialize() const;
-
- const std::string& block_device() const { return block_device_; }
-
- private:
- // Logical sector this extent represents in the presented block device.
- // This is equal to the previous extent's logical sector plus the number
- // of sectors in that extent. The first extent always starts at 0.
- uint64_t logical_sector_;
- // First 512-byte sector of this extent, on the source block device.
- uint64_t first_sector_;
- // Number of 512-byte sectors.
- uint64_t num_sectors_;
- // Target block device.
- std::string block_device_;
-};
-
struct LogicalPartition {
- LogicalPartition() : attributes(0), num_sectors(0) {}
-
std::string name;
- uint32_t attributes;
- // Number of 512-byte sectors total.
- uint64_t num_sectors;
- // List of extents.
- std::vector<LogicalPartitionExtent> extents;
+ std::vector<android::dm::DmTargetLinear> extents;
};
struct LogicalPartitionTable {
diff --git a/fs_mgr/libdm/Android.bp b/fs_mgr/libdm/Android.bp
index f1b18dd..22af123 100644
--- a/fs_mgr/libdm/Android.bp
+++ b/fs_mgr/libdm/Android.bp
@@ -28,7 +28,8 @@
srcs: [
"dm_table.cpp",
"dm_target.cpp",
- "dm.cpp"
+ "dm.cpp",
+ "loop_control.cpp",
],
header_libs: [
@@ -47,5 +48,7 @@
],
srcs: [
"dm_test.cpp",
+ "loop_control_test.cpp",
+ "test_util.cpp",
]
}
diff --git a/fs_mgr/libdm/dm.cpp b/fs_mgr/libdm/dm.cpp
index b96f4c1..ad3b6f4 100644
--- a/fs_mgr/libdm/dm.cpp
+++ b/fs_mgr/libdm/dm.cpp
@@ -272,6 +272,46 @@
return true;
}
+bool DeviceMapper::GetTableStatus(const std::string& name, std::vector<TargetInfo>* table) {
+ char buffer[4096];
+ struct dm_ioctl* io = reinterpret_cast<struct dm_ioctl*>(buffer);
+
+ InitIo(io, name);
+ io->data_size = sizeof(buffer);
+ io->data_start = sizeof(*io);
+ if (ioctl(fd_, DM_TABLE_STATUS, io) < 0) {
+ PLOG(ERROR) << "DM_TABLE_STATUS failed for " << name;
+ return false;
+ }
+ if (io->flags & DM_BUFFER_FULL_FLAG) {
+ PLOG(ERROR) << "DM_TABLE_STATUS result for " << name << " was too large";
+ return false;
+ }
+
+ uint32_t cursor = io->data_start;
+ uint32_t data_end = std::min(io->data_size, uint32_t(sizeof(buffer)));
+ for (uint32_t i = 0; i < io->target_count; i++) {
+ if (cursor + sizeof(struct dm_target_spec) > data_end) {
+ break;
+ }
+ // After each dm_target_spec is a status string. spec->next is an
+ // offset from |io->data_start|, and we clamp it to the size of our
+ // buffer.
+ struct dm_target_spec* spec = reinterpret_cast<struct dm_target_spec*>(buffer + cursor);
+ uint32_t data_offset = cursor + sizeof(dm_target_spec);
+ uint32_t next_cursor = std::min(io->data_start + spec->next, data_end);
+
+ std::string data;
+ if (next_cursor > data_offset) {
+ // Note: we use c_str() to eliminate any extra trailing 0s.
+ data = std::string(buffer + data_offset, next_cursor - data_offset).c_str();
+ }
+ table->emplace_back(*spec, data);
+ cursor = next_cursor;
+ }
+ return true;
+}
+
// private methods of DeviceMapper
void DeviceMapper::InitIo(struct dm_ioctl* io, const std::string& name) const {
CHECK(io != nullptr) << "nullptr passed to dm_ioctl initialization";
diff --git a/fs_mgr/libdm/dm_table.cpp b/fs_mgr/libdm/dm_table.cpp
index cb6f210..15c7ce1 100644
--- a/fs_mgr/libdm/dm_table.cpp
+++ b/fs_mgr/libdm/dm_table.cpp
@@ -23,6 +23,9 @@
namespace dm {
bool DmTable::AddTarget(std::unique_ptr<DmTarget>&& target) {
+ if (!target->Valid()) {
+ return false;
+ }
targets_.push_back(std::move(target));
return true;
}
diff --git a/fs_mgr/libdm/dm_target.cpp b/fs_mgr/libdm/dm_target.cpp
index 5934416..20b26df 100644
--- a/fs_mgr/libdm/dm_target.cpp
+++ b/fs_mgr/libdm/dm_target.cpp
@@ -18,6 +18,7 @@
#include <android-base/logging.h>
#include <android-base/macros.h>
+#include <android-base/strings.h>
#include <libdm/dm.h>
@@ -55,5 +56,60 @@
return block_device_ + " " + std::to_string(physical_sector_);
}
+DmTargetVerity::DmTargetVerity(uint64_t start, uint64_t length, uint32_t version,
+ const std::string& block_device, const std::string& hash_device,
+ uint32_t data_block_size, uint32_t hash_block_size,
+ uint32_t num_data_blocks, uint32_t hash_start_block,
+ const std::string& hash_algorithm, const std::string& root_digest,
+ const std::string& salt)
+ : DmTarget(start, length), valid_(true) {
+ base_args_ = {
+ std::to_string(version),
+ block_device,
+ hash_device,
+ std::to_string(data_block_size),
+ std::to_string(hash_block_size),
+ std::to_string(num_data_blocks),
+ std::to_string(hash_start_block),
+ hash_algorithm,
+ root_digest,
+ salt,
+ };
+}
+
+void DmTargetVerity::UseFec(const std::string& device, uint32_t num_roots, uint32_t num_blocks,
+ uint32_t start) {
+ optional_args_.emplace_back("use_fec_from_device");
+ optional_args_.emplace_back(device);
+ optional_args_.emplace_back("fec_roots");
+ optional_args_.emplace_back(std::to_string(num_roots));
+ optional_args_.emplace_back("fec_blocks");
+ optional_args_.emplace_back(std::to_string(num_blocks));
+ optional_args_.emplace_back("fec_start");
+ optional_args_.emplace_back(std::to_string(start));
+}
+
+void DmTargetVerity::SetVerityMode(const std::string& mode) {
+ if (mode != "restart_on_corruption" && mode != "ignore_corruption") {
+ LOG(ERROR) << "Unknown verity mode: " << mode;
+ valid_ = false;
+ return;
+ }
+ optional_args_.emplace_back(mode);
+}
+
+void DmTargetVerity::IgnoreZeroBlocks() {
+ optional_args_.emplace_back("ignore_zero_blocks");
+}
+
+std::string DmTargetVerity::GetParameterString() const {
+ std::string base = android::base::Join(base_args_, " ");
+ if (optional_args_.empty()) {
+ return base;
+ }
+ std::string optional = android::base::Join(optional_args_, " ");
+ return base + " " + std::to_string(optional_args_.size()) + " " + optional;
+}
+
} // namespace dm
} // namespace android
diff --git a/fs_mgr/libdm/dm_test.cpp b/fs_mgr/libdm/dm_test.cpp
index adbe820..cc61917 100644
--- a/fs_mgr/libdm/dm_test.cpp
+++ b/fs_mgr/libdm/dm_test.cpp
@@ -14,13 +14,29 @@
* limitations under the License.
*/
-#include <map>
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <time.h>
+#include <unistd.h>
+#include <chrono>
+#include <ctime>
+#include <map>
+#include <thread>
+
+#include <android-base/file.h>
+#include <android-base/unique_fd.h>
#include <gtest/gtest.h>
#include <libdm/dm.h>
+#include <libdm/loop_control.h>
+#include "test_util.h"
using namespace std;
using namespace android::dm;
+using unique_fd = android::base::unique_fd;
TEST(libdm, HasMinimumTargets) {
DeviceMapper& dm = DeviceMapper::Instance();
@@ -35,3 +51,152 @@
auto iter = by_name.find("linear");
EXPECT_NE(iter, by_name.end());
}
+
+// Helper to ensure that device mapper devices are released.
+class TempDevice {
+ public:
+ TempDevice(const std::string& name, const DmTable& table)
+ : dm_(DeviceMapper::Instance()), name_(name), valid_(false) {
+ valid_ = dm_.CreateDevice(name, table);
+ }
+ TempDevice(TempDevice&& other) : dm_(other.dm_), name_(other.name_), valid_(other.valid_) {
+ other.valid_ = false;
+ }
+ ~TempDevice() {
+ if (valid_) {
+ dm_.DeleteDevice(name_);
+ }
+ }
+ bool Destroy() {
+ if (!valid_) {
+ return false;
+ }
+ valid_ = false;
+ return dm_.DeleteDevice(name_);
+ }
+ bool WaitForUdev() const {
+ auto start_time = std::chrono::steady_clock::now();
+ while (true) {
+ if (!access(path().c_str(), F_OK)) {
+ return true;
+ }
+ if (errno != ENOENT) {
+ return false;
+ }
+ std::this_thread::sleep_for(50ms);
+ std::chrono::duration elapsed = std::chrono::steady_clock::now() - start_time;
+ if (elapsed >= 5s) {
+ return false;
+ }
+ }
+ }
+ std::string path() const {
+ std::string device_path;
+ if (!dm_.GetDmDevicePathByName(name_, &device_path)) {
+ return "";
+ }
+ return device_path;
+ }
+ const std::string& name() const { return name_; }
+ bool valid() const { return valid_; }
+
+ TempDevice(const TempDevice&) = delete;
+ TempDevice& operator=(const TempDevice&) = delete;
+
+ TempDevice& operator=(TempDevice&& other) {
+ name_ = other.name_;
+ valid_ = other.valid_;
+ other.valid_ = false;
+ return *this;
+ }
+
+ private:
+ DeviceMapper& dm_;
+ std::string name_;
+ bool valid_;
+};
+
+TEST(libdm, DmLinear) {
+ unique_fd tmp1(CreateTempFile("file_1", 4096));
+ ASSERT_GE(tmp1, 0);
+ unique_fd tmp2(CreateTempFile("file_2", 4096));
+ ASSERT_GE(tmp2, 0);
+
+ // Create two different files. These will back two separate loop devices.
+ const char message1[] = "Hello! This is sector 1.";
+ const char message2[] = "Goodbye. This is sector 2.";
+ ASSERT_TRUE(android::base::WriteFully(tmp1, message1, sizeof(message1)));
+ ASSERT_TRUE(android::base::WriteFully(tmp2, message2, sizeof(message2)));
+
+ LoopDevice loop_a(tmp1);
+ ASSERT_TRUE(loop_a.valid());
+ LoopDevice loop_b(tmp2);
+ ASSERT_TRUE(loop_b.valid());
+
+ // Define a 2-sector device, with each sector mapping to the first sector
+ // of one of our loop devices.
+ DmTable table;
+ ASSERT_TRUE(table.AddTarget(make_unique<DmTargetLinear>(0, 1, loop_a.device(), 0)));
+ ASSERT_TRUE(table.AddTarget(make_unique<DmTargetLinear>(1, 1, loop_b.device(), 0)));
+ ASSERT_TRUE(table.valid());
+
+ TempDevice dev("libdm-test-dm-linear", table);
+ ASSERT_TRUE(dev.valid());
+ ASSERT_FALSE(dev.path().empty());
+ ASSERT_TRUE(dev.WaitForUdev());
+
+ // Note: a scope is needed to ensure that there are no open descriptors
+ // when we go to close the device.
+ {
+ unique_fd dev_fd(open(dev.path().c_str(), O_RDWR));
+ ASSERT_GE(dev_fd, 0);
+
+ // Test that each sector of our device is correctly mapped to each loop
+ // device.
+ char sector[512];
+ ASSERT_TRUE(android::base::ReadFully(dev_fd, sector, sizeof(sector)));
+ ASSERT_EQ(strncmp(sector, message1, sizeof(message1)), 0);
+ ASSERT_TRUE(android::base::ReadFully(dev_fd, sector, sizeof(sector)));
+ ASSERT_EQ(strncmp(sector, message2, sizeof(message2)), 0);
+ }
+
+ // Test GetTableStatus.
+ DeviceMapper& dm = DeviceMapper::Instance();
+ vector<DeviceMapper::TargetInfo> targets;
+ ASSERT_TRUE(dm.GetTableStatus(dev.name(), &targets));
+ ASSERT_EQ(targets.size(), 2);
+ EXPECT_EQ(strcmp(targets[0].spec.target_type, "linear"), 0);
+ EXPECT_TRUE(targets[0].data.empty());
+ EXPECT_EQ(targets[0].spec.sector_start, 0);
+ EXPECT_EQ(targets[0].spec.length, 1);
+ EXPECT_EQ(strcmp(targets[1].spec.target_type, "linear"), 0);
+ EXPECT_TRUE(targets[1].data.empty());
+ EXPECT_EQ(targets[1].spec.sector_start, 1);
+ EXPECT_EQ(targets[1].spec.length, 1);
+
+ // Normally the TestDevice destructor would delete this, but at least one
+ // test should ensure that device deletion works.
+ ASSERT_TRUE(dev.Destroy());
+}
+
+TEST(libdm, DmVerityArgsAvb2) {
+ std::string device = "/dev/block/platform/soc/1da4000.ufshc/by-name/vendor_a";
+ std::string algorithm = "sha1";
+ std::string digest = "4be7e823b8c40f7bd5c8ccd5123f0722c5baca21";
+ std::string salt = "cc99f81ecb9484220a003b0719ee59dcf9be7e5d";
+
+ DmTargetVerity target(0, 10000, 1, device, device, 4096, 4096, 125961, 125961, algorithm,
+ digest, salt);
+ target.UseFec(device, 2, 126955, 126955);
+ target.SetVerityMode("restart_on_corruption");
+ target.IgnoreZeroBlocks();
+
+ // Verity table from a walleye build.
+ std::string expected =
+ "1 /dev/block/platform/soc/1da4000.ufshc/by-name/vendor_a "
+ "/dev/block/platform/soc/1da4000.ufshc/by-name/vendor_a 4096 4096 125961 125961 sha1 "
+ "4be7e823b8c40f7bd5c8ccd5123f0722c5baca21 cc99f81ecb9484220a003b0719ee59dcf9be7e5d 10 "
+ "use_fec_from_device /dev/block/platform/soc/1da4000.ufshc/by-name/vendor_a fec_roots "
+ "2 fec_blocks 126955 fec_start 126955 restart_on_corruption ignore_zero_blocks";
+ EXPECT_EQ(target.GetParameterString(), expected);
+}
diff --git a/fs_mgr/libdm/include/libdm/dm.h b/fs_mgr/libdm/include/libdm/dm.h
index 60bceed..e2bc729 100644
--- a/fs_mgr/libdm/include/libdm/dm.h
+++ b/fs_mgr/libdm/include/libdm/dm.h
@@ -26,6 +26,7 @@
#include <memory>
#include <string>
+#include <utility>
#include <vector>
#include <android-base/logging.h>
@@ -117,6 +118,18 @@
}
}
+ // Query the status of a table, given a device name. The output vector will
+ // contain one TargetInfo for each target in the table. If the device does
+ // not exist, or there were too many targets, the call will fail and return
+ // false.
+ struct TargetInfo {
+ struct dm_target_spec spec;
+ std::string data;
+ TargetInfo(const struct dm_target_spec& spec, const std::string& data)
+ : spec(spec), data(data) {}
+ };
+ bool GetTableStatus(const std::string& name, std::vector<TargetInfo>* table);
+
private:
// Maximum possible device mapper targets registered in the kernel.
// This is only used to read the list of targets from kernel so we allocate
diff --git a/fs_mgr/libdm/include/libdm/dm_target.h b/fs_mgr/libdm/include/libdm/dm_target.h
index 31b6a70..d5974f4 100644
--- a/fs_mgr/libdm/include/libdm/dm_target.h
+++ b/fs_mgr/libdm/include/libdm/dm_target.h
@@ -21,6 +21,7 @@
#include <stdint.h>
#include <string>
+#include <vector>
#include <android-base/logging.h>
@@ -69,6 +70,8 @@
// must implement this, for it to be used on a device.
std::string Serialize() const;
+ virtual bool Valid() const { return true; }
+
protected:
// Get the parameter string that is passed to the end of the dm_target_spec
// for this target type.
@@ -96,12 +99,51 @@
std::string name() const override { return "linear"; }
std::string GetParameterString() const override;
+ const std::string& block_device() const { return block_device_; }
private:
std::string block_device_;
uint64_t physical_sector_;
};
+class DmTargetVerity final : public DmTarget {
+ public:
+ DmTargetVerity(uint64_t start, uint64_t length, uint32_t version,
+ const std::string& block_device, const std::string& hash_device,
+ uint32_t data_block_size, uint32_t hash_block_size, uint32_t num_data_blocks,
+ uint32_t hash_start_block, const std::string& hash_algorithm,
+ const std::string& root_digest, const std::string& salt);
+
+ void UseFec(const std::string& device, uint32_t num_roots, uint32_t num_blocks, uint32_t start);
+ void SetVerityMode(const std::string& mode);
+ void IgnoreZeroBlocks();
+
+ std::string name() const override { return "verity"; }
+ std::string GetParameterString() const override;
+ bool Valid() const override { return valid_; }
+
+ private:
+ std::vector<std::string> base_args_;
+ std::vector<std::string> optional_args_;
+ bool valid_;
+};
+
+// This is the same as DmTargetVerity, but the table may be specified as a raw
+// string. This code exists only for fs_mgr_verity and should be avoided. Use
+// DmTargetVerity for new code instead.
+class DmTargetVerityString final : public DmTarget {
+ public:
+ DmTargetVerityString(uint64_t start, uint64_t length, const std::string& target_string)
+ : DmTarget(start, length), target_string_(target_string) {}
+
+ std::string name() const override { return "verity"; }
+ std::string GetParameterString() const override { return target_string_; }
+ bool Valid() const override { return true; }
+
+ private:
+ std::string target_string_;
+};
+
} // namespace dm
} // namespace android
diff --git a/fs_mgr/libdm/include/libdm/loop_control.h b/fs_mgr/libdm/include/libdm/loop_control.h
new file mode 100644
index 0000000..e6e83f4
--- /dev/null
+++ b/fs_mgr/libdm/include/libdm/loop_control.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2018 Google, Inc
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _LIBDM_LOOP_CONTROL_H_
+#define _LIBDM_LOOP_CONTROL_H_
+
+#include <string>
+
+#include <android-base/unique_fd.h>
+
+namespace android {
+namespace dm {
+
+class LoopControl final {
+ public:
+ LoopControl();
+
+ // Attaches the file specified by 'file_fd' to the loop device specified
+ // by 'loopdev'
+ bool Attach(int file_fd, std::string* loopdev) const;
+
+ // Detach the loop device given by 'loopdev' from the attached backing file.
+ bool Detach(const std::string& loopdev) const;
+
+ LoopControl(const LoopControl&) = delete;
+ LoopControl& operator=(const LoopControl&) = delete;
+ LoopControl& operator=(LoopControl&&) = default;
+ LoopControl(LoopControl&&) = default;
+
+ private:
+ bool FindFreeLoopDevice(std::string* loopdev) const;
+
+ static constexpr const char* kLoopControlDevice = "/dev/loop-control";
+
+ android::base::unique_fd control_fd_;
+};
+
+// Create a temporary loop device around a file descriptor or path.
+class LoopDevice {
+ public:
+ // Create a loop device for the given file descriptor. It is closed when
+ // LoopDevice is destroyed only if auto_close is true.
+ LoopDevice(int fd, bool auto_close = false);
+ // Create a loop device for the given file path. It will be opened for
+ // reading and writing and closed when the loop device is detached.
+ explicit LoopDevice(const std::string& path);
+ ~LoopDevice();
+
+ bool valid() const { return fd_ != -1 && !device_.empty(); }
+ const std::string& device() const { return device_; }
+
+ LoopDevice(const LoopDevice&) = delete;
+ LoopDevice& operator=(const LoopDevice&) = delete;
+ LoopDevice& operator=(LoopDevice&&) = default;
+ LoopDevice(LoopDevice&&) = default;
+
+ private:
+ void Init();
+
+ android::base::unique_fd fd_;
+ bool owns_fd_;
+ std::string device_;
+ LoopControl control_;
+};
+
+} // namespace dm
+} // namespace android
+
+#endif /* _LIBDM_LOOP_CONTROL_H_ */
diff --git a/fs_mgr/libdm/loop_control.cpp b/fs_mgr/libdm/loop_control.cpp
new file mode 100644
index 0000000..0beb1a6
--- /dev/null
+++ b/fs_mgr/libdm/loop_control.cpp
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "libdm/loop_control.h"
+
+#include <fcntl.h>
+#include <linux/loop.h>
+#include <stdint.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+#include <android-base/unique_fd.h>
+
+namespace android {
+namespace dm {
+
+LoopControl::LoopControl() : control_fd_(-1) {
+ control_fd_.reset(TEMP_FAILURE_RETRY(open(kLoopControlDevice, O_RDWR | O_CLOEXEC)));
+ if (control_fd_ < 0) {
+ PLOG(ERROR) << "Failed to open loop-control";
+ }
+}
+
+bool LoopControl::Attach(int file_fd, std::string* loopdev) const {
+ if (!FindFreeLoopDevice(loopdev)) {
+ LOG(ERROR) << "Failed to attach, no free loop devices";
+ return false;
+ }
+
+ android::base::unique_fd loop_fd(TEMP_FAILURE_RETRY(open(loopdev->c_str(), O_RDWR | O_CLOEXEC)));
+ if (loop_fd < 0) {
+ PLOG(ERROR) << "Failed to open: " << *loopdev;
+ return false;
+ }
+
+ int rc = ioctl(loop_fd, LOOP_SET_FD, file_fd);
+ if (rc < 0) {
+ PLOG(ERROR) << "Failed LOOP_SET_FD";
+ return false;
+ }
+ return true;
+}
+
+bool LoopControl::Detach(const std::string& loopdev) const {
+ if (loopdev.empty()) {
+ LOG(ERROR) << "Must provide a loop device";
+ return false;
+ }
+
+ android::base::unique_fd loop_fd(TEMP_FAILURE_RETRY(open(loopdev.c_str(), O_RDWR | O_CLOEXEC)));
+ if (loop_fd < 0) {
+ PLOG(ERROR) << "Failed to open: " << loopdev;
+ return false;
+ }
+
+ int rc = ioctl(loop_fd, LOOP_CLR_FD, 0);
+ if (rc) {
+ PLOG(ERROR) << "Failed LOOP_CLR_FD for '" << loopdev << "'";
+ return false;
+ }
+ return true;
+}
+
+bool LoopControl::FindFreeLoopDevice(std::string* loopdev) const {
+ int rc = ioctl(control_fd_, LOOP_CTL_GET_FREE);
+ if (rc < 0) {
+ PLOG(ERROR) << "Failed to get free loop device";
+ return false;
+ }
+
+ // Ueventd on android creates all loop devices as /dev/block/loopX
+ // The total number of available devices is determined by 'loop.max_part'
+ // kernel command line argument.
+ *loopdev = ::android::base::StringPrintf("/dev/block/loop%d", rc);
+ return true;
+}
+
+LoopDevice::LoopDevice(int fd, bool auto_close) : fd_(fd), owns_fd_(auto_close) {
+ Init();
+}
+
+LoopDevice::LoopDevice(const std::string& path) : fd_(-1), owns_fd_(true) {
+ fd_.reset(open(path.c_str(), O_RDWR | O_CLOEXEC));
+ if (fd_ < -1) {
+ PLOG(ERROR) << "open failed for " << path;
+ return;
+ }
+ Init();
+}
+
+LoopDevice::~LoopDevice() {
+ if (valid()) {
+ control_.Detach(device_);
+ }
+ if (!owns_fd_) {
+ (void)fd_.release();
+ }
+}
+
+void LoopDevice::Init() {
+ control_.Attach(fd_, &device_);
+}
+
+} // namespace dm
+} // namespace android
diff --git a/fs_mgr/libdm/loop_control_test.cpp b/fs_mgr/libdm/loop_control_test.cpp
new file mode 100644
index 0000000..08bdc00
--- /dev/null
+++ b/fs_mgr/libdm/loop_control_test.cpp
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "libdm/loop_control.h"
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <android-base/file.h>
+#include <android-base/unique_fd.h>
+#include <gtest/gtest.h>
+#include "test_util.h"
+
+using namespace std;
+using namespace android::dm;
+using unique_fd = android::base::unique_fd;
+
+static unique_fd TempFile() {
+ // A loop device needs to be at least one sector to actually work, so fill
+ // up the file with a message.
+ unique_fd fd(CreateTempFile("temp", 0));
+ if (fd < 0) {
+ return {};
+ }
+ char buffer[] = "Hello";
+ for (size_t i = 0; i < 1000; i++) {
+ if (!android::base::WriteFully(fd, buffer, sizeof(buffer))) {
+ perror("write");
+ return {};
+ }
+ }
+ return fd;
+}
+
+TEST(libdm, LoopControl) {
+ unique_fd fd = TempFile();
+ ASSERT_GE(fd, 0);
+
+ LoopDevice loop(fd);
+ ASSERT_TRUE(loop.valid());
+
+ char buffer[6];
+ unique_fd loop_fd(open(loop.device().c_str(), O_RDWR));
+ ASSERT_GE(loop_fd, 0);
+ ASSERT_TRUE(android::base::ReadFully(loop_fd, buffer, sizeof(buffer)));
+ ASSERT_EQ(memcmp(buffer, "Hello", 6), 0);
+}
diff --git a/fs_mgr/libdm/test_util.cpp b/fs_mgr/libdm/test_util.cpp
new file mode 100644
index 0000000..307251c
--- /dev/null
+++ b/fs_mgr/libdm/test_util.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <fcntl.h>
+#include <linux/memfd.h>
+#include <stdio.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "test_util.h"
+
+namespace android {
+namespace dm {
+
+using unique_fd = android::base::unique_fd;
+
+// Create a temporary in-memory file. If size is non-zero, the file will be
+// created with a fixed size.
+unique_fd CreateTempFile(const std::string& name, size_t size) {
+ unique_fd fd(syscall(__NR_memfd_create, name.c_str(), MFD_ALLOW_SEALING));
+ if (fd < 0) {
+ return {};
+ }
+ if (size) {
+ if (ftruncate(fd, size) < 0) {
+ perror("ftruncate");
+ return {};
+ }
+ if (fcntl(fd, F_ADD_SEALS, F_SEAL_GROW | F_SEAL_SHRINK) < 0) {
+ perror("fcntl");
+ return {};
+ }
+ }
+ return fd;
+}
+
+} // namespace dm
+} // namespace android
diff --git a/fs_mgr/libdm/test_util.h b/fs_mgr/libdm/test_util.h
new file mode 100644
index 0000000..96b051c
--- /dev/null
+++ b/fs_mgr/libdm/test_util.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _LIBDM_TEST_UTILS_H_
+#define _LIBDM_TEST_UTILS_H_
+
+#include <android-base/unique_fd.h>
+#include <stddef.h>
+
+#include <string>
+
+namespace android {
+namespace dm {
+
+// Create a temporary in-memory file. If size is non-zero, the file will be
+// created with a fixed size.
+android::base::unique_fd CreateTempFile(const std::string& name, size_t size);
+
+} // namespace dm
+} // namespace android
+
+#endif // _LIBDM_TEST_UTILS_H_
diff --git a/fs_mgr/tests/fs_mgr_test.cpp b/fs_mgr/tests/fs_mgr_test.cpp
index 2e76752..8b1c55a 100644
--- a/fs_mgr/tests/fs_mgr_test.cpp
+++ b/fs_mgr/tests/fs_mgr_test.cpp
@@ -14,13 +14,18 @@
* limitations under the License.
*/
+#include <linux/fs.h>
+#include <mntent.h>
+
#include <algorithm>
#include <iterator>
+#include <set>
#include <string>
#include <utility>
#include <vector>
#include <android-base/strings.h>
+#include <fstab/fstab.h>
#include <gtest/gtest.h>
#include "../fs_mgr_priv_boot_config.h"
@@ -129,3 +134,70 @@
EXPECT_FALSE(fs_mgr_get_boot_config_from_kernel(cmdline, "nospace", &content));
EXPECT_TRUE(content.empty()) << content;
}
+
+TEST(fs_mgr, fs_mgr_read_fstab_file_proc_mounts) {
+ auto fstab = fs_mgr_read_fstab("/proc/mounts");
+ ASSERT_NE(fstab, nullptr);
+
+ std::unique_ptr<std::FILE, int (*)(std::FILE*)> mounts(setmntent("/proc/mounts", "r"),
+ endmntent);
+ ASSERT_NE(mounts, nullptr);
+
+ mntent* mentry;
+ int i = 0;
+ while ((mentry = getmntent(mounts.get())) != nullptr) {
+ ASSERT_LT(i, fstab->num_entries);
+ auto fsrec = &fstab->recs[i];
+
+ std::string mnt_fsname(mentry->mnt_fsname ?: "nullptr");
+ std::string blk_device(fsrec->blk_device ?: "nullptr");
+ EXPECT_EQ(mnt_fsname, blk_device);
+
+ std::string mnt_dir(mentry->mnt_dir ?: "nullptr");
+ std::string mount_point(fsrec->mount_point ?: "nullptr");
+ EXPECT_EQ(mnt_dir, mount_point);
+
+ std::string mnt_type(mentry->mnt_type ?: "nullptr");
+ std::string fs_type(fsrec->fs_type ?: "nullptr");
+ EXPECT_EQ(mnt_type, fs_type);
+
+ std::set<std::string> mnt_opts;
+ for (auto& s : android::base::Split(mentry->mnt_opts ?: "nullptr", ",")) {
+ mnt_opts.emplace(s);
+ }
+ std::set<std::string> fs_options;
+ for (auto& s : android::base::Split(fsrec->fs_options ?: "nullptr", ",")) {
+ fs_options.emplace(s);
+ }
+ // matches private content in fs_mgr_fstab.c
+ static struct flag_list {
+ const char* name;
+ unsigned int flag;
+ } mount_flags[] = {
+ {"noatime", MS_NOATIME},
+ {"noexec", MS_NOEXEC},
+ {"nosuid", MS_NOSUID},
+ {"nodev", MS_NODEV},
+ {"nodiratime", MS_NODIRATIME},
+ {"ro", MS_RDONLY},
+ {"rw", 0},
+ {"remount", MS_REMOUNT},
+ {"bind", MS_BIND},
+ {"rec", MS_REC},
+ {"unbindable", MS_UNBINDABLE},
+ {"private", MS_PRIVATE},
+ {"slave", MS_SLAVE},
+ {"shared", MS_SHARED},
+ {"defaults", 0},
+ {0, 0},
+ };
+ for (auto f = 0; mount_flags[f].name; ++f) {
+ if (mount_flags[f].flag & fsrec->flags) {
+ fs_options.emplace(mount_flags[f].name);
+ }
+ }
+ if (!(fsrec->flags & MS_RDONLY)) fs_options.emplace("rw");
+ EXPECT_EQ(mnt_opts, fs_options);
+ ++i;
+ }
+}
diff --git a/fs_mgr/tools/dmctl.cpp b/fs_mgr/tools/dmctl.cpp
index 9d48b8c..5e11c84 100644
--- a/fs_mgr/tools/dmctl.cpp
+++ b/fs_mgr/tools/dmctl.cpp
@@ -50,6 +50,7 @@
std::cerr << " delete <dm-name>" << std::endl;
std::cerr << " list <devices | targets>" << std::endl;
std::cerr << " getpath <dm-name>" << std::endl;
+ std::cerr << " table <dm-name>" << std::endl;
std::cerr << " help" << std::endl;
std::cerr << std::endl;
std::cerr << "Target syntax:" << std::endl;
@@ -258,6 +259,31 @@
return 0;
}
+static int TableCmdHandler(int argc, char** argv) {
+ if (argc != 1) {
+ std::cerr << "Invalid arguments, see \'dmctl help\'" << std::endl;
+ return -EINVAL;
+ }
+
+ DeviceMapper& dm = DeviceMapper::Instance();
+ std::vector<DeviceMapper::TargetInfo> table;
+ if (!dm.GetTableStatus(argv[0], &table)) {
+ std::cerr << "Could not query table status of device \"" << argv[0] << "\"." << std::endl;
+ return -EINVAL;
+ }
+ std::cout << "Targets in the device-mapper table for " << argv[0] << ":" << std::endl;
+ for (const auto& target : table) {
+ std::cout << target.spec.sector_start << "-"
+ << (target.spec.sector_start + target.spec.length) << ": "
+ << target.spec.target_type;
+ if (!target.data.empty()) {
+ std::cout << ", " << target.data;
+ }
+ std::cout << std::endl;
+ }
+ return 0;
+}
+
static std::map<std::string, std::function<int(int, char**)>> cmdmap = {
// clang-format off
{"create", DmCreateCmdHandler},
@@ -265,6 +291,7 @@
{"list", DmListCmdHandler},
{"help", HelpCmdHandler},
{"getpath", GetPathCmdHandler},
+ {"table", TableCmdHandler},
// clang-format on
};
diff --git a/gatekeeperd/gatekeeperd.cpp b/gatekeeperd/gatekeeperd.cpp
index 61c8804..abb387c 100644
--- a/gatekeeperd/gatekeeperd.cpp
+++ b/gatekeeperd/gatekeeperd.cpp
@@ -234,11 +234,13 @@
virtual int verify(uint32_t uid,
const uint8_t *enrolled_password_handle, uint32_t enrolled_password_handle_length,
const uint8_t *provided_password, uint32_t provided_password_length, bool *request_reenroll) {
- uint8_t *auth_token;
+ uint8_t *auth_token = nullptr;
uint32_t auth_token_length;
- return verifyChallenge(uid, 0, enrolled_password_handle, enrolled_password_handle_length,
+ int ret = verifyChallenge(uid, 0, enrolled_password_handle, enrolled_password_handle_length,
provided_password, provided_password_length,
&auth_token, &auth_token_length, request_reenroll);
+ delete [] auth_token;
+ return ret;
}
virtual int verifyChallenge(uint32_t uid, uint64_t challenge,
diff --git a/init/Android.bp b/init/Android.bp
index cf7637f..625fb94 100644
--- a/init/Android.bp
+++ b/init/Android.bp
@@ -179,6 +179,7 @@
"rlimit_parser_test.cpp",
"service_test.cpp",
"subcontext_test.cpp",
+ "tokenizer_test.cpp",
"ueventd_test.cpp",
"util_test.cpp",
],
diff --git a/init/tokenizer.cpp b/init/tokenizer.cpp
index f8d9b6b..bb143f1 100644
--- a/init/tokenizer.cpp
+++ b/init/tokenizer.cpp
@@ -85,15 +85,19 @@
goto textdone;
case 'n':
*s++ = '\n';
+ x++;
break;
case 'r':
*s++ = '\r';
+ x++;
break;
case 't':
*s++ = '\t';
+ x++;
break;
case '\\':
*s++ = '\\';
+ x++;
break;
case '\r':
/* \ <cr> <lf> -> line continuation */
@@ -101,6 +105,7 @@
x++;
continue;
}
+ x++;
case '\n':
/* \ <lf> -> line continuation */
state->line++;
diff --git a/init/tokenizer_test.cpp b/init/tokenizer_test.cpp
new file mode 100644
index 0000000..acfc7c7
--- /dev/null
+++ b/init/tokenizer_test.cpp
@@ -0,0 +1,163 @@
+//
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "tokenizer.h"
+
+#include <string>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+namespace android {
+namespace init {
+
+namespace {
+
+void RunTest(const std::string& data, const std::vector<std::vector<std::string>>& expected_tokens) {
+ auto data_copy = std::string{data};
+ data_copy.push_back('\n'); // TODO: fix tokenizer
+ data_copy.push_back('\0');
+
+ parse_state state;
+ state.line = 0;
+ state.ptr = data_copy.data();
+ state.nexttoken = 0;
+
+ std::vector<std::string> current_line;
+ std::vector<std::vector<std::string>> tokens;
+
+ while (true) {
+ switch (next_token(&state)) {
+ case T_EOF:
+ EXPECT_EQ(expected_tokens, tokens) << data;
+ return;
+ case T_NEWLINE:
+ tokens.emplace_back(std::move(current_line));
+ break;
+ case T_TEXT:
+ current_line.emplace_back(state.text);
+ break;
+ }
+ }
+}
+
+} // namespace
+
+TEST(tokenizer, null) {
+ RunTest("", {{}});
+}
+
+TEST(tokenizer, simple_oneline) {
+ RunTest("one two\tthree\rfour", {{"one", "two", "three", "four"}});
+}
+
+TEST(tokenizer, simple_multiline) {
+ RunTest("1 2 3\n4 5 6\n7 8 9", {{"1", "2", "3"}, {"4", "5", "6"}, {"7", "8", "9"}});
+}
+
+TEST(tokenizer, preceding_space) {
+ // Preceding spaces are ignored.
+ RunTest(" 1 2 3\n\t\t\t\t4 5 6\n\r\r\r\r7 8 9",
+ {{"1", "2", "3"}, {"4", "5", "6"}, {"7", "8", "9"}});
+}
+
+TEST(tokenizer, comments) {
+ // Entirely commented lines still produce a T_NEWLINE token for tracking line count.
+ RunTest("1 2 3\n#4 5 6\n7 8 9", {{"1", "2", "3"}, {}, {"7", "8", "9"}});
+
+ RunTest("#1 2 3\n4 5 6\n7 8 9", {{}, {"4", "5", "6"}, {"7", "8", "9"}});
+
+ RunTest("1 2 3\n4 5 6\n#7 8 9", {{"1", "2", "3"}, {"4", "5", "6"}, {}});
+
+ RunTest("1 2 #3\n4 #5 6\n#7 8 9", {{"1", "2"}, {"4"}, {}});
+}
+
+TEST(tokenizer, control_chars) {
+ // Literal \n, \r, \t, and \\ produce the control characters \n, \r, \t, and \\ respectively.
+ // Literal \? produces ? for all other character '?'
+
+ RunTest(R"(1 token\ntoken 2)", {{"1", "token\ntoken", "2"}});
+ RunTest(R"(1 token\rtoken 2)", {{"1", "token\rtoken", "2"}});
+ RunTest(R"(1 token\ttoken 2)", {{"1", "token\ttoken", "2"}});
+ RunTest(R"(1 token\\token 2)", {{"1", "token\\token", "2"}});
+ RunTest(R"(1 token\btoken 2)", {{"1", "tokenbtoken", "2"}});
+
+ RunTest(R"(1 token\n 2)", {{"1", "token\n", "2"}});
+ RunTest(R"(1 token\r 2)", {{"1", "token\r", "2"}});
+ RunTest(R"(1 token\t 2)", {{"1", "token\t", "2"}});
+ RunTest(R"(1 token\\ 2)", {{"1", "token\\", "2"}});
+ RunTest(R"(1 token\b 2)", {{"1", "tokenb", "2"}});
+
+ RunTest(R"(1 \ntoken 2)", {{"1", "\ntoken", "2"}});
+ RunTest(R"(1 \rtoken 2)", {{"1", "\rtoken", "2"}});
+ RunTest(R"(1 \ttoken 2)", {{"1", "\ttoken", "2"}});
+ RunTest(R"(1 \\token 2)", {{"1", "\\token", "2"}});
+ RunTest(R"(1 \btoken 2)", {{"1", "btoken", "2"}});
+
+ RunTest(R"(1 \n 2)", {{"1", "\n", "2"}});
+ RunTest(R"(1 \r 2)", {{"1", "\r", "2"}});
+ RunTest(R"(1 \t 2)", {{"1", "\t", "2"}});
+ RunTest(R"(1 \\ 2)", {{"1", "\\", "2"}});
+ RunTest(R"(1 \b 2)", {{"1", "b", "2"}});
+}
+
+TEST(tokenizer, cr_lf) {
+ // \ before \n, \r, or \r\n is interpreted as a line continuation
+ // Extra whitespace on the next line is eaten, except \r unlike in the above tests.
+
+ RunTest("lf\\\ncont", {{"lfcont"}});
+ RunTest("lf\\\n \t\t\t\tcont", {{"lfcont"}});
+
+ RunTest("crlf\\\r\ncont", {{"crlfcont"}});
+ RunTest("crlf\\\r\n \t\t\t\tcont", {{"crlfcont"}});
+
+ RunTest("cr\\\rcont", {{"crcont"}});
+
+ RunTest("lfspace \\\ncont", {{"lfspace", "cont"}});
+ RunTest("lfspace \\\n \t\t\t\tcont", {{"lfspace", "cont"}});
+
+ RunTest("crlfspace \\\r\ncont", {{"crlfspace", "cont"}});
+ RunTest("crlfspace \\\r\n \t\t\t\tcont", {{"crlfspace", "cont"}});
+
+ RunTest("crspace \\\rcont", {{"crspace", "cont"}});
+}
+
+TEST(tokenizer, quoted) {
+ RunTest("\"quoted simple string\"", {{"quoted simple string"}});
+
+ // Unterminated quotes just return T_EOF without any T_NEWLINE.
+ RunTest("\"unterminated quoted string", {});
+
+ RunTest("\"1 2 3\"\n \"unterminated quoted string", {{"1 2 3"}});
+
+ // Escaping quotes is not allowed and are treated as an unterminated quoted string.
+ RunTest("\"quoted escaped quote\\\"\"", {});
+ RunTest("\"quoted escaped\\\" quote\"", {});
+ RunTest("\"\\\"quoted escaped quote\"", {});
+
+ RunTest("\"quoted control characters \\n \\r \\t \\\\ \\b \\\r \\\n \r \n\"",
+ {{"quoted control characters \\n \\r \\t \\\\ \\b \\\r \\\n \r \n"}});
+
+ RunTest("\"quoted simple string\" \"second quoted string\"",
+ {{"quoted simple string", "second quoted string"}});
+
+ RunTest("\"# comment quoted string\"", {{"# comment quoted string"}});
+
+ RunTest("\"Adjacent \"\"quoted strings\"", {{"Adjacent quoted strings"}});
+}
+
+} // namespace init
+} // namespace android
diff --git a/libcutils/sockets_unix.cpp b/libcutils/sockets_unix.cpp
index 2849aa8..0cb8a4d 100644
--- a/libcutils/sockets_unix.cpp
+++ b/libcutils/sockets_unix.cpp
@@ -32,10 +32,6 @@
#include "android_get_control_env.h"
-#ifndef TEMP_FAILURE_RETRY
-#define TEMP_FAILURE_RETRY(exp) (exp) // KISS implementation
-#endif
-
#if defined(__ANDROID__)
/* For the socket trust (credentials) check */
#include <private/android_filesystem_config.h>
@@ -102,15 +98,15 @@
// Compare to UNIX domain socket name, must match!
struct sockaddr_un addr;
socklen_t addrlen = sizeof(addr);
- int ret = TEMP_FAILURE_RETRY(getsockname(fd, (struct sockaddr *)&addr, &addrlen));
+ int ret = getsockname(fd, (struct sockaddr*)&addr, &addrlen);
if (ret < 0) return -1;
- char *path = NULL;
- if (asprintf(&path, ANDROID_SOCKET_DIR "/%s", name) < 0) return -1;
- if (!path) return -1;
- int cmp = strcmp(addr.sun_path, path);
- free(path);
- if (cmp != 0) return -1;
- // It is what we think it is
- return fd;
+ constexpr char prefix[] = ANDROID_SOCKET_DIR "/";
+ constexpr size_t prefix_size = sizeof(prefix) - sizeof('\0');
+ if ((strncmp(addr.sun_path, prefix, prefix_size) == 0) &&
+ (strcmp(addr.sun_path + prefix_size, name) == 0)) {
+ // It is what we think it is
+ return fd;
+ }
+ return -1;
}
diff --git a/liblog/include/android/log.h b/liblog/include/android/log.h
index 52cbe8b..ee9220d 100644
--- a/liblog/include/android/log.h
+++ b/liblog/include/android/log.h
@@ -115,16 +115,8 @@
*/
int __android_log_print(int prio, const char* tag, const char* fmt, ...)
#if defined(__GNUC__)
-#ifdef __USE_MINGW_ANSI_STDIO
-#if __USE_MINGW_ANSI_STDIO
- __attribute__((__format__(gnu_printf, 3, 4)))
-#else
__attribute__((__format__(printf, 3, 4)))
#endif
-#else
- __attribute__((__format__(printf, 3, 4)))
-#endif
-#endif
;
/**
@@ -133,16 +125,8 @@
*/
int __android_log_vprint(int prio, const char* tag, const char* fmt, va_list ap)
#if defined(__GNUC__)
-#ifdef __USE_MINGW_ANSI_STDIO
-#if __USE_MINGW_ANSI_STDIO
- __attribute__((__format__(gnu_printf, 3, 0)))
-#else
__attribute__((__format__(printf, 3, 0)))
#endif
-#else
- __attribute__((__format__(printf, 3, 0)))
-#endif
-#endif
;
/**
@@ -164,16 +148,8 @@
...)
#if defined(__GNUC__)
__attribute__((__noreturn__))
-#ifdef __USE_MINGW_ANSI_STDIO
-#if __USE_MINGW_ANSI_STDIO
- __attribute__((__format__(gnu_printf, 3, 4)))
-#else
__attribute__((__format__(printf, 3, 4)))
#endif
-#else
- __attribute__((__format__(printf, 3, 4)))
-#endif
-#endif
;
#ifndef log_id_t_defined
diff --git a/libsysutils/src/NetlinkEvent.cpp b/libsysutils/src/NetlinkEvent.cpp
index 35a3063..f0c66ec 100644
--- a/libsysutils/src/NetlinkEvent.cpp
+++ b/libsysutils/src/NetlinkEvent.cpp
@@ -239,12 +239,13 @@
asprintf(&mParams[1], "INTERFACE=%s", ifname);
asprintf(&mParams[2], "FLAGS=%u", ifaddr->ifa_flags);
asprintf(&mParams[3], "SCOPE=%u", ifaddr->ifa_scope);
+ asprintf(&mParams[4], "IFINDEX=%u", ifaddr->ifa_index);
if (cacheinfo) {
- asprintf(&mParams[4], "PREFERRED=%u", cacheinfo->ifa_prefered);
- asprintf(&mParams[5], "VALID=%u", cacheinfo->ifa_valid);
- asprintf(&mParams[6], "CSTAMP=%u", cacheinfo->cstamp);
- asprintf(&mParams[7], "TSTAMP=%u", cacheinfo->tstamp);
+ asprintf(&mParams[5], "PREFERRED=%u", cacheinfo->ifa_prefered);
+ asprintf(&mParams[6], "VALID=%u", cacheinfo->ifa_valid);
+ asprintf(&mParams[7], "CSTAMP=%u", cacheinfo->cstamp);
+ asprintf(&mParams[8], "TSTAMP=%u", cacheinfo->tstamp);
}
return true;
diff --git a/run-as/Android.bp b/run-as/Android.bp
new file mode 100644
index 0000000..840a43c
--- /dev/null
+++ b/run-as/Android.bp
@@ -0,0 +1,28 @@
+//
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_binary {
+ name: "run-as",
+ srcs: [
+ "run-as.cpp",
+ ],
+ shared_libs: [
+ "libbase",
+ "libselinux",
+ "libpackagelistparser",
+ "libminijail",
+ ],
+}
diff --git a/run-as/Android.mk b/run-as/Android.mk
deleted file mode 100644
index 7111fbe..0000000
--- a/run-as/Android.mk
+++ /dev/null
@@ -1,8 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_CFLAGS := -Wall -Werror
-LOCAL_MODULE := run-as
-LOCAL_SHARED_LIBRARIES := libselinux libpackagelistparser libminijail
-LOCAL_SRC_FILES := run-as.cpp
-include $(BUILD_EXECUTABLE)
diff --git a/run-as/run-as.cpp b/run-as/run-as.cpp
index b27cfad..d005ecf 100644
--- a/run-as/run-as.cpp
+++ b/run-as/run-as.cpp
@@ -28,6 +28,7 @@
#include <libminijail.h>
#include <scoped_minijail.h>
+#include <android-base/properties.h>
#include <packagelistparser/packagelistparser.h>
#include <private/android_filesystem_config.h>
#include <selinux/android.h>
@@ -40,6 +41,7 @@
// The 'run-as' binary is installed with CAP_SETUID and CAP_SETGID file
// capabilities, but will check the following:
//
+// - that the ro.boot.disable_runas property is not set
// - that it is invoked from the 'shell' or 'root' user (abort otherwise)
// - that '<package-name>' is the name of an installed and debuggable package
// - that the package's data directory is well-formed
@@ -139,6 +141,12 @@
error(1, 0, "only 'shell' or 'root' users can run this program");
}
+ // Some devices can disable running run-as, such as Chrome OS when running in
+ // non-developer mode.
+ if (android::base::GetBoolProperty("ro.boot.disable_runas", false)) {
+ error(1, 0, "run-as is disabled from the kernel commandline");
+ }
+
char* pkgname = argv[1];
int cmd_argv_offset = 2;