Merge "libsnapshot: Track the source slot across reboots."
diff --git a/adb/sysdeps.h b/adb/sysdeps.h
index b0e7fa0..b08a13b 100644
--- a/adb/sysdeps.h
+++ b/adb/sysdeps.h
@@ -91,11 +91,14 @@
extern int adb_open(const char* path, int options);
extern int adb_creat(const char* path, int mode);
extern int adb_read(borrowed_fd fd, void* buf, int len);
+extern int adb_pread(borrowed_fd fd, void* buf, int len, off64_t offset);
extern int adb_write(borrowed_fd fd, const void* buf, int len);
+extern int adb_pwrite(borrowed_fd fd, const void* buf, int len, off64_t offset);
extern int64_t adb_lseek(borrowed_fd fd, int64_t pos, int where);
extern int adb_shutdown(borrowed_fd fd, int direction = SHUT_RDWR);
extern int adb_close(int fd);
extern int adb_register_socket(SOCKET s);
+extern HANDLE adb_get_os_handle(borrowed_fd fd);
// See the comments for the !defined(_WIN32) version of unix_close().
static __inline__ int unix_close(int fd) {
@@ -115,6 +118,9 @@
#undef read
#define read ___xxx_read
+#undef pread
+#define pread ___xxx_pread
+
// See the comments for the !defined(_WIN32) version of unix_write().
static __inline__ int unix_write(borrowed_fd fd, const void* buf, size_t len) {
return write(fd.get(), buf, len);
@@ -122,6 +128,9 @@
#undef write
#define write ___xxx_write
+#undef pwrite
+#define pwrite ___xxx_pwrite
+
// See the comments for the !defined(_WIN32) version of unix_lseek().
static __inline__ int unix_lseek(borrowed_fd fd, int pos, int where) {
return lseek(fd.get(), pos, where);
@@ -415,6 +424,14 @@
return TEMP_FAILURE_RETRY(read(fd.get(), buf, len));
}
+static __inline__ int adb_pread(int fd, void* buf, size_t len, off64_t offset) {
+#if defined(__APPLE__)
+ return TEMP_FAILURE_RETRY(pread(fd, buf, len, offset));
+#else
+ return TEMP_FAILURE_RETRY(pread64(fd, buf, len, offset));
+#endif
+}
+
// Like unix_read(), but does not handle EINTR.
static __inline__ int unix_read_interruptible(borrowed_fd fd, void* buf, size_t len) {
return read(fd.get(), buf, len);
@@ -422,12 +439,25 @@
#undef read
#define read ___xxx_read
+#undef pread
+#define pread ___xxx_pread
static __inline__ int adb_write(borrowed_fd fd, const void* buf, size_t len) {
return TEMP_FAILURE_RETRY(write(fd.get(), buf, len));
}
+
+static __inline__ int adb_pwrite(int fd, const void* buf, size_t len, off64_t offset) {
+#if defined(__APPLE__)
+ return TEMP_FAILURE_RETRY(pwrite(fd, buf, len, offset));
+#else
+ return TEMP_FAILURE_RETRY(pwrite64(fd, buf, len, offset));
+#endif
+}
+
#undef write
#define write ___xxx_write
+#undef pwrite
+#define pwrite ___xxx_pwrite
static __inline__ int64_t adb_lseek(borrowed_fd fd, int64_t pos, int where) {
#if defined(__APPLE__)
diff --git a/adb/sysdeps_win32.cpp b/adb/sysdeps_win32.cpp
index dc2525c..4d6cf3d 100644
--- a/adb/sysdeps_win32.cpp
+++ b/adb/sysdeps_win32.cpp
@@ -60,6 +60,7 @@
int (*_fh_read)(FH, void*, int);
int (*_fh_write)(FH, const void*, int);
int (*_fh_writev)(FH, const adb_iovec*, int);
+ intptr_t (*_fh_get_os_handle)(FH);
} FHClassRec;
static void _fh_file_init(FH);
@@ -68,14 +69,11 @@
static int _fh_file_read(FH, void*, int);
static int _fh_file_write(FH, const void*, int);
static int _fh_file_writev(FH, const adb_iovec*, int);
+static intptr_t _fh_file_get_os_handle(FH f);
static const FHClassRec _fh_file_class = {
- _fh_file_init,
- _fh_file_close,
- _fh_file_lseek,
- _fh_file_read,
- _fh_file_write,
- _fh_file_writev,
+ _fh_file_init, _fh_file_close, _fh_file_lseek, _fh_file_read,
+ _fh_file_write, _fh_file_writev, _fh_file_get_os_handle,
};
static void _fh_socket_init(FH);
@@ -84,14 +82,11 @@
static int _fh_socket_read(FH, void*, int);
static int _fh_socket_write(FH, const void*, int);
static int _fh_socket_writev(FH, const adb_iovec*, int);
+static intptr_t _fh_socket_get_os_handle(FH f);
static const FHClassRec _fh_socket_class = {
- _fh_socket_init,
- _fh_socket_close,
- _fh_socket_lseek,
- _fh_socket_read,
- _fh_socket_write,
- _fh_socket_writev,
+ _fh_socket_init, _fh_socket_close, _fh_socket_lseek, _fh_socket_read,
+ _fh_socket_write, _fh_socket_writev, _fh_socket_get_os_handle,
};
#if defined(assert)
@@ -331,6 +326,10 @@
return li.QuadPart;
}
+static intptr_t _fh_file_get_os_handle(FH f) {
+ return reinterpret_cast<intptr_t>(f->u.handle);
+}
+
/**************************************************************************/
/**************************************************************************/
/***** *****/
@@ -456,6 +455,26 @@
return f->clazz->_fh_read(f, buf, len);
}
+int adb_pread(borrowed_fd fd, void* buf, int len, off64_t offset) {
+ OVERLAPPED overlapped = {};
+ overlapped.Offset = static_cast<DWORD>(offset);
+ overlapped.OffsetHigh = static_cast<DWORD>(offset >> 32);
+ DWORD bytes_read;
+ if (!::ReadFile(adb_get_os_handle(fd), buf, static_cast<DWORD>(len), &bytes_read,
+ &overlapped)) {
+ D("adb_pread: could not read %d bytes from FD %d", len, fd.get());
+ switch (::GetLastError()) {
+ case ERROR_IO_PENDING:
+ errno = EAGAIN;
+ return -1;
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+ }
+ return static_cast<int>(bytes_read);
+}
+
int adb_write(borrowed_fd fd, const void* buf, int len) {
FH f = _fh_from_int(fd, __func__);
@@ -478,6 +497,25 @@
return f->clazz->_fh_writev(f, iov, iovcnt);
}
+int adb_pwrite(borrowed_fd fd, const void* buf, int len, off64_t offset) {
+ OVERLAPPED params = {};
+ params.Offset = static_cast<DWORD>(offset);
+ params.OffsetHigh = static_cast<DWORD>(offset >> 32);
+ DWORD bytes_written = 0;
+ if (!::WriteFile(adb_get_os_handle(fd), buf, len, &bytes_written, ¶ms)) {
+ D("adb_pwrite: could not write %d bytes to FD %d", len, fd.get());
+ switch (::GetLastError()) {
+ case ERROR_IO_PENDING:
+ errno = EAGAIN;
+ return -1;
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+ }
+ return static_cast<int>(bytes_written);
+}
+
int64_t adb_lseek(borrowed_fd fd, int64_t pos, int where) {
FH f = _fh_from_int(fd, __func__);
if (!f) {
@@ -500,6 +538,20 @@
return 0;
}
+HANDLE adb_get_os_handle(borrowed_fd fd) {
+ FH f = _fh_from_int(fd, __func__);
+
+ if (!f) {
+ errno = EBADF;
+ return nullptr;
+ }
+
+ D("adb_get_os_handle: %s", f->name);
+ const intptr_t intptr_handle = f->clazz->_fh_get_os_handle(f);
+ const HANDLE handle = reinterpret_cast<const HANDLE>(intptr_handle);
+ return handle;
+}
+
/**************************************************************************/
/**************************************************************************/
/***** *****/
@@ -694,6 +746,10 @@
return static_cast<int>(bytes_written);
}
+static intptr_t _fh_socket_get_os_handle(FH f) {
+ return f->u.socket;
+}
+
/**************************************************************************/
/**************************************************************************/
/***** *****/
diff --git a/fs_mgr/tests/adb-remount-test.sh b/fs_mgr/tests/adb-remount-test.sh
index 642f2c1..397d8e5 100755
--- a/fs_mgr/tests/adb-remount-test.sh
+++ b/fs_mgr/tests/adb-remount-test.sh
@@ -890,14 +890,37 @@
# If reboot too soon after fresh flash, could trip device update failure logic
wait_for_screen
# Can we test remount -R command?
+OVERLAYFS_BACKING="cache mnt/scratch"
overlayfs_supported=true
-if [ "orange" = "`get_property ro.boot.verifiedbootstate`" -a \
- "2" = "`get_property partition.system.verified`" ]; then
+if [ "orange" != "`get_property ro.boot.verifiedbootstate`" -o \
+ "2" != "`get_property partition.system.verified`" ]; then
restore() {
${overlayfs_supported} || return 0
inFastboot &&
fastboot reboot &&
- adb_wait ${ADB_WAIT}
+ adb_wait ${ADB_WAIT} ||
+ true
+ if inAdb; then
+ reboot=false
+ for d in ${OVERLAYFS_BACKING}; do
+ if adb_su ls -d /${d}/overlay </dev/null >/dev/null 2>/dev/null; then
+ adb_su rm -rf /${d}/overlay </dev/null
+ reboot=true
+ fi
+ done
+ if ${reboot}; then
+ adb_reboot &&
+ adb_wait ${ADB_WAIT}
+ fi
+ fi
+ }
+else
+ restore() {
+ ${overlayfs_supported} || return 0
+ inFastboot &&
+ fastboot reboot &&
+ adb_wait ${ADB_WAIT} ||
+ true
inAdb &&
adb_root &&
adb enable-verity >/dev/null 2>/dev/null &&
@@ -956,7 +979,6 @@
# So lets do our best to surgically wipe the overlayfs state without
# having to go through enable-verity transition.
reboot=false
-OVERLAYFS_BACKING="cache mnt/scratch"
for d in ${OVERLAYFS_BACKING}; do
if adb_sh ls -d /${d}/overlay </dev/null >/dev/null 2>/dev/null; then
echo "${ORANGE}[ WARNING ]${NORMAL} /${d}/overlay is setup, surgically wiping" >&2
@@ -1468,7 +1490,7 @@
}
dd if=/dev/zero of=${img} bs=4096 count=16 2>/dev/null &&
fastboot_wait ${FASTBOOT_WAIT} ||
- die "reboot into fastboot `usb_status`"
+ die "reboot into fastboot to flash scratch `usb_status`"
fastboot flash --force ${scratch_partition} ${img}
err=${?}
cleanup
diff --git a/init/README.ueventd.md b/init/README.ueventd.md
new file mode 100644
index 0000000..c592c37
--- /dev/null
+++ b/init/README.ueventd.md
@@ -0,0 +1,112 @@
+# Ueventd
+-------
+Ueventd manages `/dev`, sets permissions for `/sys`, and handles firmware uevents. It has default
+behavior described below, along with a scripting language that allows customizing this behavior,
+built on the same parser as init.
+
+Ueventd has one generic customization parameter, the size of rcvbuf_size for the ueventd socket. It
+is customized by the `uevent_socket_rcvbuf_size` parameter, which takes the format of
+
+ uevent_socket_rcvbuf_size <size>
+For example
+
+ uevent_socket_rcvbuf_size 16M
+Sets the uevent socket rcvbuf_size to 16 megabytes.
+
+## /dev
+----
+Ueventd listens to the kernel uevent sockets and creates/deletes nodes in `/dev` based on the
+incoming add/remove uevents. It defaults to using `0600` mode and `root` user/group. It always
+creates the nodes with the SELabel from the current loaded SEPolicy. It has three default behaviors
+for the node path:
+
+ 1. Block devices are created as `/dev/block/<basename uevent DEVPATH>`. There are symlinks created
+ to this node at `/dev/block/<type>/<parent device>/<basename uevent DEVPATH>`,
+ `/dev/block/<type>/<parent device>/by-name/<uevent PARTNAME>`, and `/dev/block/by-name/<uevent
+ PARTNAME>` if the device is a boot device.
+ 2. USB devices are created as `/dev/<uevent DEVNAME>` if `DEVNAME` was specified for the uevent,
+ otherwise as `/dev/bus/usb/<bus_id>/<device_id>` where `bus_id` is `uevent MINOR / 128 + 1` and
+ `device_id` is `uevent MINOR % 128 + 1`.
+ 3. All other devices are created as `/dev/<basename uevent DEVPATH>`
+
+The permissions can be modified using a ueventd.rc script and a line that beings with `/dev`. These
+lines take the format of
+
+ devname mode uid gid
+For example
+
+ /dev/null 0666 root root
+When `/dev/null` is created, its mode will be set to `0666`, its user to `root` and its group to
+`root`.
+
+The path can be modified using a ueventd.rc script and a `subsystem` section. There are three to set
+for a subsystem: the subsystem name, which device name to use, and which directory to place the
+device in. The section takes the below format of
+
+ subsystem <subsystem_name>
+ devname uevent_devname|uevent_devpath
+ [dirname <directory>]
+
+`subsystem_name` is used to match uevent `SUBSYSTEM` value
+
+`devname` takes one of two options
+ 1. `uevent_devname` specifies that the name of the node will be the uevent `DEVNAME`
+ 2. `uevent_devpath` specified that the name of the node will be basename uevent `DEVPATH`
+
+`dirname` is an optional parameter that specifies a directory within `/dev` where the node will be
+created.
+
+For example
+
+ subsystem sound
+ devname uevent_devpath
+ dirname /dev/snd
+Indicates that all uevents with `SUBSYSTEM=sound` will create nodes as `/dev/snd/<basename uevent
+DEVPATH>`.
+
+## /sys
+----
+Ueventd by default takes no action for `/sys`, however it can be instructed to set permissions for
+certain files in `/sys` when matching uevents are generated. This is done using a ueventd.rc script
+and a line that begins with `/sys`. These lines take the format of
+
+ nodename attr mode uid gid
+For example
+
+ /sys/devices/system/cpu/cpu* cpufreq/scaling_max_freq 0664 system system
+When a uevent that matches the pattern `/sys/devices/system/cpu/cpu*` is sent, the matching sysfs
+attribute, `cpufreq/scaling_max_freq`, will have its mode set to `0664`, its user to to `system` and
+its group set to `system`.
+
+Note that `*` matches as a wildcard and can be used anywhere in a path.
+
+## Firmware loading
+----------------
+Ueventd automatically serves firmware requests by searching through a list of firmware directories
+for a file matching the uevent `FIRMWARE`. It then forks a process to serve this firmware to the
+kernel.
+
+The list of firmware directories is customized by a `firmware_directories` line in a ueventd.rc
+file. This line takes the format of
+
+ firmware_directories <firmware_directory> [ <firmware_directory> ]*
+For example
+
+ firmware_directories /etc/firmware/ /odm/firmware/ /vendor/firmware/ /firmware/image/
+Adds those 4 directories, in that order to the list of firmware directories that will be tried by
+ueventd. Note that this option always accumulates to the list; it is not possible to remove previous
+entries.
+
+Ueventd will wait until after `post-fs` in init, to keep retrying before believing the firmwares are
+not present.
+
+## Coldboot
+--------
+Ueventd must create devices in `/dev` for all devices that have already sent their uevents before
+ueventd has started. To do so, when ueventd is started it does what it calls a 'coldboot' on `/sys`,
+in which it writes 'add' to every 'uevent' file that it finds in `/sys/class`, `/sys/block`, and
+`/sys/devices`. This causes the kernel to regenerate the uevents for these paths, and thus for
+ueventd to create the nodes.
+
+For boot time purposes, this is done in parallel across a set of child processes. `ueventd.cpp` in
+this directory contains documentation on how the parallelization is done.
diff --git a/init/first_stage_init.cpp b/init/first_stage_init.cpp
index b60c450..fd2d766 100644
--- a/init/first_stage_init.cpp
+++ b/init/first_stage_init.cpp
@@ -121,9 +121,9 @@
_exit(127);
}
ioctl(fd, TIOCSCTTY, 0);
- dup2(fd, 0);
- dup2(fd, 1);
- dup2(fd, 2);
+ dup2(fd, STDIN_FILENO);
+ dup2(fd, STDOUT_FILENO);
+ dup2(fd, STDERR_FILENO);
close(fd);
const char* path = "/system/bin/sh";
@@ -291,6 +291,10 @@
const char* path = "/system/bin/init";
const char* args[] = {path, "selinux_setup", nullptr};
+ auto fd = open("/dev/kmsg", O_WRONLY | O_CLOEXEC);
+ dup2(fd, STDOUT_FILENO);
+ dup2(fd, STDERR_FILENO);
+ close(fd);
execv(path, const_cast<char**>(args));
// execv() only returns if an error happened, in which case we
diff --git a/init/selinux.cpp b/init/selinux.cpp
index 143cdfd..fd42256 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -523,6 +523,7 @@
// This function initializes SELinux then execs init to run in the init SELinux context.
int SetupSelinux(char** argv) {
+ SetStdioToDevNull(argv);
InitKernelLogging(argv);
if (REBOOT_BOOTLOADER_ON_PANIC) {
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 86d8042..4d34b67 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -121,6 +121,9 @@
mkdir /mnt/media_rw 0750 root media_rw
mkdir /mnt/user 0755 root root
mkdir /mnt/user/0 0755 root root
+ mkdir /mnt/user/0/self 0755 root root
+ mkdir /mnt/user/0/emulated 0755 root root
+ mkdir /mnt/user/0/emulated/0 0755 root root
mkdir /mnt/expand 0771 system system
mkdir /mnt/appfuse 0711 root root
@@ -367,9 +370,6 @@
# Once everything is setup, no need to modify /.
# The bind+remount combination allows this to work in containers.
mount rootfs rootfs / remount bind ro nodev
- # Mount default storage into root namespace
- mount none /mnt/runtime/default /storage bind rec
- mount none none /storage slave rec
# Make sure /sys/kernel/debug (if present) is labeled properly
# Note that tracefs may be mounted under debug, so we need to cross filesystems
@@ -642,6 +642,22 @@
chown root system /dev/fscklogs/log
chmod 0770 /dev/fscklogs/log
+# Switch between sdcardfs and FUSE depending on persist property
+# TODO: Move this to ro property before launch because FDE devices
+# interact with persistent properties differently during boot
+on zygote-start && property:persist.sys.fuse=true
+ # Mount default storage into root namespace
+ mount none /mnt/user/0 /storage bind rec
+ mount none none /storage slave rec
+on zygote-start && property:persist.sys.fuse=false
+ # Mount default storage into root namespace
+ mount none /mnt/runtime/default /storage bind rec
+ mount none none /storage slave rec
+on zygote-start && property:persist.sys.fuse=""
+ # Mount default storage into root namespace
+ mount none /mnt/runtime/default /storage bind rec
+ mount none none /storage slave rec
+
# It is recommended to put unnecessary data/ initialization from post-fs-data
# to start-zygote in device's init.rc to unblock zygote start.
on zygote-start && property:ro.crypto.state=unencrypted