Merge "fs_mgr: allow for zramsize to be specified as percentage of total memory" into lmp-mr1-dev
diff --git a/adb/get_my_path_darwin.c b/adb/get_my_path_darwin.c
index 5b95d15..ff1396c 100644
--- a/adb/get_my_path_darwin.c
+++ b/adb/get_my_path_darwin.c
@@ -19,12 +19,12 @@
void get_my_path(char *s, size_t maxLen)
{
- ProcessSerialNumber psn;
- GetCurrentProcess(&psn);
- CFDictionaryRef dict;
- dict = ProcessInformationCopyDictionary(&psn, 0xffffffff);
- CFStringRef value = (CFStringRef)CFDictionaryGetValue(dict,
- CFSTR("CFBundleExecutable"));
- CFStringGetCString(value, s, maxLen, kCFStringEncodingUTF8);
+ CFBundleRef mainBundle = CFBundleGetMainBundle();
+ CFURLRef executableURL = CFBundleCopyExecutableURL(mainBundle);
+ CFStringRef executablePathString = CFURLCopyFileSystemPath(executableURL, kCFURLPOSIXPathStyle);
+ CFRelease(executableURL);
+
+ CFStringGetFileSystemRepresentation(executablePathString, s, maxLen);
+ CFRelease(executablePathString);
}
diff --git a/fastboot/util_osx.c b/fastboot/util_osx.c
index 26b832a..e718562 100644
--- a/fastboot/util_osx.c
+++ b/fastboot/util_osx.c
@@ -31,14 +31,15 @@
void get_my_path(char s[PATH_MAX])
{
- char *x;
- ProcessSerialNumber psn;
- GetCurrentProcess(&psn);
- CFDictionaryRef dict;
- dict = ProcessInformationCopyDictionary(&psn, 0xffffffff);
- CFStringRef value = (CFStringRef)CFDictionaryGetValue(dict,
- CFSTR("CFBundleExecutable"));
- CFStringGetCString(value, s, PATH_MAX - 1, kCFStringEncodingUTF8);
+ CFBundleRef mainBundle = CFBundleGetMainBundle();
+ CFURLRef executableURL = CFBundleCopyExecutableURL(mainBundle);
+ CFStringRef executablePathString = CFURLCopyFileSystemPath(executableURL, kCFURLPOSIXPathStyle);
+ CFRelease(executableURL);
+
+ CFStringGetFileSystemRepresentation(executablePathString, s, PATH_MAX-1);
+ CFRelease(executablePathString);
+
+ char *x;
x = strrchr(s, '/');
if(x) x[1] = 0;
}
diff --git a/fs_mgr/Android.mk b/fs_mgr/Android.mk
index 61bf1ee..0ec6c4b 100644
--- a/fs_mgr/Android.mk
+++ b/fs_mgr/Android.mk
@@ -4,8 +4,12 @@
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= fs_mgr.c fs_mgr_verity.c fs_mgr_fstab.c
+LOCAL_SRC_FILES += fs_mgr_format.c
-LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include \
+ system/vold \
+ system/extras/ext4_utils \
+ external/openssl/include
LOCAL_MODULE:= libfs_mgr
LOCAL_STATIC_LIBRARIES := liblogwrap libmincrypt libext4_utils_static
@@ -35,6 +39,7 @@
LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_UNSTRIPPED)
LOCAL_STATIC_LIBRARIES := libfs_mgr liblogwrap libcutils liblog libc libmincrypt libext4_utils_static
+LOCAL_STATIC_LIBRARIES += libsparse_static libz libselinux
LOCAL_CFLAGS := -Werror
diff --git a/fs_mgr/fs_mgr.c b/fs_mgr/fs_mgr.c
index d1e92f2..8533ff6 100644
--- a/fs_mgr/fs_mgr.c
+++ b/fs_mgr/fs_mgr.c
@@ -40,6 +40,9 @@
#include "mincrypt/sha.h"
#include "mincrypt/sha256.h"
+#include "ext4_utils.h"
+#include "wipe.h"
+
#include "fs_mgr_priv.h"
#include "fs_mgr_priv_verity.h"
@@ -256,6 +259,15 @@
return strcmp(value, "0") ? 1 : 0;
}
+static int device_is_force_encrypted() {
+ int ret = -1;
+ char value[PROP_VALUE_MAX];
+ ret = __system_property_get("ro.vold.forceencryption", value);
+ if (ret < 0)
+ return 0;
+ return strcmp(value, "1") ? 0 : 1;
+}
+
/*
* Tries to mount any of the consecutive fstab entries that match
* the mountpoint of the one given by fstab->recs[start_idx].
@@ -371,6 +383,8 @@
}
}
int last_idx_inspected;
+ int top_idx = i;
+
mret = mount_with_alternatives(fstab, i, &last_idx_inspected, &attempted_idx);
i = last_idx_inspected;
mount_errno = errno;
@@ -378,7 +392,9 @@
/* Deal with encryptability. */
if (!mret) {
/* If this is encryptable, need to trigger encryption */
- if ((fstab->recs[attempted_idx].fs_mgr_flags & MF_FORCECRYPT)) {
+ if ( (fstab->recs[attempted_idx].fs_mgr_flags & MF_FORCECRYPT)
+ || (device_is_force_encrypted()
+ && fs_mgr_is_encryptable(&fstab->recs[attempted_idx]))) {
if (umount(fstab->recs[attempted_idx].mount_point) == 0) {
if (encryptable == FS_MGR_MNTALL_DEV_NOT_ENCRYPTED) {
ERROR("Will try to encrypt %s %s\n", fstab->recs[attempted_idx].mount_point,
@@ -398,10 +414,38 @@
continue;
}
- /* mount(2) returned an error, check if it's encryptable and deal with it */
+ /* mount(2) returned an error, handle the encryptable/formattable case */
+ bool wiped = partition_wiped(fstab->recs[top_idx].blk_device);
+ if (mret && mount_errno != EBUSY && mount_errno != EACCES &&
+ fs_mgr_is_formattable(&fstab->recs[top_idx]) && wiped) {
+ /* top_idx and attempted_idx point at the same partition, but sometimes
+ * at two different lines in the fstab. Use the top one for formatting
+ * as that is the preferred one.
+ */
+ ERROR("%s(): %s is wiped and %s %s is formattable. Format it.\n", __func__,
+ fstab->recs[top_idx].blk_device, fstab->recs[top_idx].mount_point,
+ fstab->recs[top_idx].fs_type);
+ if (fs_mgr_is_encryptable(&fstab->recs[top_idx]) &&
+ strcmp(fstab->recs[top_idx].key_loc, KEY_IN_FOOTER)) {
+ int fd = open(fstab->recs[top_idx].key_loc, O_WRONLY, 0644);
+ if (fd >= 0) {
+ INFO("%s(): also wipe %s\n", __func__, fstab->recs[top_idx].key_loc);
+ wipe_block_device(fd, get_file_size(fd));
+ close(fd);
+ } else {
+ ERROR("%s(): %s wouldn't open (%s)\n", __func__,
+ fstab->recs[top_idx].key_loc, strerror(errno));
+ }
+ }
+ if (fs_mgr_do_format(&fstab->recs[top_idx]) == 0) {
+ /* Let's replay the mount actions. */
+ i = top_idx - 1;
+ continue;
+ }
+ }
if (mret && mount_errno != EBUSY && mount_errno != EACCES &&
fs_mgr_is_encryptable(&fstab->recs[attempted_idx])) {
- if(partition_wiped(fstab->recs[attempted_idx].blk_device)) {
+ if (wiped) {
ERROR("%s(): %s is wiped and %s %s is encryptable. Suggest recovery...\n", __func__,
fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point,
fstab->recs[attempted_idx].fs_type);
diff --git a/fs_mgr/fs_mgr_format.c b/fs_mgr/fs_mgr_format.c
new file mode 100644
index 0000000..b5b92b5
--- /dev/null
+++ b/fs_mgr/fs_mgr_format.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2015 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 <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <cutils/partition_utils.h>
+#include <sys/mount.h>
+#include "ext4_utils.h"
+#include "ext4.h"
+#include "make_ext4fs.h"
+#include "fs_mgr_priv.h"
+
+extern struct fs_info info; /* magic global from ext4_utils */
+extern void reset_ext4fs_info();
+
+static int format_ext4(char *fs_blkdev, char *fs_mnt_point)
+{
+ unsigned int nr_sec;
+ int fd, rc = 0;
+
+ if ((fd = open(fs_blkdev, O_WRONLY, 0644)) < 0) {
+ ERROR("Cannot open block device. %s\n", strerror(errno));
+ return -1;
+ }
+
+ if ((ioctl(fd, BLKGETSIZE, &nr_sec)) == -1) {
+ ERROR("Cannot get block device size. %s\n", strerror(errno));
+ close(fd);
+ return -1;
+ }
+
+ /* Format the partition using the calculated length */
+ reset_ext4fs_info();
+ info.len = ((off64_t)nr_sec * 512);
+
+ /* Use make_ext4fs_internal to avoid wiping an already-wiped partition. */
+ rc = make_ext4fs_internal(fd, NULL, fs_mnt_point, 0, 0, 0, 0, 0, 0, 0, 0, NULL);
+ if (rc) {
+ ERROR("make_ext4fs returned %d.\n", rc);
+ }
+ close(fd);
+
+ return rc;
+}
+
+static int format_f2fs(char *fs_blkdev)
+{
+ char * args[3];
+ int pid;
+ int rc = 0;
+
+ args[0] = (char *)"/sbin/mkfs.f2fs";
+ args[1] = fs_blkdev;
+ args[2] = (char *)0;
+
+ pid = fork();
+ if (pid < 0) {
+ return pid;
+ }
+ if (!pid) {
+ /* This doesn't return */
+ execv("/sbin/mkfs.f2fs", args);
+ exit(1);
+ }
+ for(;;) {
+ pid_t p = waitpid(pid, &rc, 0);
+ if (p != pid) {
+ ERROR("Error waiting for child process - %d\n", p);
+ rc = -1;
+ break;
+ }
+ if (WIFEXITED(rc)) {
+ rc = WEXITSTATUS(rc);
+ INFO("%s done, status %d\n", args[0], rc);
+ if (rc) {
+ rc = -1;
+ }
+ break;
+ }
+ ERROR("Still waiting for %s...\n", args[0]);
+ }
+
+ return rc;
+}
+
+int fs_mgr_do_format(struct fstab_rec *fstab)
+{
+ int rc = -EINVAL;
+
+ ERROR("%s: Format %s as '%s'.\n", __func__, fstab->blk_device, fstab->fs_type);
+
+ if (!strncmp(fstab->fs_type, "f2fs", 4)) {
+ rc = format_f2fs(fstab->blk_device);
+ } else if (!strncmp(fstab->fs_type, "ext4", 4)) {
+ rc = format_ext4(fstab->blk_device, fstab->mount_point);
+ } else {
+ ERROR("File system type '%s' is not supported\n", fstab->fs_type);
+ }
+
+ return rc;
+}
diff --git a/fs_mgr/fs_mgr_fstab.c b/fs_mgr/fs_mgr_fstab.c
index c200b05..c2da28a 100644
--- a/fs_mgr/fs_mgr_fstab.c
+++ b/fs_mgr/fs_mgr_fstab.c
@@ -70,6 +70,7 @@
{ "zramsize=", MF_ZRAMSIZE },
{ "verify", MF_VERIFY },
{ "noemulatedsd", MF_NOEMULATEDSD },
+ { "formattable", MF_FORMATTABLE },
{ "defaults", 0 },
{ 0, 0 },
};
@@ -452,3 +453,8 @@
{
return fstab->fs_mgr_flags & MF_NOEMULATEDSD;
}
+
+int fs_mgr_is_formattable(struct fstab_rec *fstab)
+{
+ return fstab->fs_mgr_flags & (MF_FORMATTABLE);
+}
diff --git a/fs_mgr/fs_mgr_priv.h b/fs_mgr/fs_mgr_priv.h
index 34938fa..fd58306 100644
--- a/fs_mgr/fs_mgr_priv.h
+++ b/fs_mgr/fs_mgr_priv.h
@@ -75,6 +75,7 @@
#define MF_FORCECRYPT 0x400
#define MF_NOEMULATEDSD 0x800 /* no emulated sdcard daemon, sd card is the only
external storage */
+#define MF_FORMATTABLE 0x1000
#define DM_BUF_SIZE 4096
diff --git a/fs_mgr/include/fs_mgr.h b/fs_mgr/include/fs_mgr.h
index 5e2ff41..5a6ad2d 100644
--- a/fs_mgr/include/fs_mgr.h
+++ b/fs_mgr/include/fs_mgr.h
@@ -84,7 +84,11 @@
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_is_formattable(struct fstab_rec *fstab);
int fs_mgr_swapon_all(struct fstab *fstab);
+
+int fs_mgr_do_format(struct fstab_rec *fstab);
+
#ifdef __cplusplus
}
#endif
diff --git a/include/cutils/debugger.h b/include/cutils/debugger.h
index 4bcc8e6..bae687d 100644
--- a/include/cutils/debugger.h
+++ b/include/cutils/debugger.h
@@ -64,11 +64,26 @@
*/
int dump_tombstone(pid_t tid, char* pathbuf, size_t pathlen);
+/* Dumps a process backtrace, registers, and stack to a tombstone file (requires root).
+ * Stores the tombstone path in the provided buffer.
+ * If reading debugger data from debuggerd ever takes longer than timeout_secs
+ * seconds, then stop and return an error.
+ * Returns 0 on success, -1 on error.
+ */
+int dump_tombstone_timeout(pid_t tid, char* pathbuf, size_t pathlen, int timeout_secs);
+
/* Dumps a process backtrace only to the specified file (requires root).
* Returns 0 on success, -1 on error.
*/
int dump_backtrace_to_file(pid_t tid, int fd);
+/* Dumps a process backtrace only to the specified file (requires root).
+ * If reading debugger data from debuggerd ever takes longer than timeout_secs
+ * seconds, then stop and return an error.
+ * Returns 0 on success, -1 on error.
+ */
+int dump_backtrace_to_file_timeout(pid_t tid, int fd, int timeout_secs);
+
#ifdef __cplusplus
}
#endif
diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h
index 5d9c3ea..2f528b9 100644
--- a/include/private/android_filesystem_config.h
+++ b/include/private/android_filesystem_config.h
@@ -248,7 +248,6 @@
{ 06755, AID_ROOT, AID_ROOT, 0, "system/xbin/librank" },
{ 06755, AID_ROOT, AID_ROOT, 0, "system/xbin/procrank" },
{ 06755, AID_ROOT, AID_ROOT, 0, "system/xbin/procmem" },
- { 06755, AID_ROOT, AID_ROOT, 0, "system/xbin/tcpdump" },
{ 04770, AID_ROOT, AID_RADIO, 0, "system/bin/pppd-ril" },
/* the following files have enhanced capabilities and ARE included in user builds. */
diff --git a/init/Android.mk b/init/Android.mk
index 489dc93..228e645 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -45,7 +45,9 @@
libc \
libselinux \
libmincrypt \
- libext4_utils_static
+ libext4_utils_static \
+ libsparse_static \
+ libz
LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/Android.mk
diff --git a/init/devices.c b/init/devices.c
index 1012fee..73fe223 100644
--- a/init/devices.c
+++ b/init/devices.c
@@ -564,7 +564,7 @@
make_device(devpath, path, block, major, minor, (const char **)links);
if (links) {
for (i = 0; links[i]; i++)
- make_link(devpath, links[i]);
+ make_link_init(devpath, links[i]);
}
}
diff --git a/init/util.c b/init/util.c
index 0f69e1c..12cb11d 100644
--- a/init/util.c
+++ b/init/util.c
@@ -329,13 +329,13 @@
if (!s)
return;
- for (; *s; s++) {
+ while (*s) {
s += strspn(s, accept);
- if (*s) *s = '_';
+ if (*s) *s++ = '_';
}
}
-void make_link(const char *oldpath, const char *newpath)
+void make_link_init(const char *oldpath, const char *newpath)
{
int ret;
char buf[256];
diff --git a/init/util.h b/init/util.h
index 04b8129..a7e7c8b 100644
--- a/init/util.h
+++ b/init/util.h
@@ -33,7 +33,7 @@
int mkdir_recursive(const char *pathname, mode_t mode);
void sanitize(char *p);
-void make_link(const char *oldpath, const char *newpath);
+void make_link_init(const char *oldpath, const char *newpath);
void remove_link(const char *oldpath, const char *newpath);
int wait_for_file(const char *filename, int timeout);
void open_devnull_stdio(void);
diff --git a/libcutils/debugger.c b/libcutils/debugger.c
index 4035ee1..b8a2efc 100644
--- a/libcutils/debugger.c
+++ b/libcutils/debugger.c
@@ -19,11 +19,16 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
#include <unistd.h>
#include <cutils/debugger.h>
#include <cutils/sockets.h>
+#define LOG_TAG "DEBUG"
+#include <log/log.h>
+
#if defined(__LP64__)
#include <elf.h>
@@ -64,7 +69,7 @@
return result;
}
-static int make_dump_request(debugger_action_t action, pid_t tid) {
+static int make_dump_request(debugger_action_t action, pid_t tid, int timeout_secs) {
const char* socket_name;
debugger_msg_t msg;
size_t msg_len;
@@ -98,6 +103,19 @@
return -1;
}
+ if (timeout_secs > 0) {
+ struct timeval tm;
+ tm.tv_sec = timeout_secs;
+ tm.tv_usec = 0;
+ if (setsockopt(sock_fd, SOL_SOCKET, SO_RCVTIMEO, &tm, sizeof(tm)) == -1) {
+ ALOGE("WARNING: Cannot set receive timeout value on socket: %s", strerror(errno));
+ }
+
+ if (setsockopt(sock_fd, SOL_SOCKET, SO_SNDTIMEO, &tm, sizeof(tm)) == -1) {
+ ALOGE("WARNING: Cannot set send timeout value on socket: %s", strerror(errno));
+ }
+ }
+
if (send_request(sock_fd, msg_ptr, msg_len) < 0) {
TEMP_FAILURE_RETRY(close(sock_fd));
return -1;
@@ -107,7 +125,11 @@
}
int dump_backtrace_to_file(pid_t tid, int fd) {
- int sock_fd = make_dump_request(DEBUGGER_ACTION_DUMP_BACKTRACE, tid);
+ return dump_backtrace_to_file_timeout(tid, fd, 0);
+}
+
+int dump_backtrace_to_file_timeout(pid_t tid, int fd, int timeout_secs) {
+ int sock_fd = make_dump_request(DEBUGGER_ACTION_DUMP_BACKTRACE, tid, timeout_secs);
if (sock_fd < 0) {
return -1;
}
@@ -127,7 +149,11 @@
}
int dump_tombstone(pid_t tid, char* pathbuf, size_t pathlen) {
- int sock_fd = make_dump_request(DEBUGGER_ACTION_DUMP_TOMBSTONE, tid);
+ return dump_tombstone_timeout(tid, pathbuf, pathlen, 0);
+}
+
+int dump_tombstone_timeout(pid_t tid, char* pathbuf, size_t pathlen, int timeout_secs) {
+ int sock_fd = make_dump_request(DEBUGGER_ACTION_DUMP_TOMBSTONE, tid, timeout_secs);
if (sock_fd < 0) {
return -1;
}
diff --git a/sdcard/sdcard.c b/sdcard/sdcard.c
index 247ddd0..9cfb040 100644
--- a/sdcard/sdcard.c
+++ b/sdcard/sdcard.c
@@ -168,6 +168,11 @@
__u32 refcount;
__u64 nid;
__u64 gen;
+ /*
+ * The inode number for this FUSE node. Note that this isn't stable across
+ * multiple invocations of the FUSE daemon.
+ */
+ __u32 ino;
/* State derived based on current position in hierarchy. */
perm_t perm;
@@ -224,6 +229,25 @@
struct node root;
char obbpath[PATH_MAX];
+ /* Used to allocate unique inode numbers for fuse nodes. We use
+ * a simple counter based scheme where inode numbers from deleted
+ * nodes aren't reused. Note that inode allocations are not stable
+ * across multiple invocation of the sdcard daemon, but that shouldn't
+ * be a huge problem in practice.
+ *
+ * Note that we restrict inodes to 32 bit unsigned integers to prevent
+ * truncation on 32 bit processes when unsigned long long stat.st_ino is
+ * assigned to an unsigned long ino_t type in an LP32 process.
+ *
+ * Also note that fuse_attr and fuse_dirent inode values are 64 bits wide
+ * on both LP32 and LP64, but the fuse kernel code doesn't squash 64 bit
+ * inode numbers into 32 bit values on 64 bit kernels (see fuse_squash_ino
+ * in fs/fuse/inode.c).
+ *
+ * Accesses must be guarded by |lock|.
+ */
+ __u32 inode_ctr;
+
Hashmap* package_to_appid;
Hashmap* appid_with_rw;
};
@@ -387,7 +411,7 @@
static void attr_from_stat(struct fuse_attr *attr, const struct stat *s, const struct node* node)
{
- attr->ino = node->nid;
+ attr->ino = node->ino;
attr->size = s->st_size;
attr->blocks = s->st_blocks;
attr->atime = s->st_atime;
@@ -575,6 +599,13 @@
struct node *node;
size_t namelen = strlen(name);
+ // Detect overflows in the inode counter. "4 billion nodes should be enough
+ // for everybody".
+ if (fuse->inode_ctr == 0) {
+ ERROR("No more inode numbers available");
+ return NULL;
+ }
+
node = calloc(1, sizeof(struct node));
if (!node) {
return NULL;
@@ -596,6 +627,7 @@
}
node->namelen = namelen;
node->nid = ptr_to_id(node);
+ node->ino = fuse->inode_ctr++;
node->gen = fuse->next_generation++;
derive_permissions_locked(fuse, parent, node);
@@ -700,6 +732,7 @@
fuse->derive = derive;
fuse->split_perms = split_perms;
fuse->write_gid = write_gid;
+ fuse->inode_ctr = 1;
memset(&fuse->root, 0, sizeof(fuse->root));
fuse->root.nid = FUSE_ROOT_ID; /* 1 */