Merge "Revert "Move property_context label handling to libselinux.""
diff --git a/adb/Android.mk b/adb/Android.mk
index 3cadee3..8ebcbf0 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -64,8 +64,6 @@
$(EXTRA_SRCS) \
$(USB_SRCS) \
-LOCAL_C_INCLUDES += external/openssl/include
-
ifneq ($(USE_SYSDEPS_WIN32),)
LOCAL_SRC_FILES += sysdeps_win32.c
else
@@ -77,7 +75,7 @@
LOCAL_MODULE := adb
LOCAL_MODULE_TAGS := debug
-LOCAL_STATIC_LIBRARIES := libzipfile libunz libcrypto_static $(EXTRA_STATIC_LIBS)
+LOCAL_STATIC_LIBRARIES := libzipfile libz libcrypto_static $(EXTRA_STATIC_LIBS)
ifeq ($(USE_SYSDEPS_WIN32),)
LOCAL_STATIC_LIBRARIES += libcutils
endif
@@ -112,6 +110,7 @@
jdwp_service.c \
framebuffer_service.c \
remount_service.c \
+ set_verity_enable_state_service.c \
usb_linux_client.c
LOCAL_CFLAGS := \
@@ -126,14 +125,27 @@
LOCAL_CFLAGS += -DALLOW_ADBD_ROOT=1
endif
+ifneq (,$(filter userdebug,$(TARGET_BUILD_VARIANT)))
+LOCAL_CFLAGS += -DALLOW_ADBD_DISABLE_VERITY=1
+endif
+
LOCAL_MODULE := adbd
LOCAL_FORCE_STATIC_EXECUTABLE := true
LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT_SBIN)
LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_SBIN_UNSTRIPPED)
+LOCAL_C_INCLUDES += system/extras/ext4_utils system/core/fs_mgr/include
-LOCAL_STATIC_LIBRARIES := liblog libcutils libc libmincrypt libselinux
+LOCAL_STATIC_LIBRARIES := liblog \
+ libfs_mgr \
+ libcutils \
+ libc \
+ libmincrypt \
+ libselinux \
+ libext4_utils_static
+
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
+
include $(BUILD_EXECUTABLE)
@@ -167,11 +179,9 @@
-D_XOPEN_SOURCE \
-D_GNU_SOURCE
-LOCAL_C_INCLUDES += external/openssl/include
-
LOCAL_MODULE := adb
-LOCAL_STATIC_LIBRARIES := libzipfile libunz libcutils liblog
+LOCAL_STATIC_LIBRARIES := libzipfile libz libcutils liblog
LOCAL_SHARED_LIBRARIES := libcrypto
diff --git a/adb/adb.h b/adb/adb.h
index 6f5f997..35d8a4d 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -328,7 +328,10 @@
#if !ADB_HOST
void framebuffer_service(int fd, void *cookie);
+// Allow enable-verity to write to system and vendor block devices
+int make_system_and_vendor_block_devices_writable();
void remount_service(int fd, void *cookie);
+void set_verity_enabled_state_service(int fd, void* cookie);
#endif
/* packet allocator */
@@ -338,6 +341,9 @@
int check_header(apacket *p);
int check_data(apacket *p);
+// Define it if you want to dump packets.
+#define DEBUG_PACKETS 0
+
#if !DEBUG_PACKETS
#define print_packet(tag,p) do {} while (0)
#endif
diff --git a/adb/adb_auth.h b/adb/adb_auth.h
index b24c674..54dd537 100644
--- a/adb/adb_auth.h
+++ b/adb/adb_auth.h
@@ -18,6 +18,7 @@
#define __ADB_AUTH_H
void adb_auth_init(void);
+int adb_auth_keygen(const char* filename);
void adb_auth_verified(atransport *t);
void send_auth_request(atransport *t);
diff --git a/adb/adb_auth_host.c b/adb/adb_auth_host.c
index c72fe42..a859199 100644
--- a/adb/adb_auth_host.c
+++ b/adb/adb_auth_host.c
@@ -15,9 +15,12 @@
*/
#include <stdio.h>
+#include <stdlib.h>
#ifdef _WIN32
-# define WIN32_LEAN_AND_MEAN
+# ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN
+# endif
# include "windows.h"
# include "shlobj.h"
#else
@@ -114,18 +117,34 @@
static void get_user_info(char *buf, size_t len)
{
char hostname[1024], username[1024];
- int ret;
+ int ret = -1;
+
+ if (getenv("HOSTNAME") != NULL) {
+ strncpy(hostname, getenv("HOSTNAME"), sizeof(hostname));
+ hostname[sizeof(hostname)-1] = '\0';
+ ret = 0;
+ }
#ifndef _WIN32
- ret = gethostname(hostname, sizeof(hostname));
if (ret < 0)
+ ret = gethostname(hostname, sizeof(hostname));
#endif
+ if (ret < 0)
strcpy(hostname, "unknown");
+ ret = -1;
+
+ if (getenv("LOGNAME") != NULL) {
+ strncpy(username, getenv("LOGNAME"), sizeof(username));
+ username[sizeof(username)-1] = '\0';
+ ret = 0;
+ }
+
#if !defined _WIN32 && !defined ADB_HOST_ON_TARGET
- ret = getlogin_r(username, sizeof(username));
if (ret < 0)
+ ret = getlogin_r(username, sizeof(username));
#endif
+ if (ret < 0)
strcpy(username, "unknown");
ret = snprintf(buf, len, " %s@%s", username, hostname);
@@ -436,6 +455,11 @@
return ret + 1;
}
+int adb_auth_keygen(const char* filename) {
+ adb_trace_mask |= (1 << TRACE_AUTH);
+ return (generate_key(filename) == 0);
+}
+
void adb_auth_init(void)
{
int ret;
diff --git a/adb/adb_client.c b/adb/adb_client.c
index eb1720d..ac5e15a 100644
--- a/adb/adb_client.c
+++ b/adb/adb_client.c
@@ -279,7 +279,7 @@
fd = _adb_connect(service);
if(fd == -1) {
- D("_adb_connect error: %s\n", __adb_error);
+ D("_adb_connect error: %s", __adb_error);
} else if(fd == -2) {
fprintf(stderr,"** daemon still not running\n");
}
diff --git a/adb/adb_trace.h b/adb/adb_trace.h
index 8a5d9f8..b8a2f4c 100644
--- a/adb/adb_trace.h
+++ b/adb/adb_trace.h
@@ -73,8 +73,9 @@
if (ADB_TRACING) { \
int save_errno = errno; \
adb_mutex_lock(&D_lock); \
- fprintf(stderr, "%s::%s():", \
- __FILE__, __FUNCTION__); \
+ fprintf(stderr, "%16s: %5d:%5lu | ", \
+ __FUNCTION__, \
+ getpid(), adb_thread_id()); \
errno = save_errno; \
fprintf(stderr, __VA_ARGS__ ); \
fflush(stderr); \
@@ -96,15 +97,16 @@
} while (0)
# define DD(...) \
do { \
- int save_errno = errno; \
- adb_mutex_lock(&D_lock); \
- fprintf(stderr, "%s::%s():", \
- __FILE__, __FUNCTION__); \
- errno = save_errno; \
- fprintf(stderr, __VA_ARGS__ ); \
- fflush(stderr); \
- adb_mutex_unlock(&D_lock); \
- errno = save_errno; \
+ int save_errno = errno; \
+ adb_mutex_lock(&D_lock); \
+ fprintf(stderr, "%16s: %5d:%5lu | ", \
+ __FUNCTION__, \
+ getpid(), adb_thread_id()); \
+ errno = save_errno; \
+ fprintf(stderr, __VA_ARGS__ ); \
+ fflush(stderr); \
+ adb_mutex_unlock(&D_lock); \
+ errno = save_errno; \
} while (0)
#else
# define D(...) \
diff --git a/adb/commandline.c b/adb/commandline.c
index 23e9ea4..49f1b95 100644
--- a/adb/commandline.c
+++ b/adb/commandline.c
@@ -36,6 +36,7 @@
#define TRACE_TAG TRACE_ADB
#include "adb.h"
#include "adb_client.h"
+#include "adb_auth.h"
#include "file_sync_service.h"
static int do_cmd(transport_type ttype, char* serial, char *cmd, ...);
@@ -189,6 +190,11 @@
"\n"
" adb restore <file> - restore device contents from the <file> backup archive\n"
"\n"
+ " adb disable-verity - disable dm-verity checking on USERDEBUG builds\n"
+ " adb enable-verity - re-enable dm-verity checking on USERDEBUG builds\n"
+ " adb keygen <file> - generate adb public/private key. The private key is stored in <file>,\n"
+ " and the public key is stored in <file>.pub. Any existing files\n"
+ " are overwritten.\n"
" adb help - show this help message\n"
" adb version - show version num\n"
"\n"
@@ -205,8 +211,7 @@
" adb reboot-bootloader - reboots the device into the bootloader\n"
" adb root - restarts the adbd daemon with root permissions\n"
" adb usb - restarts the adbd daemon listening on USB\n"
- " adb tcpip <port> - restarts the adbd daemon listening on TCP on the specified port"
- "\n"
+ " adb tcpip <port> - restarts the adbd daemon listening on TCP on the specified port\n"
"networking:\n"
" adb ppp <tty> [parameters] - Run PPP over USB.\n"
" Note: you should not automatically start a PPP connection.\n"
@@ -1442,7 +1447,8 @@
if(!strcmp(argv[0], "remount") || !strcmp(argv[0], "reboot")
|| !strcmp(argv[0], "reboot-bootloader")
|| !strcmp(argv[0], "tcpip") || !strcmp(argv[0], "usb")
- || !strcmp(argv[0], "root")) {
+ || !strcmp(argv[0], "root") || !strcmp(argv[0], "disable-verity")
+ || !strcmp(argv[0], "enable-verity")) {
char command[100];
if (!strcmp(argv[0], "reboot-bootloader"))
snprintf(command, sizeof(command), "reboot:bootloader");
@@ -1725,6 +1731,11 @@
return restore(argc, argv);
}
+ if (!strcmp(argv[0], "keygen")) {
+ if (argc < 2) return usage();
+ return adb_auth_keygen(argv[1]);
+ }
+
if (!strcmp(argv[0], "jdwp")) {
int fd = adb_connect("jdwp");
if (fd >= 0) {
diff --git a/adb/fdevent.c b/adb/fdevent.c
index 43e600c..f5ecd14 100644
--- a/adb/fdevent.c
+++ b/adb/fdevent.c
@@ -661,6 +661,8 @@
if(adb_socketpair(s)) {
FATAL("cannot create shell-exit socket-pair\n");
}
+ D("socketpair: (%d,%d)", s[0], s[1]);
+
SHELL_EXIT_NOTIFY_FD = s[0];
fdevent *fde;
fde = fdevent_create(s[1], fdevent_subproc_event_func, NULL);
diff --git a/adb/framebuffer_service.c b/adb/framebuffer_service.c
index 8cbe840..61578aa 100644
--- a/adb/framebuffer_service.c
+++ b/adb/framebuffer_service.c
@@ -76,6 +76,7 @@
exit(1);
}
+ close(fds[1]);
fd_screencap = fds[0];
/* read w, h & format */
@@ -173,10 +174,9 @@
}
done:
- TEMP_FAILURE_RETRY(waitpid(pid, NULL, 0));
-
close(fds[0]);
- close(fds[1]);
+
+ TEMP_FAILURE_RETRY(waitpid(pid, NULL, 0));
pipefail:
close(fd);
}
diff --git a/adb/jdwp_service.c b/adb/jdwp_service.c
index cd62b55..3074e42 100644
--- a/adb/jdwp_service.c
+++ b/adb/jdwp_service.c
@@ -415,6 +415,7 @@
__FUNCTION__, strerror(errno));
return -1;
}
+ D("socketpair: (%d,%d)", fds[0], fds[1]);
proc->out_fds[ proc->out_count ] = fds[1];
if (++proc->out_count == 1)
diff --git a/adb/remount_service.c b/adb/remount_service.c
index 72d15a1..05d3169 100644
--- a/adb/remount_service.c
+++ b/adb/remount_service.c
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#include "sysdeps.h"
+
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
@@ -22,7 +24,7 @@
#include <sys/mount.h>
#include <unistd.h>
-#include "sysdeps.h"
+#include "cutils/properties.h"
#define TRACE_TAG TRACE_ADB
#include "adb.h"
@@ -77,29 +79,57 @@
return false;
}
+static int make_block_device_writable(const char* dir)
+{
+ char *dev = 0;
+ int fd = -1;
+ int OFF = 0;
+ int rc = -1;
+
+ dev = find_mount(dir);
+ if (!dev)
+ goto errout;
+
+ fd = unix_open(dev, O_RDONLY | O_CLOEXEC);
+ if (fd < 0)
+ goto errout;
+
+ if (ioctl(fd, BLKROSET, &OFF)) {
+ goto errout;
+ }
+
+ rc = 0;
+
+errout:
+ if (fd >= 0) {
+ adb_close(fd);
+ }
+
+ if (dev) {
+ free(dev);
+ }
+ return rc;
+}
+
/* Init mounts /system as read only, remount to enable writes. */
static int remount(const char* dir, int* dir_ro)
{
char *dev;
- int fd;
int OFF = 0;
if (dir_ro == 0) {
return 0;
}
+ if (make_block_device_writable(dir)) {
+ return -1;
+ }
+
dev = find_mount(dir);
if (!dev)
return -1;
- fd = unix_open(dev, O_RDONLY | O_CLOEXEC);
- if (fd < 0)
- return -1;
-
- ioctl(fd, BLKROSET, &OFF);
- adb_close(fd);
-
*dir_ro = mount(dev, dir, "none", MS_REMOUNT, NULL);
free(dev);
@@ -112,9 +142,61 @@
writex(fd, str, strlen(str));
}
+int make_system_and_vendor_block_devices_writable(int fd)
+{
+ char buffer[200];
+ if (make_block_device_writable("/system")) {
+ snprintf(buffer, sizeof(buffer),
+ "Failed to make system block device writable %s\n",
+ strerror(errno));
+ write_string(fd, buffer);
+ return -1;
+ }
+
+ if (hasVendorPartition() && make_block_device_writable("/vendor")) {
+ snprintf(buffer, sizeof(buffer),
+ "Failed to make vendor block device writable: %s\n",
+ strerror(errno));
+ write_string(fd, buffer);
+ return -1;
+ }
+
+ return 0;
+}
+
void remount_service(int fd, void *cookie)
{
char buffer[200];
+ char prop_buf[PROPERTY_VALUE_MAX];
+
+ bool system_verified = false, vendor_verified = false;
+ property_get("partition.system.verified", prop_buf, "0");
+ if (!strcmp(prop_buf, "1")) {
+ system_verified = true;
+ }
+
+ property_get("partition.vendor.verified", prop_buf, "0");
+ if (!strcmp(prop_buf, "1")) {
+ vendor_verified = true;
+ }
+
+ if (system_verified || vendor_verified) {
+ // Allow remount but warn of likely bad effects
+ bool both = system_verified && vendor_verified;
+ snprintf(buffer, sizeof(buffer),
+ "dm_verity is enabled on the %s%s%s partition%s.\n",
+ system_verified ? "system" : "",
+ both ? " and " : "",
+ vendor_verified ? "vendor" : "",
+ both ? "s" : "");
+ write_string(fd, buffer);
+ snprintf(buffer, sizeof(buffer),
+ "Use \"adb disable-verity\" to disable verity.\n"
+ "If you do not, remount may succeed, however, you will still "
+ "not be able to write to these volumes.\n");
+ write_string(fd, buffer);
+ }
+
if (remount("/system", &system_ro)) {
snprintf(buffer, sizeof(buffer), "remount of system failed: %s\n",strerror(errno));
write_string(fd, buffer);
@@ -135,4 +217,3 @@
adb_close(fd);
}
-
diff --git a/adb/services.c b/adb/services.c
index bcfc163..d5a4642 100644
--- a/adb/services.c
+++ b/adb/services.c
@@ -164,6 +164,7 @@
printf("cannot create service socket pair\n");
return -1;
}
+ D("socketpair: (%d,%d)", s[0], s[1]);
sti = malloc(sizeof(stinfo));
if(sti == 0) fatal("cannot allocate stinfo");
@@ -264,10 +265,11 @@
// 0 is parent socket, 1 is child socket
int sv[2];
- if (unix_socketpair(AF_UNIX, SOCK_STREAM, 0, sv) < 0) {
+ if (adb_socketpair(sv) < 0) {
printf("[ cannot create socket pair - %s ]\n", strerror(errno));
return -1;
}
+ D("socketpair: (%d,%d)", sv[0], sv[1]);
*pid = fork();
if (*pid < 0) {
@@ -469,6 +471,10 @@
free(cookie);
}
}
+ } else if(!strncmp(name, "disable-verity:", 15)) {
+ ret = create_service_thread(set_verity_enabled_state_service, (void*)0);
+ } else if(!strncmp(name, "enable-verity:", 15)) {
+ ret = create_service_thread(set_verity_enabled_state_service, (void*)1);
#endif
}
if (ret >= 0) {
diff --git a/adb/set_verity_enable_state_service.c b/adb/set_verity_enable_state_service.c
new file mode 100644
index 0000000..1e22149
--- /dev/null
+++ b/adb/set_verity_enable_state_service.c
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2014 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 "sysdeps.h"
+
+#define TRACE_TAG TRACE_ADB
+#include "adb.h"
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <inttypes.h>
+
+#include "cutils/properties.h"
+#include "ext4_sb.h"
+#include <fs_mgr.h>
+
+#define FSTAB_PREFIX "/fstab."
+struct fstab *fstab;
+
+__attribute__((__format__(printf, 2, 3))) __nonnull((2))
+static void write_console(int fd, const char* format, ...)
+{
+ char buffer[256];
+ va_list args;
+ va_start (args, format);
+ vsnprintf (buffer, sizeof(buffer), format, args);
+ va_end (args);
+
+ adb_write(fd, buffer, strnlen(buffer, sizeof(buffer)));
+}
+
+static int get_target_device_size(int fd, const char *blk_device,
+ uint64_t *device_size)
+{
+ int data_device;
+ struct ext4_super_block sb;
+ struct fs_info info;
+
+ info.len = 0; /* Only len is set to 0 to ask the device for real size. */
+
+ data_device = adb_open(blk_device, O_RDONLY | O_CLOEXEC);
+ if (data_device < 0) {
+ write_console(fd, "Error opening block device (%s)\n", strerror(errno));
+ return -1;
+ }
+
+ if (lseek64(data_device, 1024, SEEK_SET) < 0) {
+ write_console(fd, "Error seeking to superblock\n");
+ adb_close(data_device);
+ return -1;
+ }
+
+ if (adb_read(data_device, &sb, sizeof(sb)) != sizeof(sb)) {
+ write_console(fd, "Error reading superblock\n");
+ adb_close(data_device);
+ return -1;
+ }
+
+ ext4_parse_sb(&sb, &info);
+ *device_size = info.len;
+
+ adb_close(data_device);
+ return 0;
+}
+
+/* Turn verity on/off */
+static int set_verity_enabled_state(int fd, const char *block_device,
+ const char* mount_point, bool enable)
+{
+ uint32_t magic_number;
+ const uint32_t new_magic = enable ? VERITY_METADATA_MAGIC_NUMBER
+ : VERITY_METADATA_MAGIC_DISABLE;
+ uint64_t device_length;
+ int device;
+ int retval = -1;
+
+ device = adb_open(block_device, O_RDWR | O_CLOEXEC);
+ if (device == -1) {
+ write_console(fd, "Could not open block device %s (%s).\n",
+ block_device, strerror(errno));
+ write_console(fd, "Maybe run adb remount?\n");
+ goto errout;
+ }
+
+ // find the start of the verity metadata
+ if (get_target_device_size(fd, (char*)block_device, &device_length) < 0) {
+ write_console(fd, "Could not get target device size.\n");
+ goto errout;
+ }
+
+ if (lseek64(device, device_length, SEEK_SET) < 0) {
+ write_console(fd,
+ "Could not seek to start of verity metadata block.\n");
+ goto errout;
+ }
+
+ // check the magic number
+ if (adb_read(device, &magic_number, sizeof(magic_number))
+ != sizeof(magic_number)) {
+ write_console(fd, "Couldn't read magic number!\n");
+ goto errout;
+ }
+
+ if (!enable && magic_number == VERITY_METADATA_MAGIC_DISABLE) {
+ write_console(fd, "Verity already disabled on %s\n", mount_point);
+ goto errout;
+ }
+
+ if (enable && magic_number == VERITY_METADATA_MAGIC_NUMBER) {
+ write_console(fd, "Verity already enabled on %s\n", mount_point);
+ goto errout;
+ }
+
+ if (magic_number != VERITY_METADATA_MAGIC_NUMBER
+ && magic_number != VERITY_METADATA_MAGIC_DISABLE) {
+ write_console(fd,
+ "Couldn't find verity metadata at offset %"PRIu64"!\n",
+ device_length);
+ goto errout;
+ }
+
+ if (lseek64(device, device_length, SEEK_SET) < 0) {
+ write_console(fd,
+ "Could not seek to start of verity metadata block.\n");
+ goto errout;
+ }
+
+ if (adb_write(device, &new_magic, sizeof(new_magic)) != sizeof(new_magic)) {
+ write_console(fd, "Could not set verity %s flag on device %s with error %s\n",
+ enable ? "enabled" : "disabled",
+ block_device,
+ strerror(errno));
+ goto errout;
+ }
+
+ write_console(fd, "Verity %s on %s\n",
+ enable ? "enabled" : "disabled",
+ mount_point);
+ retval = 0;
+errout:
+ if (device != -1)
+ adb_close(device);
+ return retval;
+}
+
+void set_verity_enabled_state_service(int fd, void* cookie)
+{
+ bool enable = (cookie != NULL);
+#ifdef ALLOW_ADBD_DISABLE_VERITY
+ char fstab_filename[PROPERTY_VALUE_MAX + sizeof(FSTAB_PREFIX)];
+ char propbuf[PROPERTY_VALUE_MAX];
+ int i;
+ bool any_changed = false;
+
+ property_get("ro.secure", propbuf, "0");
+ if (strcmp(propbuf, "1")) {
+ write_console(fd, "verity not enabled - ENG build\n");
+ goto errout;
+ }
+
+ property_get("ro.debuggable", propbuf, "0");
+ if (strcmp(propbuf, "1")) {
+ write_console(fd, "verity cannot be disabled/enabled - USER build\n");
+ goto errout;
+ }
+
+ property_get("ro.hardware", propbuf, "");
+ snprintf(fstab_filename, sizeof(fstab_filename), FSTAB_PREFIX"%s", propbuf);
+
+ fstab = fs_mgr_read_fstab(fstab_filename);
+ if (!fstab) {
+ write_console(fd, "Failed to open %s\nMaybe run adb root?\n",
+ fstab_filename);
+ goto errout;
+ }
+
+ if (enable && make_system_and_vendor_block_devices_writable(fd)) {
+ goto errout;
+ }
+
+ /* Loop through entries looking for ones that vold manages */
+ for (i = 0; i < fstab->num_entries; i++) {
+ if(fs_mgr_is_verified(&fstab->recs[i])) {
+ if (!set_verity_enabled_state(fd, fstab->recs[i].blk_device,
+ fstab->recs[i].mount_point, enable)) {
+ any_changed = true;
+ }
+ }
+ }
+
+ if (any_changed) {
+ write_console(fd,
+ "Now reboot your device for settings to take effect\n");
+ }
+#else
+ write_console(fd, "%s-verity only works for userdebug builds\n",
+ enable ? "enable" : "disable");
+#endif
+
+errout:
+ adb_close(fd);
+}
diff --git a/adb/sysdeps.h b/adb/sysdeps.h
index cc1f839..8d63d14 100644
--- a/adb/sysdeps.h
+++ b/adb/sysdeps.h
@@ -77,6 +77,11 @@
return 0;
}
+static __inline__ unsigned long adb_thread_id()
+{
+ return GetCurrentThreadId();
+}
+
static __inline__ void close_on_exec(int fd)
{
/* nothing really */
@@ -516,6 +521,12 @@
{
return strtok_r(str, delim, saveptr);
}
+
+static __inline__ unsigned long adb_thread_id()
+{
+ return (unsigned long)pthread_self();
+}
+
#undef strtok_r
#define strtok_r ___xxx_strtok_r
diff --git a/adb/sysdeps_win32.c b/adb/sysdeps_win32.c
index b082c6d..e69ec2b 100644
--- a/adb/sysdeps_win32.c
+++ b/adb/sysdeps_win32.c
@@ -2,6 +2,7 @@
#include <winsock2.h>
#include <windows.h>
#include <stdio.h>
+#include <stdlib.h>
#include <errno.h>
#define TRACE_TAG TRACE_SYSDEPS
#include "adb.h"
diff --git a/adb/transport.c b/adb/transport.c
index f35880c..7db6a47 100644
--- a/adb/transport.c
+++ b/adb/transport.c
@@ -629,7 +629,7 @@
fatal_errno("cannot open transport socketpair");
}
- D("transport: %s (%d,%d) starting\n", t->serial, s[0], s[1]);
+ D("transport: %s socketpair: (%d,%d) starting", t->serial, s[0], s[1]);
t->transport_socket = s[0];
t->fd = s[1];
@@ -673,6 +673,7 @@
if(adb_socketpair(s)){
fatal_errno("cannot open transport registration socketpair");
}
+ D("socketpair: (%d,%d)", s[0], s[1]);
transport_registration_send = s[0];
transport_registration_recv = s[1];
diff --git a/adb/usb_linux.c b/adb/usb_linux.c
index f16bdd0..7d13a5d 100644
--- a/adb/usb_linux.c
+++ b/adb/usb_linux.c
@@ -237,8 +237,20 @@
// looks like ADB...
ep1 = (struct usb_endpoint_descriptor *)bufptr;
bufptr += USB_DT_ENDPOINT_SIZE;
+ // For USB 3.0 SuperSpeed devices, skip potential
+ // USB 3.0 SuperSpeed Endpoint Companion descriptor
+ if (bufptr+2 <= devdesc + desclength &&
+ bufptr[0] == USB_DT_SS_EP_COMP_SIZE &&
+ bufptr[1] == USB_DT_SS_ENDPOINT_COMP) {
+ bufptr += USB_DT_SS_EP_COMP_SIZE;
+ }
ep2 = (struct usb_endpoint_descriptor *)bufptr;
bufptr += USB_DT_ENDPOINT_SIZE;
+ if (bufptr+2 <= devdesc + desclength &&
+ bufptr[0] == USB_DT_SS_EP_COMP_SIZE &&
+ bufptr[1] == USB_DT_SS_ENDPOINT_COMP) {
+ bufptr += USB_DT_SS_EP_COMP_SIZE;
+ }
if (bufptr > devdesc + desclength ||
ep1->bLength != USB_DT_ENDPOINT_SIZE ||
diff --git a/adb/usb_linux_client.c b/adb/usb_linux_client.c
index 8426e0e..fd566f4 100644
--- a/adb/usb_linux_client.c
+++ b/adb/usb_linux_client.c
@@ -33,6 +33,7 @@
#define MAX_PACKET_SIZE_FS 64
#define MAX_PACKET_SIZE_HS 512
+#define MAX_PACKET_SIZE_SS 1024
#define cpu_to_le16(x) htole16(x)
#define cpu_to_le32(x) htole32(x)
@@ -55,71 +56,85 @@
int bulk_in; /* "in" from the host's perspective => sink for adbd */
};
-static const struct {
- struct usb_functionfs_descs_head header;
- struct {
- struct usb_interface_descriptor intf;
- struct usb_endpoint_descriptor_no_audio source;
- struct usb_endpoint_descriptor_no_audio sink;
- } __attribute__((packed)) fs_descs, hs_descs;
-} __attribute__((packed)) descriptors = {
- .header = {
- .magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC),
- .length = cpu_to_le32(sizeof(descriptors)),
- .fs_count = 3,
- .hs_count = 3,
+struct func_desc {
+ struct usb_interface_descriptor intf;
+ struct usb_endpoint_descriptor_no_audio source;
+ struct usb_endpoint_descriptor_no_audio sink;
+} __attribute__((packed));
+
+struct desc_v1 {
+ struct usb_functionfs_descs_head_v1 {
+ __le32 magic;
+ __le32 length;
+ __le32 fs_count;
+ __le32 hs_count;
+ } __attribute__((packed)) header;
+ struct func_desc fs_descs, hs_descs;
+} __attribute__((packed));
+
+struct desc_v2 {
+ struct usb_functionfs_descs_head_v2 {
+ __le32 magic;
+ __le32 length;
+ __le32 flags;
+ __le32 fs_count;
+ __le32 hs_count;
+ __le32 ss_count;
+ } __attribute__((packed)) header;
+ struct func_desc fs_descs, hs_descs;
+} __attribute__((packed));
+
+struct func_desc fs_descriptors = {
+ .intf = {
+ .bLength = sizeof(fs_descriptors.intf),
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bInterfaceNumber = 0,
+ .bNumEndpoints = 2,
+ .bInterfaceClass = ADB_CLASS,
+ .bInterfaceSubClass = ADB_SUBCLASS,
+ .bInterfaceProtocol = ADB_PROTOCOL,
+ .iInterface = 1, /* first string from the provided table */
},
- .fs_descs = {
- .intf = {
- .bLength = sizeof(descriptors.fs_descs.intf),
- .bDescriptorType = USB_DT_INTERFACE,
- .bInterfaceNumber = 0,
- .bNumEndpoints = 2,
- .bInterfaceClass = ADB_CLASS,
- .bInterfaceSubClass = ADB_SUBCLASS,
- .bInterfaceProtocol = ADB_PROTOCOL,
- .iInterface = 1, /* first string from the provided table */
- },
- .source = {
- .bLength = sizeof(descriptors.fs_descs.source),
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = 1 | USB_DIR_OUT,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = MAX_PACKET_SIZE_FS,
- },
- .sink = {
- .bLength = sizeof(descriptors.fs_descs.sink),
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = 2 | USB_DIR_IN,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = MAX_PACKET_SIZE_FS,
- },
+ .source = {
+ .bLength = sizeof(fs_descriptors.source),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = 1 | USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = MAX_PACKET_SIZE_FS,
},
- .hs_descs = {
- .intf = {
- .bLength = sizeof(descriptors.hs_descs.intf),
- .bDescriptorType = USB_DT_INTERFACE,
- .bInterfaceNumber = 0,
- .bNumEndpoints = 2,
- .bInterfaceClass = ADB_CLASS,
- .bInterfaceSubClass = ADB_SUBCLASS,
- .bInterfaceProtocol = ADB_PROTOCOL,
- .iInterface = 1, /* first string from the provided table */
- },
- .source = {
- .bLength = sizeof(descriptors.hs_descs.source),
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = 1 | USB_DIR_OUT,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = MAX_PACKET_SIZE_HS,
- },
- .sink = {
- .bLength = sizeof(descriptors.hs_descs.sink),
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = 2 | USB_DIR_IN,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = MAX_PACKET_SIZE_HS,
- },
+ .sink = {
+ .bLength = sizeof(fs_descriptors.sink),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = 2 | USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = MAX_PACKET_SIZE_FS,
+ },
+};
+
+struct func_desc hs_descriptors = {
+ .intf = {
+ .bLength = sizeof(hs_descriptors.intf),
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bInterfaceNumber = 0,
+ .bNumEndpoints = 2,
+ .bInterfaceClass = ADB_CLASS,
+ .bInterfaceSubClass = ADB_SUBCLASS,
+ .bInterfaceProtocol = ADB_PROTOCOL,
+ .iInterface = 1, /* first string from the provided table */
+ },
+ .source = {
+ .bLength = sizeof(hs_descriptors.source),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = 1 | USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = MAX_PACKET_SIZE_HS,
+ },
+ .sink = {
+ .bLength = sizeof(hs_descriptors.sink),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = 2 | USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = MAX_PACKET_SIZE_HS,
},
};
@@ -263,6 +278,17 @@
static void init_functionfs(struct usb_handle *h)
{
ssize_t ret;
+ struct desc_v1 v1_descriptor;
+ struct desc_v2 v2_descriptor;
+
+ v2_descriptor.header.magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC_V2);
+ v2_descriptor.header.length = cpu_to_le32(sizeof(v2_descriptor));
+ v2_descriptor.header.flags = FUNCTIONFS_HAS_FS_DESC | FUNCTIONFS_HAS_HS_DESC;
+ v2_descriptor.header.fs_count = 3;
+ v2_descriptor.header.hs_count = 3;
+ v2_descriptor.header.ss_count = 0;
+ v2_descriptor.fs_descs = fs_descriptors;
+ v2_descriptor.hs_descs = hs_descriptors;
if (h->control < 0) { // might have already done this before
D("OPENING %s\n", USB_FFS_ADB_EP0);
@@ -272,10 +298,20 @@
goto err;
}
- ret = adb_write(h->control, &descriptors, sizeof(descriptors));
+ ret = adb_write(h->control, &v2_descriptor, sizeof(v2_descriptor));
if (ret < 0) {
- D("[ %s: write descriptors failed: errno=%d ]\n", USB_FFS_ADB_EP0, errno);
- goto err;
+ v1_descriptor.header.magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC);
+ v1_descriptor.header.length = cpu_to_le32(sizeof(v1_descriptor));
+ v1_descriptor.header.fs_count = 3;
+ v1_descriptor.header.hs_count = 3;
+ v1_descriptor.fs_descs = fs_descriptors;
+ v1_descriptor.hs_descs = hs_descriptors;
+ D("[ %s: Switching to V1_descriptor format errno=%d ]\n", USB_FFS_ADB_EP0, errno);
+ ret = adb_write(h->control, &v1_descriptor, sizeof(v1_descriptor));
+ if (ret < 0) {
+ D("[ %s: write descriptors failed: errno=%d ]\n", USB_FFS_ADB_EP0, errno);
+ goto err;
+ }
}
ret = adb_write(h->control, &strings, sizeof(strings));
diff --git a/adb/usb_windows.c b/adb/usb_windows.c
index b7ad913..a2d7226 100644
--- a/adb/usb_windows.c
+++ b/adb/usb_windows.c
@@ -21,6 +21,7 @@
#include <usb100.h>
#include <adb_api.h>
#include <stdio.h>
+#include <stdlib.h>
#include "sysdeps.h"
diff --git a/fastboot/fastboot_protocol.txt b/fastboot/fastboot_protocol.txt
index 2248992..37b1959 100644
--- a/fastboot/fastboot_protocol.txt
+++ b/fastboot/fastboot_protocol.txt
@@ -12,8 +12,8 @@
------------------
* Two bulk endpoints (in, out) are required
-* Max packet size must be 64 bytes for full-speed and 512 bytes for
- high-speed USB
+* Max packet size must be 64 bytes for full-speed, 512 bytes for
+ high-speed and 1024 bytes for Super Speed USB.
* The protocol is entirely host-driven and synchronous (unlike the
multi-channel, bi-directional, asynchronous ADB protocol)
diff --git a/fastboot/protocol.c b/fastboot/protocol.c
index 84e9837..10a84c1 100644
--- a/fastboot/protocol.c
+++ b/fastboot/protocol.c
@@ -216,7 +216,7 @@
}
}
-#define USB_BUF_SIZE 512
+#define USB_BUF_SIZE 1024
static char usb_buf[USB_BUF_SIZE];
static int usb_buf_len;
diff --git a/fastboot/usb_linux.c b/fastboot/usb_linux.c
index fabbd51..022f364 100644
--- a/fastboot/usb_linux.c
+++ b/fastboot/usb_linux.c
@@ -223,6 +223,13 @@
} else {
out = ept->bEndpointAddress;
}
+
+ // For USB 3.0 devices skip the SS Endpoint Companion descriptor
+ if (check((struct usb_descriptor_hdr *)ptr, len,
+ USB_DT_SS_ENDPOINT_COMP, USB_DT_SS_EP_COMP_SIZE) == 0) {
+ len -= USB_DT_SS_EP_COMP_SIZE;
+ ptr += USB_DT_SS_EP_COMP_SIZE;
+ }
}
info.has_bulk_in = (in != -1);
diff --git a/fastboot/usb_windows.c b/fastboot/usb_windows.c
index 0d13863..a09610f 100644
--- a/fastboot/usb_windows.c
+++ b/fastboot/usb_windows.c
@@ -32,6 +32,7 @@
#include <usb100.h>
#include <adb_api.h>
#include <stdio.h>
+#include <stdlib.h>
#include "usb.h"
diff --git a/fastbootd/usb_linux_client.c b/fastbootd/usb_linux_client.c
index 64420e9..2c678b9 100644
--- a/fastbootd/usb_linux_client.c
+++ b/fastbootd/usb_linux_client.c
@@ -69,71 +69,85 @@
struct transport_handle handle;
};
-static const struct {
- struct usb_functionfs_descs_head header;
- struct {
- struct usb_interface_descriptor intf;
- struct usb_endpoint_descriptor_no_audio source;
- struct usb_endpoint_descriptor_no_audio sink;
- } __attribute__((packed)) fs_descs, hs_descs;
-} __attribute__((packed)) descriptors = {
- .header = {
- .magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC),
- .length = cpu_to_le32(sizeof(descriptors)),
- .fs_count = 3,
- .hs_count = 3,
+struct func_desc {
+ struct usb_interface_descriptor intf;
+ struct usb_endpoint_descriptor_no_audio source;
+ struct usb_endpoint_descriptor_no_audio sink;
+} __attribute__((packed));
+
+struct desc_v1 {
+ struct usb_functionfs_descs_head_v1 {
+ __le32 magic;
+ __le32 length;
+ __le32 fs_count;
+ __le32 hs_count;
+ } __attribute__((packed)) header;
+ struct func_desc fs_descs, hs_descs;
+} __attribute__((packed));
+
+struct desc_v2 {
+ struct usb_functionfs_descs_head_v2 {
+ __le32 magic;
+ __le32 length;
+ __le32 flags;
+ __le32 fs_count;
+ __le32 hs_count;
+ __le32 ss_count;
+ } __attribute__((packed)) header;
+ struct func_desc fs_descs, hs_descs;
+} __attribute__((packed));
+
+struct func_desc fs_descriptors = {
+ .intf = {
+ .bLength = sizeof(fs_descriptors.intf),
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bInterfaceNumber = 0,
+ .bNumEndpoints = 2,
+ .bInterfaceClass = FASTBOOT_CLASS,
+ .bInterfaceSubClass = FASTBOOT_SUBCLASS,
+ .bInterfaceProtocol = FASTBOOT_PROTOCOL,
+ .iInterface = 1, /* first string from the provided table */
},
- .fs_descs = {
- .intf = {
- .bLength = sizeof(descriptors.fs_descs.intf),
- .bDescriptorType = USB_DT_INTERFACE,
- .bInterfaceNumber = 0,
- .bNumEndpoints = 2,
- .bInterfaceClass = FASTBOOT_CLASS,
- .bInterfaceSubClass = FASTBOOT_SUBCLASS,
- .bInterfaceProtocol = FASTBOOT_PROTOCOL,
- .iInterface = 1, /* first string from the provided table */
- },
- .source = {
- .bLength = sizeof(descriptors.fs_descs.source),
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = 1 | USB_DIR_OUT,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = MAX_PACKET_SIZE_FS,
- },
- .sink = {
- .bLength = sizeof(descriptors.fs_descs.sink),
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = 2 | USB_DIR_IN,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = MAX_PACKET_SIZE_FS,
- },
+ .source = {
+ .bLength = sizeof(fs_descriptors.source),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = 1 | USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = MAX_PACKET_SIZE_FS,
},
- .hs_descs = {
- .intf = {
- .bLength = sizeof(descriptors.hs_descs.intf),
- .bDescriptorType = USB_DT_INTERFACE,
- .bInterfaceNumber = 0,
- .bNumEndpoints = 2,
- .bInterfaceClass = FASTBOOT_CLASS,
- .bInterfaceSubClass = FASTBOOT_SUBCLASS,
- .bInterfaceProtocol = FASTBOOT_PROTOCOL,
- .iInterface = 1, /* first string from the provided table */
- },
- .source = {
- .bLength = sizeof(descriptors.hs_descs.source),
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = 1 | USB_DIR_OUT,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = MAX_PACKET_SIZE_HS,
- },
- .sink = {
- .bLength = sizeof(descriptors.hs_descs.sink),
- .bDescriptorType = USB_DT_ENDPOINT,
- .bEndpointAddress = 2 | USB_DIR_IN,
- .bmAttributes = USB_ENDPOINT_XFER_BULK,
- .wMaxPacketSize = MAX_PACKET_SIZE_HS,
- },
+ .sink = {
+ .bLength = sizeof(fs_descriptors.sink),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = 2 | USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = MAX_PACKET_SIZE_FS,
+ },
+};
+
+struct func_desc hs_descriptors = {
+ .intf = {
+ .bLength = sizeof(hs_descriptors.intf),
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bInterfaceNumber = 0,
+ .bNumEndpoints = 2,
+ .bInterfaceClass = FASTBOOT_CLASS,
+ .bInterfaceSubClass = FASTBOOT_SUBCLASS,
+ .bInterfaceProtocol = FASTBOOT_PROTOCOL,
+ .iInterface = 1, /* first string from the provided table */
+ },
+ .source = {
+ .bLength = sizeof(hs_descriptors.source),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = 1 | USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = MAX_PACKET_SIZE_HS,
+ },
+ .sink = {
+ .bLength = sizeof(hs_descriptors.sink),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ .bEndpointAddress = 2 | USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .wMaxPacketSize = MAX_PACKET_SIZE_HS,
},
};
@@ -161,6 +175,17 @@
static int init_functionfs(struct usb_transport *usb_transport)
{
ssize_t ret;
+ struct desc_v1 v1_descriptor;
+ struct desc_v2 v2_descriptor;
+
+ v2_descriptor.header.magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC_V2);
+ v2_descriptor.header.length = cpu_to_le32(sizeof(v2_descriptor));
+ v2_descriptor.header.flags = FUNCTIONFS_HAS_FS_DESC | FUNCTIONFS_HAS_HS_DESC;
+ v2_descriptor.header.fs_count = 3;
+ v2_descriptor.header.hs_count = 3;
+ v2_descriptor.header.ss_count = 0;
+ v2_descriptor.fs_descs = fs_descriptors;
+ v2_descriptor.hs_descs = hs_descriptors;
D(VERBOSE, "OPENING %s", USB_FFS_FASTBOOT_EP0);
usb_transport->control = open(USB_FFS_FASTBOOT_EP0, O_RDWR);
@@ -169,10 +194,20 @@
goto err;
}
- ret = write(usb_transport->control, &descriptors, sizeof(descriptors));
+ ret = write(usb_transport->control, &v2_descriptor, sizeof(v2_descriptor));
if (ret < 0) {
- D(ERR, "[ %s: write descriptors failed: errno=%d ]", USB_FFS_FASTBOOT_EP0, errno);
- goto err;
+ v1_descriptor.header.magic = cpu_to_le32(FUNCTIONFS_DESCRIPTORS_MAGIC);
+ v1_descriptor.header.length = cpu_to_le32(sizeof(v1_descriptor));
+ v1_descriptor.header.fs_count = 3;
+ v1_descriptor.header.hs_count = 3;
+ v1_descriptor.fs_descs = fs_descriptors;
+ v1_descriptor.hs_descs = hs_descriptors;
+ D(ERR, "[ %s: Switching to V1_descriptor format errno=%d ]\n", USB_FFS_FASTBOOT_EP0, errno);
+ ret = write(usb_transport->control, &v1_descriptor, sizeof(v1_descriptor));
+ if (ret < 0) {
+ D(ERR, "[ %s: write descriptors failed: errno=%d ]", USB_FFS_FASTBOOT_EP0, errno);
+ goto err;
+ }
}
ret = write(usb_transport->control, &strings, sizeof(strings));
diff --git a/fs_mgr/Android.mk b/fs_mgr/Android.mk
index 7cffc37..61bf1ee 100644
--- a/fs_mgr/Android.mk
+++ b/fs_mgr/Android.mk
@@ -13,6 +13,10 @@
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
LOCAL_CFLAGS := -Werror
+ifneq (,$(filter userdebug,$(TARGET_BUILD_VARIANT)))
+LOCAL_CFLAGS += -DALLOW_ADBD_DISABLE_VERITY=1
+endif
+
include $(BUILD_STATIC_LIBRARY)
diff --git a/fs_mgr/fs_mgr.c b/fs_mgr/fs_mgr.c
index 91e6c33..40878c1 100644
--- a/fs_mgr/fs_mgr.c
+++ b/fs_mgr/fs_mgr.c
@@ -245,6 +245,16 @@
return strcmp(value, "1") ? 0 : 1;
}
+static int device_is_secure() {
+ int ret = -1;
+ char value[PROP_VALUE_MAX];
+ ret = __system_property_get("ro.secure", value);
+ /* If error, we want to fail secure */
+ if (ret < 0)
+ return 1;
+ return strcmp(value, "0") ? 1 : 0;
+}
+
/*
* Tries to mount any of the consecutive fstab entries that match
* the mountpoint of the one given by fstab->recs[start_idx].
@@ -350,9 +360,11 @@
wait_for_file(fstab->recs[i].blk_device, WAIT_TIMEOUT);
}
- if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) &&
- !device_is_debuggable()) {
- if (fs_mgr_setup_verity(&fstab->recs[i]) < 0) {
+ if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) && device_is_secure()) {
+ int rc = fs_mgr_setup_verity(&fstab->recs[i]);
+ if (device_is_debuggable() && rc == FS_MGR_SETUP_VERITY_DISABLED) {
+ INFO("Verity disabled");
+ } else if (rc != FS_MGR_SETUP_VERITY_SUCCESS) {
ERROR("Could not set up verified partition, skipping!\n");
continue;
}
@@ -467,9 +479,11 @@
fstab->recs[i].mount_point);
}
- if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) &&
- !device_is_debuggable()) {
- if (fs_mgr_setup_verity(&fstab->recs[i]) < 0) {
+ if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) && device_is_secure()) {
+ int rc = fs_mgr_setup_verity(&fstab->recs[i]);
+ if (device_is_debuggable() && rc == FS_MGR_SETUP_VERITY_DISABLED) {
+ INFO("Verity disabled");
+ } else if (rc != FS_MGR_SETUP_VERITY_SUCCESS) {
ERROR("Could not set up verified partition, skipping!\n");
continue;
}
diff --git a/fs_mgr/fs_mgr_fstab.c b/fs_mgr/fs_mgr_fstab.c
index 3f84179..ab8f128 100644
--- a/fs_mgr/fs_mgr_fstab.c
+++ b/fs_mgr/fs_mgr_fstab.c
@@ -418,6 +418,11 @@
return fstab->fs_mgr_flags & MF_NONREMOVABLE;
}
+int fs_mgr_is_verified(struct fstab_rec *fstab)
+{
+ return fstab->fs_mgr_flags & MF_VERIFY;
+}
+
int fs_mgr_is_encryptable(struct fstab_rec *fstab)
{
return fstab->fs_mgr_flags & (MF_CRYPT | MF_FORCECRYPT);
diff --git a/fs_mgr/fs_mgr_priv_verity.h b/fs_mgr/fs_mgr_priv_verity.h
index 6193784..f90e596 100644
--- a/fs_mgr/fs_mgr_priv_verity.h
+++ b/fs_mgr/fs_mgr_priv_verity.h
@@ -14,4 +14,7 @@
* limitations under the License.
*/
-int fs_mgr_setup_verity(struct fstab_rec *fstab);
\ No newline at end of file
+#define FS_MGR_SETUP_VERITY_DISABLED -2
+#define FS_MGR_SETUP_VERITY_FAIL -1
+#define FS_MGR_SETUP_VERITY_SUCCESS 0
+int fs_mgr_setup_verity(struct fstab_rec *fstab);
diff --git a/fs_mgr/fs_mgr_verity.c b/fs_mgr/fs_mgr_verity.c
index 01f7844..39f96a7 100644
--- a/fs_mgr/fs_mgr_verity.c
+++ b/fs_mgr/fs_mgr_verity.c
@@ -43,7 +43,6 @@
#include "fs_mgr_priv_verity.h"
#define VERITY_METADATA_SIZE 32768
-#define VERITY_METADATA_MAGIC_NUMBER 0xb001b001
#define VERITY_TABLE_RSA_KEY "/verity_key"
extern struct fs_info info;
@@ -157,7 +156,9 @@
uint64_t device_length;
int protocol_version;
FILE *device;
- int retval = -1;
+ int retval = FS_MGR_SETUP_VERITY_FAIL;
+ *signature = 0;
+ *table = 0;
device = fopen(block_device, "r");
if (!device) {
@@ -180,8 +181,18 @@
ERROR("Couldn't read magic number!\n");
goto out;
}
+
+#ifdef ALLOW_ADBD_DISABLE_VERITY
+ if (magic_number == VERITY_METADATA_MAGIC_DISABLE) {
+ retval = FS_MGR_SETUP_VERITY_DISABLED;
+ INFO("Attempt to cleanly disable verity - only works in USERDEBUG");
+ goto out;
+ }
+#endif
+
if (magic_number != VERITY_METADATA_MAGIC_NUMBER) {
- ERROR("Couldn't find verity metadata at offset %"PRIu64"!\n", device_length);
+ ERROR("Couldn't find verity metadata at offset %"PRIu64"!\n",
+ device_length);
goto out;
}
@@ -203,14 +214,12 @@
}
if (!fread(*signature, RSANUMBYTES, 1, device)) {
ERROR("Couldn't read signature from verity metadata!\n");
- free(*signature);
goto out;
}
// get the size of the table
if (!fread(&table_length, sizeof(int), 1, device)) {
ERROR("Couldn't get the size of the verity table from metadata!\n");
- free(*signature);
goto out;
}
@@ -223,16 +232,22 @@
}
if (!fgets(*table, table_length, device)) {
ERROR("Couldn't read the verity table from metadata!\n");
- free(*table);
- free(*signature);
goto out;
}
- retval = 0;
+ retval = FS_MGR_SETUP_VERITY_SUCCESS;
out:
if (device)
fclose(device);
+
+ if (retval != FS_MGR_SETUP_VERITY_SUCCESS) {
+ free(*table);
+ free(*signature);
+ *table = 0;
+ *signature = 0;
+ }
+
return retval;
}
@@ -360,10 +375,11 @@
int fs_mgr_setup_verity(struct fstab_rec *fstab) {
int retval = -1;
+ int fd = -1;
- char *verity_blk_name;
- char *verity_table;
- char *verity_table_signature;
+ char *verity_blk_name = 0;
+ char *verity_table = 0;
+ char *verity_table_signature = 0;
char buffer[DM_BUF_SIZE];
struct dm_ioctl *io = (struct dm_ioctl *) buffer;
@@ -380,11 +396,19 @@
return retval;
}
+ // read the verity block at the end of the block device
+ // send error code up the chain so we can detect attempts to disable verity
+ retval = read_verity_metadata(fstab->blk_device,
+ &verity_table_signature,
+ &verity_table);
+ if (retval < 0) {
+ goto out;
+ }
+
// get the device mapper fd
- int fd;
if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) {
ERROR("Error opening device mapper (%s)", strerror(errno));
- return retval;
+ goto out;;
}
// create the device
@@ -399,14 +423,6 @@
goto out;
}
- verity_table = verity_table_signature = NULL;
- // read the verity block at the end of the block device
- if (read_verity_metadata(fstab->blk_device,
- &verity_table_signature,
- &verity_table) < 0) {
- goto out;
- }
-
// verify the signature on the table
if (verify_table(verity_table_signature,
verity_table,
@@ -427,6 +443,7 @@
// assign the new verity block device as the block device
free(fstab->blk_device);
fstab->blk_device = verity_blk_name;
+ verity_blk_name = 0;
// make sure we've set everything up properly
if (test_access(fstab->blk_device) < 0) {
@@ -437,6 +454,13 @@
retval = set_verified_property(mount_point);
out:
- close(fd);
+ if (fd != -1) {
+ close(fd);
+ }
+
+ free (verity_table);
+ free (verity_table_signature);
+ free (verity_blk_name);
+
return retval;
}
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index 0c7eb20..5e2ff41 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -20,6 +20,13 @@
#include <stdint.h>
#include <linux/dm-ioctl.h>
+// Magic number at start of verity metadata
+#define VERITY_METADATA_MAGIC_NUMBER 0xb001b001
+
+// Replacement magic number at start of verity metadata to cleanly
+// turn verity off in userdebug builds.
+#define VERITY_METADATA_MAGIC_DISABLE 0x46464f56 // "VOFF"
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -74,6 +81,7 @@
struct fstab_rec *fs_mgr_get_entry_for_mount_point(struct fstab *fstab, const char *path);
int fs_mgr_is_voldmanaged(struct fstab_rec *fstab);
int fs_mgr_is_nonremovable(struct fstab_rec *fstab);
+int fs_mgr_is_verified(struct fstab_rec *fstab);
int fs_mgr_is_encryptable(struct fstab_rec *fstab);
int fs_mgr_is_noemulatedsd(struct fstab_rec *fstab);
int fs_mgr_swapon_all(struct fstab *fstab);
diff --git a/libpixelflinger/Android.mk b/libpixelflinger/Android.mk
index da9829d..f1bd522 100644
--- a/libpixelflinger/Android.mk
+++ b/libpixelflinger/Android.mk
@@ -36,6 +36,7 @@
ifeq ($(ARCH_ARM_HAVE_NEON),true)
PIXELFLINGER_SRC_FILES_arm += col32cb16blend_neon.S
+PIXELFLINGER_CFLAGS_arm += -D__ARM_HAVE_NEON
endif
PIXELFLINGER_SRC_FILES_arm64 := \
diff --git a/libpixelflinger/codeflinger/load_store.cpp b/libpixelflinger/codeflinger/load_store.cpp
index 0a46eaa..e5a1ae0 100644
--- a/libpixelflinger/codeflinger/load_store.cpp
+++ b/libpixelflinger/codeflinger/load_store.cpp
@@ -20,10 +20,6 @@
#include <cutils/log.h>
#include "GGLAssembler.h"
-#ifdef __ARM_ARCH__
-#include <machine/cpu-features.h>
-#endif
-
namespace android {
// ----------------------------------------------------------------------------
@@ -117,20 +113,6 @@
#endif
assert(h);
-#if __ARM_ARCH__ >= 7
- const int mask = (1<<maskLen)-1;
- if ((h == bits) && !l && (s != d.reg)) {
- MOV(AL, 0, d.reg, s); // component = packed;
- } else if ((h == bits) && l) {
- MOV(AL, 0, d.reg, reg_imm(s, LSR, l)); // component = packed >> l;
- } else if (!l && isValidImmediate(mask)) {
- AND(AL, 0, d.reg, s, imm(mask)); // component = packed & mask;
- } else if (!l && isValidImmediate(~mask)) {
- BIC(AL, 0, d.reg, s, imm(~mask)); // component = packed & mask;
- } else {
- UBFX(AL, d.reg, s, l, maskLen); // component = (packed & mask) >> l;
- }
-#else
if (h != bits) {
const int mask = ((1<<maskLen)-1) << l;
if (isValidImmediate(mask)) {
@@ -153,7 +135,6 @@
if (s != d.reg) {
MOV(AL, 0, d.reg, s);
}
-#endif
d.s = maskLen;
}
diff --git a/libpixelflinger/codeflinger/texturing.cpp b/libpixelflinger/codeflinger/texturing.cpp
index 81950bf..29a3742 100644
--- a/libpixelflinger/codeflinger/texturing.cpp
+++ b/libpixelflinger/codeflinger/texturing.cpp
@@ -25,10 +25,6 @@
#include "GGLAssembler.h"
-#ifdef __ARM_ARCH__
-#include <machine/cpu-features.h>
-#endif
-
namespace android {
// ---------------------------------------------------------------------------
@@ -888,106 +884,6 @@
load(txPtr, texel, 0);
}
-#if __ARM_ARCH__ >= 6
-// ARMv6 version, using UXTB16, and scheduled for Cortex-A8 pipeline
-void GGLAssembler::filter32(
- const fragment_parts_t& parts,
- pixel_t& texel, const texture_unit_t& tmu,
- int U, int V, pointer_t& txPtr,
- int FRAC_BITS)
-{
- const int adjust = FRAC_BITS*2 - 8;
- const int round = 0;
- const int prescale = 16 - adjust;
-
- Scratch scratches(registerFile());
-
- int pixel= scratches.obtain();
- int dh = scratches.obtain();
- int u = scratches.obtain();
- int k = scratches.obtain();
-
- int temp = scratches.obtain();
- int dl = scratches.obtain();
-
- int offsetrt = scratches.obtain();
- int offsetlb = scratches.obtain();
-
- int pixellb = offsetlb;
-
- // RB -> U * V
- CONTEXT_LOAD(offsetrt, generated_vars.rt);
- CONTEXT_LOAD(offsetlb, generated_vars.lb);
- if(!round) {
- MOV(AL, 0, U, reg_imm(U, LSL, prescale));
- }
- ADD(AL, 0, u, offsetrt, offsetlb);
-
- LDR(AL, pixel, txPtr.reg, reg_scale_pre(u));
- if (round) {
- SMULBB(AL, u, U, V);
- RSB(AL, 0, U, U, imm(1<<FRAC_BITS));
- } else {
- SMULWB(AL, u, U, V);
- RSB(AL, 0, U, U, imm(1<<(FRAC_BITS+prescale)));
- }
- UXTB16(AL, temp, pixel, 0);
- if (round) {
- ADD(AL, 0, u, u, imm(1<<(adjust-1)));
- MOV(AL, 0, u, reg_imm(u, LSR, adjust));
- }
- LDR(AL, pixellb, txPtr.reg, reg_scale_pre(offsetlb));
- MUL(AL, 0, dh, temp, u);
- UXTB16(AL, temp, pixel, 8);
- MUL(AL, 0, dl, temp, u);
- RSB(AL, 0, k, u, imm(0x100));
-
- // LB -> (1-U) * V
- if (round) {
- SMULBB(AL, u, U, V);
- } else {
- SMULWB(AL, u, U, V);
- }
- UXTB16(AL, temp, pixellb, 0);
- if (round) {
- ADD(AL, 0, u, u, imm(1<<(adjust-1)));
- MOV(AL, 0, u, reg_imm(u, LSR, adjust));
- }
- MLA(AL, 0, dh, temp, u, dh);
- UXTB16(AL, temp, pixellb, 8);
- MLA(AL, 0, dl, temp, u, dl);
- SUB(AL, 0, k, k, u);
-
- // LT -> (1-U)*(1-V)
- RSB(AL, 0, V, V, imm(1<<FRAC_BITS));
- LDR(AL, pixel, txPtr.reg);
- if (round) {
- SMULBB(AL, u, U, V);
- } else {
- SMULWB(AL, u, U, V);
- }
- UXTB16(AL, temp, pixel, 0);
- if (round) {
- ADD(AL, 0, u, u, imm(1<<(adjust-1)));
- MOV(AL, 0, u, reg_imm(u, LSR, adjust));
- }
- MLA(AL, 0, dh, temp, u, dh);
- UXTB16(AL, temp, pixel, 8);
- MLA(AL, 0, dl, temp, u, dl);
-
- // RT -> U*(1-V)
- LDR(AL, pixel, txPtr.reg, reg_scale_pre(offsetrt));
- SUB(AL, 0, u, k, u);
- UXTB16(AL, temp, pixel, 0);
- MLA(AL, 0, dh, temp, u, dh);
- UXTB16(AL, temp, pixel, 8);
- MLA(AL, 0, dl, temp, u, dl);
-
- UXTB16(AL, dh, dh, 8);
- UXTB16(AL, dl, dl, 8);
- ORR(AL, 0, texel.reg, dh, reg_imm(dl, LSL, 8));
-}
-#else
void GGLAssembler::filter32(
const fragment_parts_t& /*parts*/,
pixel_t& texel, const texture_unit_t& /*tmu*/,
@@ -1075,7 +971,6 @@
AND(AL, 0, dl, dl, reg_imm(mask, LSL, 8));
ORR(AL, 0, texel.reg, dh, dl);
}
-#endif
void GGLAssembler::build_texture_environment(
component_t& fragment,
diff --git a/libutils/Android.mk b/libutils/Android.mk
index e738c15..52de910 100644
--- a/libutils/Android.mk
+++ b/libutils/Android.mk
@@ -53,13 +53,6 @@
endif
endif
-host_commonLdlibs :=
-
-ifeq ($(TARGET_OS),linux)
-host_commonLdlibs += -lrt -ldl
-endif
-
-
# For the host
# =====================================================
include $(CLEAR_VARS)
@@ -93,9 +86,6 @@
endif
LOCAL_CFLAGS += -Werror
-LOCAL_C_INCLUDES += \
- external/zlib
-
LOCAL_STATIC_LIBRARIES := \
libcutils
diff --git a/libutils/SystemClock.cpp b/libutils/SystemClock.cpp
index dbad581..ac3dd98 100644
--- a/libutils/SystemClock.cpp
+++ b/libutils/SystemClock.cpp
@@ -68,7 +68,7 @@
*/
#define DEBUG_TIMESTAMP 0
-#if DEBUG_TIMESTAMP && defined(ARCH_ARM)
+#if DEBUG_TIMESTAMP && defined(__arm__)
static inline void checkTimeStamps(int64_t timestamp,
int64_t volatile *prevTimestampPtr,
int volatile *prevMethodPtr,
diff --git a/libziparchive/Android.mk b/libziparchive/Android.mk
index 9bc6e61..ba7b74d 100644
--- a/libziparchive/Android.mk
+++ b/libziparchive/Android.mk
@@ -16,7 +16,6 @@
LOCAL_PATH := $(call my-dir)
source_files := zip_archive.cc
-includes := external/zlib
include $(CLEAR_VARS)
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
@@ -25,16 +24,13 @@
LOCAL_STATIC_LIBRARIES := libz
LOCAL_SHARED_LIBRARIES := libutils
LOCAL_MODULE:= libziparchive
-LOCAL_C_INCLUDES += ${includes}
LOCAL_CFLAGS := -Werror
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-LOCAL_MODULE := libziparchive
LOCAL_CPP_EXTENSION := .cc
LOCAL_SRC_FILES := ${source_files}
-LOCAL_C_INCLUDES += ${includes}
LOCAL_STATIC_LIBRARIES := libz libutils
LOCAL_MODULE:= libziparchive-host
LOCAL_CFLAGS := -Werror
@@ -46,10 +42,8 @@
include $(CLEAR_VARS)
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
-LOCAL_MODULE := libziparchive
LOCAL_CPP_EXTENSION := .cc
LOCAL_SRC_FILES := ${source_files}
-LOCAL_C_INCLUDES += ${includes}
LOCAL_STATIC_LIBRARIES := libz libutils
LOCAL_SHARED_LIBRARIES := liblog
LOCAL_MODULE:= libziparchive-host
@@ -63,7 +57,7 @@
LOCAL_MODULE := ziparchive-tests
LOCAL_CPP_EXTENSION := .cc
LOCAL_CFLAGS := -Werror
-LOCAL_SRC_FILES := zip_archive_test.cc
+LOCAL_SRC_FILES := zip_archive_test.cc entry_name_utils_test.cc
LOCAL_SHARED_LIBRARIES := liblog
LOCAL_STATIC_LIBRARIES := libziparchive libz libutils
include $(BUILD_NATIVE_TEST)
@@ -75,7 +69,7 @@
LOCAL_CFLAGS += \
-Werror \
-Wno-unnamed-type-template-args
-LOCAL_SRC_FILES := zip_archive_test.cc
+LOCAL_SRC_FILES := zip_archive_test.cc entry_name_utils_test.cc
LOCAL_SHARED_LIBRARIES := libziparchive-host liblog
LOCAL_STATIC_LIBRARIES := \
libz \
diff --git a/libziparchive/entry_name_utils-inl.h b/libziparchive/entry_name_utils-inl.h
new file mode 100644
index 0000000..ddbc286
--- /dev/null
+++ b/libziparchive/entry_name_utils-inl.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2014 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 LIBZIPARCHIVE_ENTRY_NAME_UTILS_INL_H_
+#define LIBZIPARCHIVE_ENTRY_NAME_UTILS_INL_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+// Check if |length| bytes at |entry_name| constitute a valid entry name.
+// Entry names must be valid UTF-8 and must not contain '0'.
+inline bool IsValidEntryName(const uint8_t* entry_name, const size_t length) {
+ for (size_t i = 0; i < length; ++i) {
+ const uint8_t byte = entry_name[i];
+ if (byte == 0) {
+ return false;
+ } else if ((byte & 0x80) == 0) {
+ // Single byte sequence.
+ continue;
+ } else if ((byte & 0xc0) == 0x80 || (byte & 0xfe) == 0xfe) {
+ // Invalid sequence.
+ return false;
+ } else {
+ // 2-5 byte sequences.
+ for (uint8_t first = byte << 1; first & 0x80; first <<= 1) {
+ ++i;
+
+ // Missing continuation byte..
+ if (i == length) {
+ return false;
+ }
+
+ // Invalid continuation byte.
+ const uint8_t continuation_byte = entry_name[i];
+ if ((continuation_byte & 0xc0) != 0x80) {
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+
+#endif // LIBZIPARCHIVE_ENTRY_NAME_UTILS_INL_H_
diff --git a/libziparchive/entry_name_utils_test.cc b/libziparchive/entry_name_utils_test.cc
new file mode 100644
index 0000000..20715bb
--- /dev/null
+++ b/libziparchive/entry_name_utils_test.cc
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2014 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 "entry_name_utils-inl.h"
+
+#include <gtest/gtest.h>
+
+TEST(entry_name_utils, NullChars) {
+ // 'A', 'R', '\0', 'S', 'E'
+ const uint8_t zeroes[] = { 0x41, 0x52, 0x00, 0x53, 0x45 };
+ ASSERT_FALSE(IsValidEntryName(zeroes, sizeof(zeroes)));
+
+ const uint8_t zeroes_continuation_chars[] = { 0xc2, 0xa1, 0xc2, 0x00 };
+ ASSERT_FALSE(IsValidEntryName(zeroes_continuation_chars,
+ sizeof(zeroes_continuation_chars)));
+}
+
+TEST(entry_name_utils, InvalidSequence) {
+ // 0xfe is an invalid start byte
+ const uint8_t invalid[] = { 0x41, 0xfe };
+ ASSERT_FALSE(IsValidEntryName(invalid, sizeof(invalid)));
+
+ // 0x91 is an invalid start byte (it's a valid continuation byte).
+ const uint8_t invalid2[] = { 0x41, 0x91 };
+ ASSERT_FALSE(IsValidEntryName(invalid2, sizeof(invalid2)));
+}
+
+TEST(entry_name_utils, TruncatedContinuation) {
+ // Malayalam script with truncated bytes. There should be 2 bytes
+ // after 0xe0
+ const uint8_t truncated[] = { 0xe0, 0xb4, 0x85, 0xe0, 0xb4 };
+ ASSERT_FALSE(IsValidEntryName(truncated, sizeof(truncated)));
+
+ // 0xc2 is the start of a 2 byte sequence that we've subsequently
+ // dropped.
+ const uint8_t truncated2[] = { 0xc2, 0xc2, 0xa1 };
+ ASSERT_FALSE(IsValidEntryName(truncated2, sizeof(truncated2)));
+}
+
+TEST(entry_name_utils, BadContinuation) {
+ // 0x41 is an invalid continuation char, since it's MSBs
+ // aren't "10..." (are 01).
+ const uint8_t bad[] = { 0xc2, 0xa1, 0xc2, 0x41 };
+ ASSERT_FALSE(IsValidEntryName(bad, sizeof(bad)));
+
+ // 0x41 is an invalid continuation char, since it's MSBs
+ // aren't "10..." (are 11).
+ const uint8_t bad2[] = { 0xc2, 0xa1, 0xc2, 0xfe };
+ ASSERT_FALSE(IsValidEntryName(bad2, sizeof(bad2)));
+}
diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc
index 92150c3..b6fd0d2 100644
--- a/libziparchive/zip_archive.cc
+++ b/libziparchive/zip_archive.cc
@@ -33,8 +33,10 @@
#include <JNIHelp.h> // TEMP_FAILURE_RETRY may or may not be in unistd
+#include "entry_name_utils-inl.h"
#include "ziparchive/zip_archive.h"
+
// This is for windows. If we don't open a file in binary mode, weird
// things will happen.
#ifndef O_BINARY
@@ -641,9 +643,8 @@
const uint16_t comment_length = cdr->comment_length;
const uint8_t* file_name = ptr + sizeof(CentralDirectoryRecord);
- /* check that file name doesn't contain \0 character */
- if (memchr(file_name, 0, file_name_length) != NULL) {
- ALOGW("Zip: entry name can't contain \\0 character");
+ /* check that file name is valid UTF-8 and doesn't contain NUL (U+0000) characters */
+ if (!IsValidEntryName(file_name, file_name_length)) {
goto bail;
}
diff --git a/libzipfile/Android.mk b/libzipfile/Android.mk
index 12a2229..f054e15 100644
--- a/libzipfile/Android.mk
+++ b/libzipfile/Android.mk
@@ -7,13 +7,10 @@
centraldir.c \
zipfile.c
-LOCAL_STATIC_LIBRARIES := \
- libunz
+LOCAL_STATIC_LIBRARIES := libz
LOCAL_MODULE:= libzipfile
-LOCAL_C_INCLUDES += external/zlib
-
LOCAL_CFLAGS := -Werror
LOCAL_MULTILIB := both
@@ -27,13 +24,10 @@
centraldir.c \
zipfile.c
-LOCAL_STATIC_LIBRARIES := \
- libunz
+LOCAL_STATIC_LIBRARIES := libz
LOCAL_MODULE:= libzipfile
-LOCAL_C_INCLUDES += external/zlib
-
LOCAL_CFLAGS := -Werror
include $(BUILD_STATIC_LIBRARY)
@@ -45,12 +39,10 @@
LOCAL_SRC_FILES:= \
test_zipfile.c
-LOCAL_STATIC_LIBRARIES := libzipfile libunz
+LOCAL_STATIC_LIBRARIES := libzipfile libz
LOCAL_MODULE := test_zipfile
-LOCAL_C_INCLUDES += external/zlib
-
LOCAL_CFLAGS := -Werror
include $(BUILD_HOST_EXECUTABLE)
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index 6306f5c..79f2ebd 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -455,36 +455,31 @@
delete dev;
}
- dev = devices = new log_device_t("main", false, 'm');
- android::g_devCount = 1;
- if (android_name_to_log_id("system") == LOG_ID_SYSTEM) {
- dev->next = new log_device_t("system", false, 's');
- if (dev->next) {
- dev = dev->next;
- android::g_devCount++;
+ devices = dev = NULL;
+ android::g_devCount = 0;
+ needBinary = false;
+ for(int i = LOG_ID_MIN; i < LOG_ID_MAX; ++i) {
+ const char *name = android_log_id_to_name((log_id_t)i);
+ log_id_t log_id = android_name_to_log_id(name);
+
+ if (log_id != (log_id_t)i) {
+ continue;
}
- }
- if (android_name_to_log_id("radio") == LOG_ID_RADIO) {
- dev->next = new log_device_t("radio", false, 'r');
- if (dev->next) {
- dev = dev->next;
- android::g_devCount++;
+
+ bool binary = strcmp(name, "events") == 0;
+ log_device_t* d = new log_device_t(name, binary, *name);
+
+ if (dev) {
+ dev->next = d;
+ dev = d;
+ } else {
+ devices = dev = d;
}
- }
- if (android_name_to_log_id("events") == LOG_ID_EVENTS) {
- dev->next = new log_device_t("events", true, 'e');
- if (dev->next) {
- dev = dev->next;
- android::g_devCount++;
+ android::g_devCount++;
+ if (binary) {
needBinary = true;
}
}
- if (android_name_to_log_id("crash") == LOG_ID_CRASH) {
- dev->next = new log_device_t("crash", false, 'c');
- if (dev->next) {
- android::g_devCount++;
- }
- }
break;
}
diff --git a/logd/LogAudit.cpp b/logd/LogAudit.cpp
index ee2f32d..c7c0249 100644
--- a/logd/LogAudit.cpp
+++ b/logd/LogAudit.cpp
@@ -19,7 +19,6 @@
#include <limits.h>
#include <stdarg.h>
#include <stdlib.h>
-#include <sys/klog.h>
#include <sys/prctl.h>
#include <sys/uio.h>
#include <syslog.h>
@@ -33,21 +32,23 @@
'0' + (LOG_AUTH | (PRI)) % 10, \
'>'
-LogAudit::LogAudit(LogBuffer *buf, LogReader *reader, int fdDmsg)
+LogAudit::LogAudit(LogBuffer *buf, LogReader *reader, int fdDmesg)
: SocketListener(getLogSocket(), false)
, logbuf(buf)
, reader(reader)
- , fdDmesg(-1) {
+ , fdDmesg(fdDmesg)
+ , initialized(false) {
static const char auditd_message[] = { KMSG_PRIORITY(LOG_INFO),
'l', 'o', 'g', 'd', '.', 'a', 'u', 'd', 'i', 't', 'd', ':',
' ', 's', 't', 'a', 'r', 't', '\n' };
- write(fdDmsg, auditd_message, sizeof(auditd_message));
- logDmesg();
- fdDmesg = fdDmsg;
+ write(fdDmesg, auditd_message, sizeof(auditd_message));
}
bool LogAudit::onDataAvailable(SocketClient *cli) {
- prctl(PR_SET_NAME, "logd.auditd");
+ if (!initialized) {
+ prctl(PR_SET_NAME, "logd.auditd");
+ initialized = true;
+ }
struct audit_message rep;
@@ -60,7 +61,8 @@
return false;
}
- logPrint("type=%d %.*s", rep.nlh.nlmsg_type, rep.nlh.nlmsg_len, rep.data);
+ logPrint("type=%d %.*s",
+ rep.nlh.nlmsg_type, rep.nlh.nlmsg_len, rep.data);
return true;
}
@@ -87,7 +89,7 @@
}
bool info = strstr(str, " permissive=1") || strstr(str, " policy loaded ");
- if (fdDmesg >= 0) {
+ if ((fdDmesg >= 0) && initialized) {
struct iovec iov[3];
static const char log_info[] = { KMSG_PRIORITY(LOG_INFO) };
static const char log_warning[] = { KMSG_PRIORITY(LOG_WARNING) };
@@ -213,34 +215,23 @@
return rc;
}
-void LogAudit::logDmesg() {
- int len = klogctl(KLOG_SIZE_BUFFER, NULL, 0);
- if (len <= 0) {
- return;
+int LogAudit::log(char *buf) {
+ char *audit = strstr(buf, " audit(");
+ if (!audit) {
+ return 0;
}
- len++;
- char buf[len];
+ *audit = '\0';
- int rc = klogctl(KLOG_READ_ALL, buf, len);
-
- buf[len - 1] = '\0';
-
- for(char *tok = buf; (rc >= 0) && ((tok = strtok(tok, "\r\n"))); tok = NULL) {
- char *audit = strstr(tok, " audit(");
- if (!audit) {
- continue;
- }
-
- *audit++ = '\0';
-
- char *type = strstr(tok, "type=");
- if (type) {
- rc = logPrint("%s %s", type, audit);
- } else {
- rc = logPrint("%s", audit);
- }
+ int rc;
+ char *type = strstr(buf, "type=");
+ if (type) {
+ rc = logPrint("%s %s", type, audit + 1);
+ } else {
+ rc = logPrint("%s", audit + 1);
}
+ *audit = ' ';
+ return rc;
}
int LogAudit::getLogSocket() {
diff --git a/logd/LogAudit.h b/logd/LogAudit.h
index 111030a..f977be9 100644
--- a/logd/LogAudit.h
+++ b/logd/LogAudit.h
@@ -24,16 +24,17 @@
LogBuffer *logbuf;
LogReader *reader;
int fdDmesg;
+ bool initialized;
public:
LogAudit(LogBuffer *buf, LogReader *reader, int fdDmesg);
+ int log(char *buf);
protected:
virtual bool onDataAvailable(SocketClient *cli);
private:
static int getLogSocket();
- void logDmesg();
int logPrint(const char *fmt, ...)
__attribute__ ((__format__ (__printf__, 2, 3)));
};
diff --git a/logd/main.cpp b/logd/main.cpp
index 54da7e3..946a9a0 100644
--- a/logd/main.cpp
+++ b/logd/main.cpp
@@ -22,6 +22,7 @@
#include <stdlib.h>
#include <string.h>
#include <sys/capability.h>
+#include <sys/klog.h>
#include <sys/prctl.h>
#include <sys/stat.h>
#include <sys/types.h>
@@ -195,6 +196,23 @@
if (auditd) {
// failure is an option ... messages are in dmesg (required by standard)
LogAudit *al = new LogAudit(logBuf, reader, fdDmesg);
+
+ int len = klogctl(KLOG_SIZE_BUFFER, NULL, 0);
+ if (len > 0) {
+ len++;
+ char buf[len];
+
+ int rc = klogctl(KLOG_READ_ALL, buf, len);
+
+ buf[len - 1] = '\0';
+
+ for(char *ptr, *tok = buf;
+ (rc >= 0) && ((tok = strtok_r(tok, "\r\n", &ptr)));
+ tok = NULL) {
+ rc = al->log(tok);
+ }
+ }
+
if (al->startListener()) {
delete al;
close(fdDmesg);
diff --git a/toolbox/Android.mk b/toolbox/Android.mk
index 6fdf610..249f91e 100644
--- a/toolbox/Android.mk
+++ b/toolbox/Android.mk
@@ -7,6 +7,10 @@
-I$(LOCAL_PATH)/upstream-netbsd/include/ \
-include bsd-compatibility.h \
+# Temporary, remove after cleanup. b/18632512
+common_cflags += -Wno-unused-variable \
+ -Wno-unused-but-set-variable
+
include $(CLEAR_VARS)
LOCAL_SRC_FILES := upstream-netbsd/bin/cat/cat.c
@@ -64,13 +68,6 @@
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
-LOCAL_SRC_FILES := upstream-netbsd/bin/kill/kill.c
-LOCAL_CFLAGS += $(common_cflags) -Dmain=kill_main
-LOCAL_MODULE := libtoolbox_kill
-LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/Android.mk
-include $(BUILD_STATIC_LIBRARY)
-
-include $(CLEAR_VARS)
LOCAL_SRC_FILES := upstream-netbsd/bin/ln/ln.c
LOCAL_CFLAGS += $(common_cflags) -Dmain=ln_main
LOCAL_MODULE := libtoolbox_ln
@@ -108,7 +105,6 @@
dd \
du \
grep \
- kill \
ln \
mv \
rm \
@@ -159,7 +155,6 @@
touch \
umount \
uptime \
- vmstat \
watchprops \
wipe \
diff --git a/toolbox/upstream-netbsd/bin/kill/kill.c b/toolbox/upstream-netbsd/bin/kill/kill.c
deleted file mode 100644
index 0592577..0000000
--- a/toolbox/upstream-netbsd/bin/kill/kill.c
+++ /dev/null
@@ -1,253 +0,0 @@
-/* $NetBSD: kill.c,v 1.27 2011/08/29 14:51:18 joerg Exp $ */
-
-/*
- * Copyright (c) 1988, 1993, 1994
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-#if !defined(lint) && !defined(SHELL)
-__COPYRIGHT("@(#) Copyright (c) 1988, 1993, 1994\
- The Regents of the University of California. All rights reserved.");
-#endif /* not lint */
-
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)kill.c 8.4 (Berkeley) 4/28/95";
-#else
-__RCSID("$NetBSD: kill.c,v 1.27 2011/08/29 14:51:18 joerg Exp $");
-#endif
-#endif /* not lint */
-
-#include <ctype.h>
-#include <err.h>
-#include <errno.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <limits.h>
-#include <inttypes.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-#include <locale.h>
-#include <sys/ioctl.h>
-
-#ifdef SHELL /* sh (aka ash) builtin */
-int killcmd(int, char *argv[]);
-#define main killcmd
-#include "../../bin/sh/bltin/bltin.h"
-#endif /* SHELL */
-
-__dead static void nosig(char *);
-static void printsignals(FILE *);
-static int signame_to_signum(char *);
-__dead static void usage(void);
-
-int
-main(int argc, char *argv[])
-{
- int errors;
- intmax_t numsig, pid;
- char *ep;
-
- setprogname(argv[0]);
- setlocale(LC_ALL, "");
- if (argc < 2)
- usage();
-
- numsig = SIGTERM;
-
- argc--, argv++;
- if (strcmp(*argv, "-l") == 0) {
- argc--, argv++;
- if (argc > 1)
- usage();
- if (argc == 1) {
- if (isdigit((unsigned char)**argv) == 0)
- usage();
- numsig = strtoimax(*argv, &ep, 10);
- /* check for correctly parsed number */
- if (*ep != '\0' || numsig == INTMAX_MIN || numsig == INTMAX_MAX) {
- errx(EXIT_FAILURE, "illegal signal number: %s",
- *argv);
- /* NOTREACHED */
- }
- if (numsig >= 128)
- numsig -= 128;
- /* and whether it fits into signals range */
- if (numsig <= 0 || numsig >= NSIG)
- nosig(*argv);
- printf("%s\n", sys_signame[(int) numsig]);
- exit(0);
- }
- printsignals(stdout);
- exit(0);
- }
-
- if (!strcmp(*argv, "-s")) {
- argc--, argv++;
- if (argc < 1) {
- warnx("option requires an argument -- s");
- usage();
- }
- if (strcmp(*argv, "0")) {
- if ((numsig = signame_to_signum(*argv)) < 0)
- nosig(*argv);
- } else
- numsig = 0;
- argc--, argv++;
- } else if (**argv == '-') {
- char *sn = *argv + 1;
- if (isalpha((unsigned char)*sn)) {
- if ((numsig = signame_to_signum(sn)) < 0)
- nosig(sn);
- } else if (isdigit((unsigned char)*sn)) {
- numsig = strtoimax(sn, &ep, 10);
- /* check for correctly parsed number */
- if (*ep || numsig == INTMAX_MIN || numsig == INTMAX_MAX ) {
- errx(EXIT_FAILURE, "illegal signal number: %s",
- sn);
- /* NOTREACHED */
- }
- /* and whether it fits into signals range */
- if (numsig < 0 || numsig >= NSIG)
- nosig(sn);
- } else
- nosig(sn);
- argc--, argv++;
- }
-
- if (argc == 0)
- usage();
-
- for (errors = 0; argc; argc--, argv++) {
-#ifdef SHELL
- extern int getjobpgrp(const char *);
- if (*argv[0] == '%') {
- pid = getjobpgrp(*argv);
- if (pid == 0) {
- warnx("illegal job id: %s", *argv);
- errors = 1;
- continue;
- }
- } else
-#endif
- {
- pid = strtoimax(*argv, &ep, 10);
- /* make sure the pid is a number and fits into pid_t */
- if (!**argv || *ep || pid == INTMAX_MIN ||
- pid == INTMAX_MAX || pid != (pid_t) pid) {
-
- warnx("illegal process id: %s", *argv);
- errors = 1;
- continue;
- }
- }
- if (kill((pid_t) pid, (int) numsig) == -1) {
- warn("%s", *argv);
- errors = 1;
- }
-#ifdef SHELL
- /* Wakeup the process if it was suspended, so it can
- exit without an explicit 'fg'. */
- if (numsig == SIGTERM || numsig == SIGHUP)
- kill((pid_t) pid, SIGCONT);
-#endif
- }
-
- exit(errors);
- /* NOTREACHED */
-}
-
-static int
-signame_to_signum(char *sig)
-{
- int n;
-
- if (strncasecmp(sig, "sig", 3) == 0)
- sig += 3;
- for (n = 1; n < NSIG; n++) {
- if (!strcasecmp(sys_signame[n], sig))
- return (n);
- }
- return (-1);
-}
-
-static void
-nosig(char *name)
-{
-
- warnx("unknown signal %s; valid signals:", name);
- printsignals(stderr);
- exit(1);
- /* NOTREACHED */
-}
-
-static void
-printsignals(FILE *fp)
-{
- int sig;
- int len, nl;
- const char *name;
- int termwidth = 80;
-
- if (isatty(fileno(fp))) {
- struct winsize win;
- if (ioctl(fileno(fp), TIOCGWINSZ, &win) == 0 && win.ws_col > 0)
- termwidth = win.ws_col;
- }
-
- for (len = 0, sig = 1; sig < NSIG; sig++) {
- name = sys_signame[sig];
- nl = 1 + strlen(name);
-
- if (len + nl >= termwidth) {
- fprintf(fp, "\n");
- len = 0;
- } else
- if (len != 0)
- fprintf(fp, " ");
- len += nl;
- fprintf(fp, "%s", name);
- }
- if (len != 0)
- fprintf(fp, "\n");
-}
-
-static void
-usage(void)
-{
-
- fprintf(stderr, "usage: %s [-s signal_name] pid ...\n"
- " %s -l [exit_status]\n"
- " %s -signal_name pid ...\n"
- " %s -signal_number pid ...\n",
- getprogname(), getprogname(), getprogname(), getprogname());
- exit(1);
- /* NOTREACHED */
-}
diff --git a/toolbox/vmstat.c b/toolbox/vmstat.c
deleted file mode 100644
index 4086ed0..0000000
--- a/toolbox/vmstat.c
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * Copyright (c) 2008, The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google, Inc. nor the names of its contributors
- * may be used to endorse or promote products derived from this
- * software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/param.h>
-#include <unistd.h>
-
-struct state {
- long procs_r;
- long procs_b;
-
- long mem_free;
- long mem_mapped;
- long mem_anon;
- long mem_slab;
-
- long sys_in;
- long sys_cs;
- long sys_flt;
-
- long cpu_us;
- long cpu_ni;
- long cpu_sy;
- long cpu_id;
- long cpu_wa;
- long cpu_ir;
- long cpu_si;
-};
-
-#define MAX_LINE 256
-
-char line[MAX_LINE];
-
-static void read_state(struct state *s);
-static int read_meminfo(struct state *s);
-static int read_stat(struct state *s);
-static int read_vmstat(struct state *s);
-static void print_header(void);
-static void print_line(struct state *old, struct state *new);
-static void usage(char *cmd);
-
-int vmstat_main(int argc, char *argv[]) {
- struct state s[2];
- int iterations, delay, header_interval;
- int toggle, count;
- int i;
-
- iterations = -1;
- delay = 1;
- header_interval = 20;
-
- for (i = 1; i < argc; i++) {
- if (!strcmp(argv[i], "-n")) {
- if (i >= argc - 1) {
- fprintf(stderr, "Option -n requires an argument.\n");
- exit(EXIT_FAILURE);
- }
- iterations = atoi(argv[++i]);
- continue;
- }
- if (!strcmp(argv[i], "-d")) {
- if (i >= argc - 1) {
- fprintf(stderr, "Option -d requires an argument.\n");
- exit(EXIT_FAILURE);
- }
- delay = atoi(argv[++i]);
- continue;
- }
- if (!strcmp(argv[i], "-r")) {
- if (i >= argc - 1) {
- fprintf(stderr, "Option -r requires an argument.\n");
- exit(EXIT_FAILURE);
- }
- header_interval = atoi(argv[++i]);
- continue;
- }
- if (!strcmp(argv[i], "-h")) {
- usage(argv[0]);
- exit(EXIT_SUCCESS);
- }
- fprintf(stderr, "Invalid argument \"%s\".\n", argv[i]);
- usage(argv[0]);
- exit(EXIT_FAILURE);
- }
-
- toggle = 0;
- count = 0;
-
- if (!header_interval)
- print_header();
- read_state(&s[1 - toggle]);
- while ((iterations < 0) || (iterations-- > 0)) {
- sleep(delay);
- read_state(&s[toggle]);
- if (header_interval) {
- if (count == 0)
- print_header();
- count = (count + 1) % header_interval;
- }
- print_line(&s[1 - toggle], &s[toggle]);
- toggle = 1 - toggle;
- }
-
- return 0;
-}
-
-static void read_state(struct state *s) {
- int error;
-
- error = read_meminfo(s);
- if (error) {
- fprintf(stderr, "vmstat: could not read /proc/meminfo: %s\n", strerror(error));
- exit(EXIT_FAILURE);
- }
-
- error = read_stat(s);
- if (error) {
- fprintf(stderr, "vmstat: could not read /proc/stat: %s\n", strerror(error));
- exit(EXIT_FAILURE);
- }
-
- error = read_vmstat(s);
- if (error) {
- fprintf(stderr, "vmstat: could not read /proc/vmstat: %s\n", strerror(error));
- exit(EXIT_FAILURE);
- }
-}
-
-static int read_meminfo(struct state *s) {
- FILE *f;
-
- f = fopen("/proc/meminfo", "r");
- if (!f) return errno;
-
- while (fgets(line, MAX_LINE, f)) {
- sscanf(line, "MemFree: %ld kB", &s->mem_free);
- sscanf(line, "AnonPages: %ld kB", &s->mem_anon);
- sscanf(line, "Mapped: %ld kB", &s->mem_mapped);
- sscanf(line, "Slab: %ld kB", &s->mem_slab);
- }
-
- fclose(f);
-
- return 0;
-}
-
-static int read_stat(struct state *s) {
- FILE *f;
-
- f = fopen("/proc/stat", "r");
- if (!f) return errno;
-
- while (fgets(line, MAX_LINE, f)) {
- if (!strncmp(line, "cpu ", 4)) {
- sscanf(line, "cpu %ld %ld %ld %ld %ld %ld %ld",
- &s->cpu_us, &s->cpu_ni, &s->cpu_sy, &s->cpu_id, &s->cpu_wa,
- &s->cpu_ir, &s->cpu_si);
- }
- sscanf(line, "intr %ld", &s->sys_in);
- sscanf(line, "ctxt %ld", &s->sys_cs);
- sscanf(line, "procs_running %ld", &s->procs_r);
- sscanf(line, "procs_blocked %ld", &s->procs_b);
- }
-
- fclose(f);
-
- return 0;
-}
-
-static int read_vmstat(struct state *s) {
- FILE *f;
-
- f = fopen("/proc/vmstat", "r");
- if (!f) return errno;
-
- while (fgets(line, MAX_LINE, f)) {
- sscanf(line, "pgmajfault %ld", &s->sys_flt);
- }
-
- fclose(f);
-
- return 0;
-}
-
-static void print_header(void) {
- printf("%-5s %-27s %-14s %-17s\n", "procs", "memory", "system", "cpu");
- printf("%2s %2s %6s %6s %6s %6s %4s %4s %4s %2s %2s %2s %2s %2s %2s\n", "r", "b", "free", "mapped", "anon", "slab", "in", "cs", "flt", "us", "ni", "sy", "id", "wa", "ir");
-}
-
-/* Jiffies to percent conversion */
-#define JP(jif) ((jif) * 100 / (HZ))
-#define NORM(var) ((var) = (((var) > 99) ? (99) : (var)))
-
-static void print_line(struct state *old, struct state *new) {
- int us, ni, sy, id, wa, ir;
- us = JP(new->cpu_us - old->cpu_us); NORM(us);
- ni = JP(new->cpu_ni - old->cpu_ni); NORM(ni);
- sy = JP(new->cpu_sy - old->cpu_sy); NORM(sy);
- id = JP(new->cpu_id - old->cpu_id); NORM(id);
- wa = JP(new->cpu_wa - old->cpu_wa); NORM(wa);
- ir = JP(new->cpu_ir - old->cpu_ir); NORM(ir);
- printf("%2ld %2ld %6ld %6ld %6ld %6ld %4ld %4ld %4ld %2d %2d %2d %2d %2d %2d\n",
- new->procs_r ? (new->procs_r - 1) : 0, new->procs_b,
- new->mem_free, new->mem_mapped, new->mem_anon, new->mem_slab,
- new->sys_in - old->sys_in, new->sys_cs - old->sys_cs, new->sys_flt - old->sys_flt,
- us, ni, sy, id, wa, ir);
-}
-
-static void usage(char *cmd) {
- fprintf(stderr, "Usage: %s [ -h ] [ -n iterations ] [ -d delay ] [ -r header_repeat ]\n"
- " -n iterations How many rows of data to print.\n"
- " -d delay How long to sleep between rows.\n"
- " -r header_repeat How many rows to print before repeating\n"
- " the header. Zero means never repeat.\n"
- " -h Displays this help screen.\n",
- cmd);
-}