diff --git a/Devmapper.cpp b/Devmapper.cpp index 2cbed86..2510771 100644 --- a/Devmapper.cpp +++ b/Devmapper.cpp @@ -30,11 +30,8 @@ #include -#define LOG_TAG "Vold" - -#include - #include +#include #include #include @@ -62,42 +59,6 @@ void Devmapper::ioctlInit(struct dm_ioctl *io, size_t dataSize, } } -int Devmapper::lookupActive(const char *name_raw, char *ubuffer, size_t len) { - auto name_string = StringPrintf("%s%s", kVoldPrefix, name_raw); - const char* name = name_string.c_str(); - - char *buffer = (char *) malloc(DEVMAPPER_BUFFER_SIZE); - if (!buffer) { - SLOGE("Error allocating memory (%s)", strerror(errno)); - return -1; - } - - int fd; - if ((fd = open("/dev/device-mapper", O_RDWR | O_CLOEXEC)) < 0) { - SLOGE("Error opening devmapper (%s)", strerror(errno)); - free(buffer); - return -1; - } - - struct dm_ioctl *io = (struct dm_ioctl *) buffer; - - ioctlInit(io, DEVMAPPER_BUFFER_SIZE, name, 0); - if (ioctl(fd, DM_DEV_STATUS, io)) { - if (errno != ENXIO) { - SLOGE("DM_DEV_STATUS ioctl failed for lookup (%s)", strerror(errno)); - } - free(buffer); - close(fd); - return -1; - } - close(fd); - - unsigned minor = (io->dev & 0xff) | ((io->dev >> 12) & 0xfff00); - free(buffer); - snprintf(ubuffer, len, "/dev/block/dm-%u", minor); - return 0; -} - int Devmapper::create(const char *name_raw, const char *loopFile, const char *key, unsigned long numSectors, char *ubuffer, size_t len) { auto name_string = StringPrintf("%s%s", kVoldPrefix, name_raw); @@ -105,13 +66,13 @@ int Devmapper::create(const char *name_raw, const char *loopFile, const char *ke char *buffer = (char *) malloc(DEVMAPPER_BUFFER_SIZE); if (!buffer) { - SLOGE("Error allocating memory (%s)", strerror(errno)); + PLOG(ERROR) << "Failed malloc"; return -1; } int fd; if ((fd = open("/dev/device-mapper", O_RDWR | O_CLOEXEC)) < 0) { - SLOGE("Error opening devmapper (%s)", strerror(errno)); + PLOG(ERROR) << "Failed open"; free(buffer); return -1; } @@ -122,7 +83,7 @@ int Devmapper::create(const char *name_raw, const char *loopFile, const char *ke ioctlInit(io, DEVMAPPER_BUFFER_SIZE, name, 0); if (ioctl(fd, DM_DEV_CREATE, io)) { - SLOGE("Error creating device mapping (%s)", strerror(errno)); + PLOG(ERROR) << "Failed DM_DEV_CREATE"; free(buffer); close(fd); return -1; @@ -137,7 +98,7 @@ int Devmapper::create(const char *name_raw, const char *loopFile, const char *ke geoParams += strlen(geoParams) + 1; geoParams = (char *) _align(geoParams, 8); if (ioctl(fd, DM_DEV_SET_GEOMETRY, io)) { - SLOGE("Error setting device geometry (%s)", strerror(errno)); + PLOG(ERROR) << "Failed DM_DEV_SET_GEOMETRY"; free(buffer); close(fd); return -1; @@ -146,7 +107,7 @@ int Devmapper::create(const char *name_raw, const char *loopFile, const char *ke // Retrieve the device number we were allocated ioctlInit(io, DEVMAPPER_BUFFER_SIZE, name, 0); if (ioctl(fd, DM_DEV_STATUS, io)) { - SLOGE("Error retrieving devmapper status (%s)", strerror(errno)); + PLOG(ERROR) << "Failed DM_DEV_STATUS"; free(buffer); close(fd); return -1; @@ -177,7 +138,7 @@ int Devmapper::create(const char *name_raw, const char *loopFile, const char *ke tgt->next = cryptParams - buffer; if (ioctl(fd, DM_TABLE_LOAD, io)) { - SLOGE("Error loading mapping table (%s)", strerror(errno)); + PLOG(ERROR) << "Failed DM_TABLE_LOAD"; free(buffer); close(fd); return -1; @@ -187,7 +148,7 @@ int Devmapper::create(const char *name_raw, const char *loopFile, const char *ke ioctlInit(io, DEVMAPPER_BUFFER_SIZE, name, 0); if (ioctl(fd, DM_DEV_SUSPEND, io)) { - SLOGE("Error Resuming (%s)", strerror(errno)); + PLOG(ERROR) << "Failed DM_DEV_SUSPEND"; free(buffer); close(fd); return -1; @@ -205,13 +166,13 @@ int Devmapper::destroy(const char *name_raw) { char *buffer = (char *) malloc(DEVMAPPER_BUFFER_SIZE); if (!buffer) { - SLOGE("Error allocating memory (%s)", strerror(errno)); + PLOG(ERROR) << "Failed malloc"; return -1; } int fd; if ((fd = open("/dev/device-mapper", O_RDWR | O_CLOEXEC)) < 0) { - SLOGE("Error opening devmapper (%s)", strerror(errno)); + PLOG(ERROR) << "Failed open"; free(buffer); return -1; } @@ -223,7 +184,7 @@ int Devmapper::destroy(const char *name_raw) { if (ioctl(fd, DM_DEV_REMOVE, io)) { if (errno != ENXIO) { - SLOGE("Error destroying device mapping (%s)", strerror(errno)); + PLOG(ERROR) << "Failed DM_DEV_REMOVE"; } free(buffer); close(fd); @@ -239,21 +200,21 @@ int Devmapper::destroyAll() { ATRACE_NAME("Devmapper::destroyAll"); char *buffer = (char *) malloc(1024 * 64); if (!buffer) { - SLOGE("Error allocating memory (%s)", strerror(errno)); + PLOG(ERROR) << "Failed malloc"; return -1; } memset(buffer, 0, (1024 * 64)); char *buffer2 = (char *) malloc(DEVMAPPER_BUFFER_SIZE); if (!buffer2) { - SLOGE("Error allocating memory (%s)", strerror(errno)); + PLOG(ERROR) << "Failed malloc"; free(buffer); return -1; } int fd; if ((fd = open("/dev/device-mapper", O_RDWR | O_CLOEXEC)) < 0) { - SLOGE("Error opening devmapper (%s)", strerror(errno)); + PLOG(ERROR) << "Failed open"; free(buffer); free(buffer2); return -1; @@ -263,7 +224,7 @@ int Devmapper::destroyAll() { ioctlInit(io, (1024 * 64), NULL, 0); if (ioctl(fd, DM_LIST_DEVICES, io)) { - SLOGE("DM_LIST_DEVICES ioctl failed (%s)", strerror(errno)); + PLOG(ERROR) << "Failed DM_LIST_DEVICES"; free(buffer); free(buffer2); close(fd); @@ -281,19 +242,20 @@ int Devmapper::destroyAll() { unsigned nxt = 0; do { n = (struct dm_name_list *) (((char *) n) + nxt); - if (strncmp(n->name, kVoldPrefix, strlen(kVoldPrefix)) == 0) { - LOG(DEBUG) << "Tearing down stale dm device named " << n->name; + auto name = std::string(n->name); + if (android::base::StartsWith(name, kVoldPrefix)) { + LOG(DEBUG) << "Tearing down stale dm device named " << name; memset(buffer2, 0, DEVMAPPER_BUFFER_SIZE); struct dm_ioctl *io2 = (struct dm_ioctl *) buffer2; ioctlInit(io2, DEVMAPPER_BUFFER_SIZE, n->name, 0); if (ioctl(fd, DM_DEV_REMOVE, io2)) { if (errno != ENXIO) { - PLOG(WARNING) << "Failed to destroy dm device named " << n->name; + PLOG(WARNING) << "Failed to destroy dm device named " << name; } } } else { - LOG(VERBOSE) << "Found unmanaged dm device named " << n->name; + LOG(VERBOSE) << "Found unmanaged dm device named " << name; } nxt = n->next; } while (nxt); diff --git a/Devmapper.h b/Devmapper.h index 086ad78..7bb9786 100644 --- a/Devmapper.h +++ b/Devmapper.h @@ -26,7 +26,6 @@ public: unsigned long numSectors, char *buffer, size_t len); static int destroy(const char *name); static int destroyAll(); - static int lookupActive(const char *name, char *buffer, size_t len); private: static void *_align(void *ptr, unsigned int a); diff --git a/Loop.cpp b/Loop.cpp index 1eb9865..3736d6a 100644 --- a/Loop.cpp +++ b/Loop.cpp @@ -31,11 +31,8 @@ #include -#define LOG_TAG "Vold" - -#include - #include +#include #include #include #include @@ -49,161 +46,6 @@ using android::base::unique_fd; static const char* kVoldPrefix = "vold:"; -int Loop::lookupActive(const char *id_raw, char *buffer, size_t len) { - auto id_string = StringPrintf("%s%s", kVoldPrefix, id_raw); - const char* id = id_string.c_str(); - - int i; - int fd; - char filename[256]; - - memset(buffer, 0, len); - - for (i = 0; i < LOOP_MAX; i++) { - struct loop_info64 li; - int rc; - - snprintf(filename, sizeof(filename), "/dev/block/loop%d", i); - - if ((fd = open(filename, O_RDWR | O_CLOEXEC)) < 0) { - if (errno != ENOENT) { - SLOGE("Unable to open %s (%s)", filename, strerror(errno)); - } else { - continue; - } - return -1; - } - - rc = ioctl(fd, LOOP_GET_STATUS64, &li); - if (rc < 0 && errno == ENXIO) { - close(fd); - continue; - } - close(fd); - - if (rc < 0) { - SLOGE("Unable to get loop status for %s (%s)", filename, - strerror(errno)); - return -1; - } - if (!strncmp((const char*) li.lo_crypt_name, id, LO_NAME_SIZE)) { - break; - } - } - - if (i == LOOP_MAX) { - errno = ENOENT; - return -1; - } - strlcpy(buffer, filename, len); - return 0; -} - -int Loop::create(const char *id_raw, const char *loopFile, char *loopDeviceBuffer, size_t len) { - auto id_string = StringPrintf("%s%s", kVoldPrefix, id_raw); - const char* id = id_string.c_str(); - - int i; - int fd; - char filename[256]; - - for (i = 0; i < LOOP_MAX; i++) { - struct loop_info64 li; - int rc; - char *secontext = NULL; - - snprintf(filename, sizeof(filename), "/dev/block/loop%d", i); - - /* - * The kernel starts us off with 8 loop nodes, but more - * are created on-demand if needed. - */ - mode_t mode = 0660 | S_IFBLK; - unsigned int dev = (0xff & i) | ((i << 12) & 0xfff00000) | (7 << 8); - - if (sehandle) { - rc = selabel_lookup(sehandle, &secontext, filename, S_IFBLK); - if (rc == 0) - setfscreatecon(secontext); - } - - if (mknod(filename, mode, dev) < 0) { - if (errno != EEXIST) { - int sverrno = errno; - SLOGE("Error creating loop device node (%s)", strerror(errno)); - if (secontext) { - freecon(secontext); - setfscreatecon(NULL); - } - errno = sverrno; - return -1; - } - } - if (secontext) { - freecon(secontext); - setfscreatecon(NULL); - } - - if ((fd = open(filename, O_RDWR | O_CLOEXEC)) < 0) { - SLOGE("Unable to open %s (%s)", filename, strerror(errno)); - return -1; - } - - rc = ioctl(fd, LOOP_GET_STATUS64, &li); - if (rc < 0 && errno == ENXIO) - break; - - close(fd); - - if (rc < 0) { - SLOGE("Unable to get loop status for %s (%s)", filename, - strerror(errno)); - return -1; - } - } - - if (i == LOOP_MAX) { - SLOGE("Exhausted all loop devices"); - errno = ENOSPC; - return -1; - } - - strlcpy(loopDeviceBuffer, filename, len); - - int file_fd; - - if ((file_fd = open(loopFile, O_RDWR | O_CLOEXEC)) < 0) { - SLOGE("Unable to open %s (%s)", loopFile, strerror(errno)); - close(fd); - return -1; - } - - if (ioctl(fd, LOOP_SET_FD, file_fd) < 0) { - SLOGE("Error setting up loopback interface (%s)", strerror(errno)); - close(file_fd); - close(fd); - return -1; - } - - struct loop_info64 li; - - memset(&li, 0, sizeof(li)); - strlcpy((char*) li.lo_crypt_name, id, LO_NAME_SIZE); - strlcpy((char*) li.lo_file_name, loopFile, LO_NAME_SIZE); - - if (ioctl(fd, LOOP_SET_STATUS64, &li) < 0) { - SLOGE("Error setting loopback status (%s)", strerror(errno)); - close(file_fd); - close(fd); - return -1; - } - - close(fd); - close(file_fd); - - return 0; -} - int Loop::create(const std::string& target, std::string& out_device) { unique_fd ctl_fd(open("/dev/loop-control", O_RDWR | O_CLOEXEC)); if (ctl_fd.get() == -1) { @@ -251,12 +93,12 @@ int Loop::destroyByDevice(const char *loopDevice) { device_fd = open(loopDevice, O_RDONLY | O_CLOEXEC); if (device_fd < 0) { - SLOGE("Failed to open loop (%d)", errno); + PLOG(ERROR) << "Failed to open " << loopDevice; return -1; } if (ioctl(device_fd, LOOP_CLR_FD, 0) < 0) { - SLOGE("Failed to destroy loop (%d)", errno); + PLOG(ERROR) << "Failed to destroy " << loopDevice; close(device_fd); return -1; } @@ -279,7 +121,8 @@ int Loop::destroyAll() { // Poke through all devices looking for loops while ((de = readdir(dir))) { - if (strncmp(de->d_name, "loop", 4) != 0) continue; + auto test = std::string(de->d_name); + if (!android::base::StartsWith(test, "loop")) continue; auto path = root + de->d_name; unique_fd fd(open(path.c_str(), O_RDWR | O_CLOEXEC)); @@ -296,8 +139,8 @@ int Loop::destroyAll() { continue; } - char* id = (char*) li.lo_crypt_name; - if (strncmp(id, kVoldPrefix, strlen(kVoldPrefix)) == 0) { + auto id = std::string((char*) li.lo_crypt_name); + if (android::base::StartsWith(id, kVoldPrefix)) { LOG(DEBUG) << "Tearing down stale loop device at " << path << " named " << id; if (ioctl(fd.get(), LOOP_CLR_FD, 0) < 0) { @@ -332,22 +175,22 @@ int Loop::resizeImageFile(const char *file, unsigned long numSectors) { int fd; if ((fd = open(file, O_RDWR | O_CLOEXEC)) < 0) { - SLOGE("Error opening imagefile (%s)", strerror(errno)); + PLOG(ERROR) << "Failed to open " << file; return -1; } - SLOGD("Attempting to increase size of %s to %lu sectors.", file, numSectors); + LOG(DEBUG) << "Attempting to increase " << file << " to " << numSectors; if (fallocate(fd, 0, 0, numSectors * 512)) { if (errno == ENOSYS || errno == ENOTSUP) { - SLOGW("fallocate not found. Falling back to ftruncate."); + PLOG(WARNING) << "fallocate not found. Falling back to ftruncate."; if (ftruncate(fd, numSectors * 512) < 0) { - SLOGE("Error truncating imagefile (%s)", strerror(errno)); + PLOG(ERROR) << "Failed to ftruncate"; close(fd); return -1; } } else { - SLOGE("Error allocating space (%s)", strerror(errno)); + PLOG(ERROR) << "Failed to fallocate"; close(fd); return -1; } diff --git a/Loop.h b/Loop.h index 654b8ad..130c5b6 100644 --- a/Loop.h +++ b/Loop.h @@ -25,8 +25,6 @@ class Loop { public: static const int LOOP_MAX = 4096; public: - static int lookupActive(const char *id, char *buffer, size_t len); - static int create(const char *id, const char *loopFile, char *loopDeviceBuffer, size_t len); static int create(const std::string& file, std::string& out_device); static int destroyByDevice(const char *loopDevice); static int destroyAll(); diff --git a/NetlinkHandler.cpp b/NetlinkHandler.cpp index ecda2a0..92131e9 100644 --- a/NetlinkHandler.cpp +++ b/NetlinkHandler.cpp @@ -19,9 +19,7 @@ #include #include -#define LOG_TAG "Vold" - -#include +#include #include #include "NetlinkHandler.h" @@ -47,11 +45,11 @@ void NetlinkHandler::onEvent(NetlinkEvent *evt) { const char *subsys = evt->getSubsystem(); if (!subsys) { - SLOGW("No subsystem found in netlink event"); + LOG(WARNING) << "No subsystem found in netlink event"; return; } - if (!strcmp(subsys, "block")) { + if (std::string(subsys) == "block") { vm->handleBlockEvent(evt); } } diff --git a/NetlinkManager.cpp b/NetlinkManager.cpp index 90e3c6c..409cdc8 100644 --- a/NetlinkManager.cpp +++ b/NetlinkManager.cpp @@ -26,9 +26,7 @@ #include -#define LOG_TAG "Vold" - -#include +#include #include "NetlinkManager.h" #include "NetlinkHandler.h" @@ -60,7 +58,7 @@ int NetlinkManager::start() { if ((mSock = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_KOBJECT_UEVENT)) < 0) { - SLOGE("Unable to create uevent socket: %s", strerror(errno)); + PLOG(ERROR) << "Unable to create uevent socket"; return -1; } @@ -69,23 +67,23 @@ int NetlinkManager::start() { // Try using SO_RCVBUF if that fails. if ((setsockopt(mSock, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)) < 0) && (setsockopt(mSock, SOL_SOCKET, SO_RCVBUF, &sz, sizeof(sz)) < 0)) { - SLOGE("Unable to set uevent socket SO_RCVBUF/SO_RCVBUFFORCE option: %s", strerror(errno)); + PLOG(ERROR) << "Unable to set uevent socket SO_RCVBUF/SO_RCVBUFFORCE option"; goto out; } if (setsockopt(mSock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0) { - SLOGE("Unable to set uevent socket SO_PASSCRED option: %s", strerror(errno)); + PLOG(ERROR) << "Unable to set uevent socket SO_PASSCRED option"; goto out; } if (bind(mSock, (struct sockaddr *) &nladdr, sizeof(nladdr)) < 0) { - SLOGE("Unable to bind uevent socket: %s", strerror(errno)); + PLOG(ERROR) << "Unable to bind uevent socket"; goto out; } mHandler = new NetlinkHandler(mSock); if (mHandler->start()) { - SLOGE("Unable to start NetlinkHandler: %s", strerror(errno)); + PLOG(ERROR) << "Unable to start NetlinkHandler"; goto out; } @@ -100,7 +98,7 @@ int NetlinkManager::stop() { int status = 0; if (mHandler->stop()) { - SLOGE("Unable to stop NetlinkHandler: %s", strerror(errno)); + PLOG(ERROR) << "Unable to stop NetlinkHandler"; status = -1; } delete mHandler; diff --git a/Process.cpp b/Process.cpp index 1c0f504..042ba2d 100644 --- a/Process.cpp +++ b/Process.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -27,196 +28,98 @@ #include #include -#define LOG_TAG "ProcessKiller" +#include +#include #include +#include +#include #include #include -#include #include "Process.h" -using android::base::ReadFileToString; using android::base::StringPrintf; -int Process::readSymLink(const char *path, char *link, size_t max) { - struct stat s; - int length; +namespace android { +namespace vold { - if (lstat(path, &s) < 0) - return 0; - if ((s.st_mode & S_IFMT) != S_IFLNK) - return 0; - - // we have a symlink - length = readlink(path, link, max- 1); - if (length <= 0) - return 0; - link[length] = 0; - return 1; -} - -int Process::pathMatchesMountPoint(const char* path, const char* mountPoint) { - int length = strlen(mountPoint); - if (length > 1 && strncmp(path, mountPoint, length) == 0) { - // we need to do extra checking if mountPoint does not end in a '/' - if (mountPoint[length - 1] == '/') - return 1; - // if mountPoint does not have a trailing slash, we need to make sure - // there is one in the path to avoid partial matches. - return (path[length] == 0 || path[length] == '/'); - } - - return 0; -} - -void Process::getProcessName(int pid, std::string& out_name) { - if (!ReadFileToString(StringPrintf("/proc/%d/cmdline", pid), &out_name)) { - out_name = "???"; - } -} - -int Process::checkFileDescriptorSymLinks(int pid, const char *mountPoint) { - return checkFileDescriptorSymLinks(pid, mountPoint, NULL, 0); -} - -int Process::checkFileDescriptorSymLinks(int pid, const char *mountPoint, char *openFilename, size_t max) { - - - // compute path to process's directory of open files - char path[PATH_MAX]; - snprintf(path, sizeof(path), "/proc/%d/fd", pid); - DIR *dir = opendir(path); - if (!dir) - return 0; - - // remember length of the path - int parent_length = strlen(path); - // append a trailing '/' - path[parent_length++] = '/'; - - struct dirent* de; - while ((de = readdir(dir))) { - if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..") - || strlen(de->d_name) + parent_length + 1 >= PATH_MAX) - continue; - - // append the file name, after truncating to parent directory - path[parent_length] = 0; - strlcat(path, de->d_name, PATH_MAX); - - char link[PATH_MAX]; - - if (readSymLink(path, link, sizeof(link)) && pathMatchesMountPoint(link, mountPoint)) { - if (openFilename) { - memset(openFilename, 0, max); - strlcpy(openFilename, link, max); +static bool checkMaps(const std::string& path, const std::string& prefix) { + bool found = false; + std::ifstream infile(path); + std::string line; + while (std::getline(infile, line)) { + std::string::size_type pos = line.find('/'); + if (pos != std::string::npos) { + line = line.substr(pos); + if (android::base::StartsWith(line, prefix.c_str())) { + LOG(WARNING) << "Found map " << path << " referencing " << line; + found = true; } - closedir(dir); - return 1; } } - - closedir(dir); - return 0; + return found; } -int Process::checkFileMaps(int pid, const char *mountPoint) { - return checkFileMaps(pid, mountPoint, NULL, 0); -} - -int Process::checkFileMaps(int pid, const char *mountPoint, char *openFilename, size_t max) { - FILE *file; - char buffer[PATH_MAX + 100]; - - snprintf(buffer, sizeof(buffer), "/proc/%d/maps", pid); - file = fopen(buffer, "re"); - if (!file) - return 0; - - while (fgets(buffer, sizeof(buffer), file)) { - // skip to the path - const char* path = strchr(buffer, '/'); - if (path && pathMatchesMountPoint(path, mountPoint)) { - if (openFilename) { - memset(openFilename, 0, max); - strlcpy(openFilename, path, max); - } - fclose(file); - return 1; +static bool checkSymlink(const std::string& path, const std::string& prefix) { + std::string res; + if (android::base::Readlink(path, &res)) { + if (android::base::StartsWith(res, prefix.c_str())) { + LOG(WARNING) << "Found symlink " << path << " referencing " << res; + return true; } } - - fclose(file); - return 0; + return false; } -int Process::checkSymLink(int pid, const char *mountPoint, const char *name) { - char path[PATH_MAX]; - char link[PATH_MAX]; +int KillProcessesWithOpenFiles(const std::string& prefix, int signal) { + std::unordered_set pids; - snprintf(path, sizeof(path), "/proc/%d/%s", pid, name); - if (readSymLink(path, link, sizeof(link)) && pathMatchesMountPoint(link, mountPoint)) - return 1; - return 0; -} - -int Process::getPid(const char *s) { - int result = 0; - while (*s) { - if (!isdigit(*s)) return -1; - result = 10 * result + (*s++ - '0'); - } - return result; -} - -extern "C" void vold_killProcessesWithOpenFiles(const char *path, int signal) { - Process::killProcessesWithOpenFiles(path, signal); -} - -/* - * Hunt down processes that have files open at the given mount point. - */ -int Process::killProcessesWithOpenFiles(const char *path, int signal) { - int count = 0; - DIR* dir; - struct dirent* de; - - if (!(dir = opendir("/proc"))) { - SLOGE("opendir failed (%s)", strerror(errno)); - return count; + auto proc_d = std::unique_ptr(opendir("/proc"), closedir); + if (!proc_d) { + PLOG(ERROR) << "Failed to open proc"; + return -1; } - while ((de = readdir(dir))) { - int pid = getPid(de->d_name); - if (pid == -1) - continue; + struct dirent* proc_de; + while ((proc_de = readdir(proc_d.get())) != nullptr) { + // We only care about valid PIDs + pid_t pid; + if (proc_de->d_type != DT_DIR) continue; + if (!android::base::ParseInt(proc_de->d_name, &pid)) continue; - std::string name; - getProcessName(pid, name); + // Look for references to prefix + bool found = false; + auto path = StringPrintf("/proc/%d", pid); + found |= checkMaps(path + "/maps", prefix); + found |= checkSymlink(path + "/cwd", prefix); + found |= checkSymlink(path + "/root", prefix); + found |= checkSymlink(path + "/exe", prefix); - char openfile[PATH_MAX]; - - if (checkFileDescriptorSymLinks(pid, path, openfile, sizeof(openfile))) { - SLOGE("Process %s (%d) has open file %s", name.c_str(), pid, openfile); - } else if (checkFileMaps(pid, path, openfile, sizeof(openfile))) { - SLOGE("Process %s (%d) has open filemap for %s", name.c_str(), pid, openfile); - } else if (checkSymLink(pid, path, "cwd")) { - SLOGE("Process %s (%d) has cwd within %s", name.c_str(), pid, path); - } else if (checkSymLink(pid, path, "root")) { - SLOGE("Process %s (%d) has chroot within %s", name.c_str(), pid, path); - } else if (checkSymLink(pid, path, "exe")) { - SLOGE("Process %s (%d) has executable path within %s", name.c_str(), pid, path); + auto fd_path = path + "/fd"; + auto fd_d = std::unique_ptr(opendir(fd_path.c_str()), closedir); + if (!fd_d) { + PLOG(WARNING) << "Failed to open " << fd_path; } else { - continue; + struct dirent* fd_de; + while ((fd_de = readdir(fd_d.get())) != nullptr) { + if (fd_de->d_type != DT_LNK) continue; + found |= checkSymlink(fd_path + "/" + fd_de->d_name, prefix); + } } - if (signal != 0) { - SLOGW("Sending %s to process %d", strsignal(signal), pid); - kill(pid, signal); - count++; + if (found) { + pids.insert(pid); } } - closedir(dir); - return count; + if (signal != 0) { + for (const auto& pid : pids) { + LOG(WARNING) << "Sending " << strsignal(signal) << " to " << pid; + kill(pid, signal); + } + } + return pids.size(); } + +} // namespace vold +} // namespace android diff --git a/Process.h b/Process.h index 4ddbdb9..1406782 100644 --- a/Process.h +++ b/Process.h @@ -17,28 +17,12 @@ #ifndef _PROCESS_H #define _PROCESS_H -#ifdef __cplusplus +namespace android { +namespace vold { -class Process { -public: - static int killProcessesWithOpenFiles(const char *path, int signal); - static int getPid(const char *s); - static int checkSymLink(int pid, const char *path, const char *name); - static int checkFileMaps(int pid, const char *path); - static int checkFileMaps(int pid, const char *path, char *openFilename, size_t max); - static int checkFileDescriptorSymLinks(int pid, const char *mountPoint); - static int checkFileDescriptorSymLinks(int pid, const char *mountPoint, char *openFilename, size_t max); - static void getProcessName(int pid, std::string& out_name); -private: - static int readSymLink(const char *path, char *link, size_t max); - static int pathMatchesMountPoint(const char *path, const char *mountPoint); -}; +int KillProcessesWithOpenFiles(const std::string& path, int signal); -extern "C" { -#endif /* __cplusplus */ - void vold_killProcessesWithOpenFiles(const char *path, int signal); -#ifdef __cplusplus -} -#endif +} // namespace vold +} // namespace android #endif diff --git a/TrimTask.cpp b/TrimTask.cpp index fafb345..2718095 100644 --- a/TrimTask.cpp +++ b/TrimTask.cpp @@ -20,7 +20,6 @@ #include #include -#include #include #include #include @@ -67,9 +66,9 @@ void TrimTask::addFromFstab() { struct fstab_rec *prev_rec = NULL; for (int i = 0; i < fstab->num_entries; i++) { + auto fs_type = std::string(fstab->recs[i].fs_type); /* Skip raw partitions */ - if (!strcmp(fstab->recs[i].fs_type, "emmc") || - !strcmp(fstab->recs[i].fs_type, "mtd")) { + if (fs_type == "emmc" || fs_type == "mtd") { continue; } /* Skip read-only filesystems */ diff --git a/Utils.cpp b/Utils.cpp index a9350e8..484de90 100644 --- a/Utils.cpp +++ b/Utils.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -129,19 +130,19 @@ status_t ForceUnmount(const std::string& path) { // we start sending signals if (!VolumeManager::shutting_down) sleep(5); - Process::killProcessesWithOpenFiles(cpath, SIGINT); + KillProcessesWithOpenFiles(path, SIGINT); if (!VolumeManager::shutting_down) sleep(5); if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) { return OK; } - Process::killProcessesWithOpenFiles(cpath, SIGTERM); + KillProcessesWithOpenFiles(path, SIGTERM); if (!VolumeManager::shutting_down) sleep(5); if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) { return OK; } - Process::killProcessesWithOpenFiles(cpath, SIGKILL); + KillProcessesWithOpenFiles(path, SIGKILL); if (!VolumeManager::shutting_down) sleep(5); if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) { return OK; @@ -151,25 +152,24 @@ status_t ForceUnmount(const std::string& path) { } status_t KillProcessesUsingPath(const std::string& path) { - const char* cpath = path.c_str(); - if (Process::killProcessesWithOpenFiles(cpath, SIGINT) == 0) { + if (KillProcessesWithOpenFiles(path, SIGINT) == 0) { return OK; } if (!VolumeManager::shutting_down) sleep(5); - if (Process::killProcessesWithOpenFiles(cpath, SIGTERM) == 0) { + if (KillProcessesWithOpenFiles(path, SIGTERM) == 0) { return OK; } if (!VolumeManager::shutting_down) sleep(5); - if (Process::killProcessesWithOpenFiles(cpath, SIGKILL) == 0) { + if (KillProcessesWithOpenFiles(path, SIGKILL) == 0) { return OK; } if (!VolumeManager::shutting_down) sleep(5); // Send SIGKILL a second time to determine if we've // actually killed everyone with open files - if (Process::killProcessesWithOpenFiles(cpath, SIGKILL) == 0) { + if (KillProcessesWithOpenFiles(path, SIGKILL) == 0) { return OK; } PLOG(ERROR) << "Failed to kill processes using " << path; @@ -184,11 +184,28 @@ status_t BindMount(const std::string& source, const std::string& target) { return OK; } -static status_t readMetadata(const std::string& path, std::string& fsType, - std::string& fsUuid, std::string& fsLabel, bool untrusted) { - fsType.clear(); - fsUuid.clear(); - fsLabel.clear(); +bool FindValue(const std::string& raw, const std::string& key, std::string* value) { + auto qual = key + "=\""; + auto start = raw.find(qual); + if (start > 0 && raw[start - 1] != ' ') { + start = raw.find(qual, start + 1); + } + + if (start == std::string::npos) return false; + start += qual.length(); + + auto end = raw.find("\"", start); + if (end == std::string::npos) return false; + + *value = raw.substr(start, end - start); + return true; +} + +static status_t readMetadata(const std::string& path, std::string* fsType, + std::string* fsUuid, std::string* fsLabel, bool untrusted) { + fsType->clear(); + fsUuid->clear(); + fsLabel->clear(); std::vector cmd; cmd.push_back(kBlkidPath); @@ -209,36 +226,23 @@ static status_t readMetadata(const std::string& path, std::string& fsType, return res; } - char value[128]; for (const auto& line : output) { // Extract values from blkid output, if defined - const char* cline = line.c_str(); - const char* start = strstr(cline, "TYPE="); - if (start != nullptr && sscanf(start + 5, "\"%127[^\"]\"", value) == 1) { - fsType = value; - } - - start = strstr(cline, "UUID="); - if (start != nullptr && sscanf(start + 5, "\"%127[^\"]\"", value) == 1) { - fsUuid = value; - } - - start = strstr(cline, "LABEL="); - if (start != nullptr && sscanf(start + 6, "\"%127[^\"]\"", value) == 1) { - fsLabel = value; - } + FindValue(line, "TYPE", fsType); + FindValue(line, "UUID", fsUuid); + FindValue(line, "LABEL", fsLabel); } return OK; } -status_t ReadMetadata(const std::string& path, std::string& fsType, - std::string& fsUuid, std::string& fsLabel) { +status_t ReadMetadata(const std::string& path, std::string* fsType, + std::string* fsUuid, std::string* fsLabel) { return readMetadata(path, fsType, fsUuid, fsLabel, false); } -status_t ReadMetadataUntrusted(const std::string& path, std::string& fsType, - std::string& fsUuid, std::string& fsLabel) { +status_t ReadMetadataUntrusted(const std::string& path, std::string* fsType, + std::string* fsUuid, std::string* fsLabel) { return readMetadata(path, fsType, fsUuid, fsLabel, true); } @@ -673,15 +677,27 @@ status_t RestoreconRecursive(const std::string& path) { return OK; } -status_t SaneReadLinkAt(int dirfd, const char* path, char* buf, size_t bufsiz) { - ssize_t len = readlinkat(dirfd, path, buf, bufsiz); - if (len < 0) { - return -1; - } else if (len == (ssize_t) bufsiz) { - return -1; - } else { - buf[len] = '\0'; - return 0; +bool Readlinkat(int dirfd, const std::string& path, std::string* result) { + // Shamelessly borrowed from android::base::Readlink() + result->clear(); + + // Most Linux file systems (ext2 and ext4, say) limit symbolic links to + // 4095 bytes. Since we'll copy out into the string anyway, it doesn't + // waste memory to just start there. We add 1 so that we can recognize + // whether it actually fit (rather than being truncated to 4095). + std::vector buf(4095 + 1); + while (true) { + ssize_t size = readlinkat(dirfd, path.c_str(), &buf[0], buf.size()); + // Unrecoverable error? + if (size == -1) + return false; + // It fit! (If size == buf.size(), it may have been truncated.) + if (static_cast(size) < buf.size()) { + result->assign(&buf[0], size); + return true; + } + // Double our buffer and try again. + buf.resize(buf.size() * 2); } } diff --git a/Utils.h b/Utils.h index 8d09ddf..9163006 100644 --- a/Utils.h +++ b/Utils.h @@ -53,13 +53,15 @@ status_t KillProcessesUsingPath(const std::string& path); /* Creates bind mount from source to target */ status_t BindMount(const std::string& source, const std::string& target); +bool FindValue(const std::string& raw, const std::string& key, std::string* value); + /* Reads filesystem metadata from device at path */ -status_t ReadMetadata(const std::string& path, std::string& fsType, - std::string& fsUuid, std::string& fsLabel); +status_t ReadMetadata(const std::string& path, std::string* fsType, + std::string* fsUuid, std::string* fsLabel); /* Reads filesystem metadata from untrusted device at path */ -status_t ReadMetadataUntrusted(const std::string& path, std::string& fsType, - std::string& fsUuid, std::string& fsLabel); +status_t ReadMetadataUntrusted(const std::string& path, std::string* fsType, + std::string* fsUuid, std::string* fsLabel); /* Returns either WEXITSTATUS() status, or a negative errno */ status_t ForkExecvp(const std::vector& args); @@ -112,7 +114,8 @@ dev_t GetDevice(const std::string& path); status_t RestoreconRecursive(const std::string& path); -status_t SaneReadLinkAt(int dirfd, const char* path, char* buf, size_t bufsiz); +// TODO: promote to android::base +bool Readlinkat(int dirfd, const std::string& path, std::string* result); /* Checks if Android is running in QEMU */ bool IsRunningInEmulator(); diff --git a/VoldNativeService.cpp b/VoldNativeService.cpp index 6fb1731..d1986ef 100644 --- a/VoldNativeService.cpp +++ b/VoldNativeService.cpp @@ -37,10 +37,6 @@ #include #include -#ifndef LOG_TAG -#define LOG_TAG "vold" -#endif - using android::base::StringPrintf; using std::endl; @@ -423,7 +419,7 @@ binder::Status VoldNativeService::mkdirs(const std::string& path) { CHECK_ARGUMENT_PATH(path); ACQUIRE_LOCK; - return translate(VolumeManager::Instance()->mkdirs(path.c_str())); + return translate(VolumeManager::Instance()->mkdirs(path)); } binder::Status VoldNativeService::createObb(const std::string& sourcePath, @@ -519,7 +515,7 @@ static int fdeEnableInternal(int32_t passwordType, const std::string& password, if (rc == 0) { return 0; } else if (tries == 0) { - Process::killProcessesWithOpenFiles(DATA_MNT_POINT, SIGKILL); + KillProcessesWithOpenFiles(DATA_MNT_POINT, SIGKILL); } } diff --git a/VolumeManager.cpp b/VolumeManager.cpp index d441297..c1d51d9 100644 --- a/VolumeManager.cpp +++ b/VolumeManager.cpp @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include @@ -34,14 +33,11 @@ #include -#define LOG_TAG "Vold" - -#include - #include +#include +#include #include #include -#include #include #include @@ -98,7 +94,7 @@ VolumeManager::~VolumeManager() { int VolumeManager::updateVirtualDisk() { ATRACE_NAME("VolumeManager::updateVirtualDisk"); - if (property_get_bool(kPropVirtualDisk, false)) { + if (android::base::GetBoolProperty(kPropVirtualDisk, false)) { if (access(kPathVirtualDisk, F_OK) != 0) { Loop::createImageFile(kPathVirtualDisk, kSizeVirtualDisk / 512); } @@ -323,13 +319,12 @@ int VolumeManager::linkPrimary(userid_t userId) { std::string target(StringPrintf("/mnt/user/%d/primary", userId)); if (TEMP_FAILURE_RETRY(unlink(target.c_str()))) { if (errno != ENOENT) { - SLOGW("Failed to unlink %s: %s", target.c_str(), strerror(errno)); + PLOG(WARNING) << "Failed to unlink " << target; } } LOG(DEBUG) << "Linking " << source << " to " << target; if (TEMP_FAILURE_RETRY(symlink(source.c_str(), target.c_str()))) { - SLOGW("Failed to link %s to %s: %s", source.c_str(), target.c_str(), - strerror(errno)); + PLOG(WARNING) << "Failed to link"; return -errno; } return 0; @@ -372,12 +367,10 @@ int VolumeManager::setPrimary(const std::shared_ptr& return 0; } -static int unmount_tree(const char* path) { - size_t path_len = strlen(path); - +static int unmount_tree(const std::string& prefix) { FILE* fp = setmntent("/proc/mounts", "r"); if (fp == NULL) { - ALOGE("Error opening /proc/mounts: %s", strerror(errno)); + PLOG(ERROR) << "Failed to open /proc/mounts"; return -errno; } @@ -386,15 +379,16 @@ static int unmount_tree(const char* path) { std::list toUnmount; mntent* mentry; while ((mentry = getmntent(fp)) != NULL) { - if (strncmp(mentry->mnt_dir, path, path_len) == 0) { - toUnmount.push_front(std::string(mentry->mnt_dir)); + auto test = std::string(mentry->mnt_dir) + "/"; + if (android::base::StartsWith(test, prefix.c_str())) { + toUnmount.push_front(test); } } endmntent(fp); for (const auto& path : toUnmount) { if (umount2(path.c_str(), MNT_DETACH)) { - ALOGW("Failed to unmount %s: %s", path.c_str(), strerror(errno)); + PLOG(ERROR) << "Failed to unmount " << path; } } return 0; @@ -405,8 +399,8 @@ int VolumeManager::remountUid(uid_t uid, const std::string& mode) { DIR* dir; struct dirent* de; - char rootName[PATH_MAX]; - char pidName[PATH_MAX]; + std::string rootName; + std::string pidName; int pidFd; int nsFd; struct stat sb; @@ -418,8 +412,8 @@ int VolumeManager::remountUid(uid_t uid, const std::string& mode) { } // Figure out root namespace to compare against below - if (android::vold::SaneReadLinkAt(dirfd(dir), "1/ns/mnt", rootName, PATH_MAX) == -1) { - PLOG(ERROR) << "Failed to readlink"; + if (!android::vold::Readlinkat(dirfd(dir), "1/ns/mnt", &rootName)) { + PLOG(ERROR) << "Failed to read root namespace"; closedir(dir); return -1; } @@ -443,11 +437,11 @@ int VolumeManager::remountUid(uid_t uid, const std::string& mode) { // Matches so far, but refuse to touch if in root namespace LOG(DEBUG) << "Found matching PID " << de->d_name; - if (android::vold::SaneReadLinkAt(pidFd, "ns/mnt", pidName, PATH_MAX) == -1) { + if (!android::vold::Readlinkat(pidFd, "ns/mnt", &pidName)) { PLOG(WARNING) << "Failed to read namespace for " << de->d_name; goto next; } - if (!strcmp(rootName, pidName)) { + if (rootName == pidName) { LOG(WARNING) << "Skipping due to root namespace"; goto next; } @@ -465,7 +459,7 @@ int VolumeManager::remountUid(uid_t uid, const std::string& mode) { _exit(1); } - unmount_tree("/storage"); + unmount_tree("/storage/"); std::string storageSource; if (mode == "default") { @@ -568,7 +562,7 @@ int VolumeManager::unmountAll() { // force unmount those just to be safe. FILE* fp = setmntent("/proc/mounts", "r"); if (fp == NULL) { - SLOGE("Error opening /proc/mounts: %s", strerror(errno)); + PLOG(ERROR) << "Failed to open /proc/mounts"; return -errno; } @@ -577,9 +571,10 @@ int VolumeManager::unmountAll() { std::list toUnmount; mntent* mentry; while ((mentry = getmntent(fp)) != NULL) { - if (strncmp(mentry->mnt_dir, "/mnt/", 5) == 0 - || strncmp(mentry->mnt_dir, "/storage/", 9) == 0) { - toUnmount.push_front(std::string(mentry->mnt_dir)); + auto test = std::string(mentry->mnt_dir); + if (android::base::StartsWith(test, "/mnt/") + || android::base::StartsWith(test, "/storage/")) { + toUnmount.push_front(test); } } endmntent(fp); @@ -597,13 +592,13 @@ extern "C" int vold_unmountAll(void) { return vm->unmountAll(); } -int VolumeManager::mkdirs(const char* path) { +int VolumeManager::mkdirs(const std::string& path) { // Only offer to create directories for paths managed by vold - if (strncmp(path, "/storage/", 9) == 0) { + if (android::base::StartsWith(path, "/storage/")) { // fs_mkdirs() does symlink checking and relative path enforcement - return fs_mkdirs(path, 0700); + return fs_mkdirs(path.c_str(), 0700); } else { - SLOGE("Failed to find mounted volume for %s", path); + LOG(ERROR) << "Failed to find mounted volume for " << path; return -EINVAL; } } @@ -694,21 +689,14 @@ static android::status_t runCommandInNamespace(const std::string& command, // Matches so far, but refuse to touch if in root namespace { - char rootName[PATH_MAX]; - char pidName[PATH_MAX]; - const int root_result = - android::vold::SaneReadLinkAt(dir.get(), "1/ns/mnt", rootName, PATH_MAX); - const int pid_result = - android::vold::SaneReadLinkAt(pid_fd.get(), "ns/mnt", pidName, PATH_MAX); - if (root_result == -1) { - LOG(ERROR) << "Failed to readlink for /proc/1/ns/mnt"; + std::string rootName; + std::string pidName; + if (!android::vold::Readlinkat(dir.get(), "1/ns/mnt", &rootName) + || !android::vold::Readlinkat(pid_fd.get(), "ns/mnt", &pidName)) { + PLOG(ERROR) << "Failed to read namespaces"; return -EPERM; } - if (pid_result == -1) { - LOG(ERROR) << "Failed to readlink for /proc/" << pid << "/ns/mnt"; - return -EPERM; - } - if (!strcmp(rootName, pidName)) { + if (rootName == pidName) { LOG(ERROR) << "Don't mount appfuse in root namespace"; return -EPERM; } diff --git a/VolumeManager.h b/VolumeManager.h index dcfbdad..4f62de9 100644 --- a/VolumeManager.h +++ b/VolumeManager.h @@ -123,7 +123,7 @@ public: * is treated as filename and ignored, unless the path ends with "/". Also * ensures that path belongs to a volume managed by vold. */ - int mkdirs(const char* path); + int mkdirs(const std::string& path); int createObb(const std::string& path, const std::string& key, int32_t ownerGid, std::string* outVolId); diff --git a/cryptfs.cpp b/cryptfs.cpp index 08a3d16..ae9b0af 100644 --- a/cryptfs.cpp +++ b/cryptfs.cpp @@ -1277,10 +1277,10 @@ int wait_and_unmount(const char *mountpoint, bool kill) if (kill) { if (i == (WAIT_UNMOUNT_COUNT - 3)) { SLOGW("sending SIGHUP to processes with open files\n"); - vold_killProcessesWithOpenFiles(mountpoint, SIGTERM); + android::vold::KillProcessesWithOpenFiles(mountpoint, SIGTERM); } else if (i == (WAIT_UNMOUNT_COUNT - 2)) { SLOGW("sending SIGKILL to processes with open files\n"); - vold_killProcessesWithOpenFiles(mountpoint, SIGKILL); + android::vold::KillProcessesWithOpenFiles(mountpoint, SIGKILL); } } @@ -1291,7 +1291,7 @@ int wait_and_unmount(const char *mountpoint, bool kill) SLOGD("unmounting %s succeeded\n", mountpoint); rc = 0; } else { - vold_killProcessesWithOpenFiles(mountpoint, 0); + android::vold::KillProcessesWithOpenFiles(mountpoint, 0); SLOGE("unmounting %s failed: %s\n", mountpoint, strerror(err)); rc = -1; } diff --git a/fs/Ext4.cpp b/fs/Ext4.cpp index 1898155..89b8414 100644 --- a/fs/Ext4.cpp +++ b/fs/Ext4.cpp @@ -146,7 +146,7 @@ status_t Mount(const std::string& source, const std::string& target, bool ro, rc = mount(c_source, c_target, "ext4", flags, NULL); if (rc && errno == EROFS) { - SLOGE("%s appears to be a read only filesystem - retrying mount RO", c_source); + LOG(ERROR) << source << " appears to be a read only filesystem - retrying mount RO"; flags |= MS_RDONLY; rc = mount(c_source, c_target, "ext4", flags, NULL); } diff --git a/fs/Vfat.cpp b/fs/Vfat.cpp index dc1fe33..538178e 100644 --- a/fs/Vfat.cpp +++ b/fs/Vfat.cpp @@ -35,12 +35,8 @@ #include -#define LOG_TAG "Vold" - #include #include -#include -#include #include #include @@ -65,11 +61,6 @@ bool IsSupported() { } status_t Check(const std::string& source) { - if (access(kFsckPath, X_OK)) { - SLOGW("Skipping fs checks\n"); - return 0; - } - int pass = 1; int rc = 0; do { @@ -83,38 +74,37 @@ status_t Check(const std::string& source) { rc = ForkExecvp(cmd, sFsckUntrustedContext); if (rc < 0) { - SLOGE("Filesystem check failed due to logwrap error"); + LOG(ERROR) << "Filesystem check failed due to logwrap error"; errno = EIO; return -1; } switch(rc) { case 0: - SLOGI("Filesystem check completed OK"); + LOG(INFO) << "Filesystem check completed OK"; return 0; case 2: - SLOGE("Filesystem check failed (not a FAT filesystem)"); + LOG(ERROR) << "Filesystem check failed (not a FAT filesystem)"; errno = ENODATA; return -1; case 4: if (pass++ <= 3) { - SLOGW("Filesystem modified - rechecking (pass %d)", - pass); + LOG(WARNING) << "Filesystem modified - rechecking (pass " << pass << ")"; continue; } - SLOGE("Failing check after too many rechecks"); + LOG(ERROR) << "Failing check after too many rechecks"; errno = EIO; return -1; case 8: - SLOGE("Filesystem check failed (no filesystem)"); + LOG(ERROR) << "Filesystem check failed (no filesystem)"; errno = ENODATA; return -1; default: - SLOGE("Filesystem check failed (unknown exit code %d)", rc); + LOG(ERROR) << "Filesystem check failed (unknown exit code " << rc << ")"; errno = EIO; return -1; } @@ -128,7 +118,6 @@ status_t Mount(const std::string& source, const std::string& target, bool ro, bool createLost) { int rc; unsigned long flags; - char mountData[255]; const char* c_source = source.c_str(); const char* c_target = target.c_str(); @@ -139,31 +128,29 @@ status_t Mount(const std::string& source, const std::string& target, bool ro, flags |= (ro ? MS_RDONLY : 0); flags |= (remount ? MS_REMOUNT : 0); - snprintf(mountData, sizeof(mountData), + auto mountData = android::base::StringPrintf( "utf8,uid=%d,gid=%d,fmask=%o,dmask=%o,shortname=mixed", ownerUid, ownerGid, permMask, permMask); - rc = mount(c_source, c_target, "vfat", flags, mountData); + rc = mount(c_source, c_target, "vfat", flags, mountData.c_str()); if (rc && errno == EROFS) { - SLOGE("%s appears to be a read only filesystem - retrying mount RO", c_source); + LOG(ERROR) << source << " appears to be a read only filesystem - retrying mount RO"; flags |= MS_RDONLY; - rc = mount(c_source, c_target, "vfat", flags, mountData); + rc = mount(c_source, c_target, "vfat", flags, mountData.c_str()); } if (rc == 0 && createLost) { - char *lost_path; - asprintf(&lost_path, "%s/LOST.DIR", c_target); - if (access(lost_path, F_OK)) { + auto lost_path = android::base::StringPrintf("%s/LOST.DIR", target.c_str()); + if (access(lost_path.c_str(), F_OK)) { /* * Create a LOST.DIR in the root so we have somewhere to put * lost cluster chains (fsck_msdos doesn't currently do this) */ - if (mkdir(lost_path, 0755)) { - SLOGE("Unable to create LOST.DIR (%s)", strerror(errno)); + if (mkdir(lost_path.c_str(), 0755)) { + PLOG(ERROR) << "Unable to create LOST.DIR"; } } - free(lost_path); } return rc; @@ -189,16 +176,16 @@ status_t Format(const std::string& source, unsigned long numSectors) { int rc = ForkExecvp(cmd); if (rc < 0) { - SLOGE("Filesystem format failed due to logwrap error"); + LOG(ERROR) << "Filesystem format failed due to logwrap error"; errno = EIO; return -1; } if (rc == 0) { - SLOGI("Filesystem formatted OK"); + LOG(INFO) << "Filesystem formatted OK"; return 0; } else { - SLOGE("Format failed (unknown exit code %d)", rc); + LOG(ERROR) << "Format failed (unknown exit code " << rc << ")"; errno = EIO; return -1; } diff --git a/main.cpp b/main.cpp index 30f60a1..cca738e 100644 --- a/main.cpp +++ b/main.cpp @@ -25,9 +25,9 @@ #include "sehandle.h" #include +#include #include #include -#include #include #include @@ -88,7 +88,7 @@ int main(int argc, char** argv) { exit(1); } - if (property_get_bool("vold.debug", false)) { + if (android::base::GetBoolProperty("vold.debug", false)) { vm->setDebug(true); } @@ -120,8 +120,8 @@ int main(int argc, char** argv) { // This call should go after listeners are started to avoid // a deadlock between vold and init (see b/34278978 for details) - property_set("vold.has_adoptable", has_adoptable ? "1" : "0"); - property_set("vold.has_quota", has_quota ? "1" : "0"); + android::base::SetProperty("vold.has_adoptable", has_adoptable ? "1" : "0"); + android::base::SetProperty("vold.has_quota", has_quota ? "1" : "0"); // Do coldboot here so it won't block booting, // also the cold boot is needed in case we have flash drive @@ -240,7 +240,7 @@ static int process_config(VolumeManager *vm, bool* has_adoptable, bool* has_quot *has_adoptable = true; } if (fs_mgr_is_noemulatedsd(rec) - || property_get_bool("vold.debug.default_primary", false)) { + || android::base::GetBoolProperty("vold.debug.default_primary", false)) { flags |= android::vold::Disk::Flags::kDefaultPrimary; } diff --git a/model/Disk.cpp b/model/Disk.cpp index 5b0c981..291c2e1 100644 --- a/model/Disk.cpp +++ b/model/Disk.cpp @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include #include @@ -263,7 +265,11 @@ status_t Disk::readMetadata() { PLOG(WARNING) << "Failed to read manufacturer from " << path; return -errno; } - uint64_t manfid = strtoll(tmp.c_str(), nullptr, 16); + int64_t manfid; + if (!android::base::ParseInt(tmp, &manfid)) { + PLOG(WARNING) << "Failed to parse manufacturer " << tmp; + return -EINVAL; + } // Our goal here is to give the user a meaningful label, ideally // matching whatever is silk-screened on the card. To reduce // user confusion, this list doesn't contain white-label manfid. @@ -295,7 +301,7 @@ status_t Disk::readMetadata() { } status_t Disk::readPartitions() { - int8_t maxMinors = getMaxMinors(); + int maxMinors = getMaxMinors(); if (maxMinors < 0) { return -ENOTSUP; } @@ -324,31 +330,40 @@ status_t Disk::readPartitions() { Table table = Table::kUnknown; bool foundParts = false; for (const auto& line : output) { - char* cline = (char*) line.c_str(); - char* token = strtok(cline, kSgdiskToken); - if (token == nullptr) continue; + auto split = android::base::Split(line, kSgdiskToken); + auto it = split.begin(); + if (it == split.end()) continue; - if (!strcmp(token, "DISK")) { - const char* type = strtok(nullptr, kSgdiskToken); - if (!strcmp(type, "mbr")) { + if (*it == "DISK") { + if (++it == split.end()) continue; + if (*it == "mbr") { table = Table::kMbr; - } else if (!strcmp(type, "gpt")) { + } else if (*it == "gpt") { table = Table::kGpt; + } else { + LOG(WARNING) << "Invalid partition table " << *it; + continue; } - } else if (!strcmp(token, "PART")) { + } else if (*it == "PART") { foundParts = true; - int i = strtol(strtok(nullptr, kSgdiskToken), nullptr, 10); - if (i <= 0 || i > maxMinors) { - LOG(WARNING) << mId << " is ignoring partition " << i - << " beyond max supported devices"; + + if (++it == split.end()) continue; + int i = 0; + if (!android::base::ParseInt(*it, &i, 1, maxMinors)) { + LOG(WARNING) << "Invalid partition number " << *it; continue; } dev_t partDevice = makedev(major(mDevice), minor(mDevice) + i); if (table == Table::kMbr) { - const char* type = strtok(nullptr, kSgdiskToken); + if (++it == split.end()) continue; + int type = 0; + if (!android::base::ParseInt("0x" + *it, &type)) { + LOG(WARNING) << "Invalid partition type " << *it; + continue; + } - switch (strtol(type, nullptr, 16)) { + switch (type) { case 0x06: // FAT16 case 0x0b: // W95 FAT32 (LBA) case 0x0c: // W95 FAT32 (LBA) @@ -357,12 +372,14 @@ status_t Disk::readPartitions() { break; } } else if (table == Table::kGpt) { - const char* typeGuid = strtok(nullptr, kSgdiskToken); - const char* partGuid = strtok(nullptr, kSgdiskToken); + if (++it == split.end()) continue; + auto typeGuid = *it; + if (++it == split.end()) continue; + auto partGuid = *it; - if (!strcasecmp(typeGuid, kGptBasicData)) { + if (android::base::EqualsIgnoreCase(typeGuid, kGptBasicData)) { createPublicVolume(partDevice); - } else if (!strcasecmp(typeGuid, kGptAndroidExpand)) { + } else if (android::base::EqualsIgnoreCase(typeGuid, kGptAndroidExpand)) { createPrivateVolume(partDevice, partGuid); } } @@ -375,7 +392,7 @@ status_t Disk::readPartitions() { std::string fsType; std::string unused; - if (ReadMetadataUntrusted(mDevPath, fsType, unused, unused) == OK) { + if (ReadMetadataUntrusted(mDevPath, &fsType, &unused, &unused) == OK) { createPublicVolume(mDevice); } else { LOG(WARNING) << mId << " failed to identify, giving up"; diff --git a/model/PrivateVolume.cpp b/model/PrivateVolume.cpp index 3152313..48d041b 100644 --- a/model/PrivateVolume.cpp +++ b/model/PrivateVolume.cpp @@ -53,7 +53,7 @@ PrivateVolume::~PrivateVolume() { } status_t PrivateVolume::readMetadata() { - status_t res = ReadMetadata(mDmDevPath, mFsType, mFsUuid, mFsLabel); + status_t res = ReadMetadata(mDmDevPath, &mFsType, &mFsUuid, &mFsLabel); auto listener = getListener(); if (listener) listener->onVolumeMetadataChanged(getId(), mFsType, mFsUuid, mFsLabel); diff --git a/model/PublicVolume.cpp b/model/PublicVolume.cpp index f80f59e..98c897f 100644 --- a/model/PublicVolume.cpp +++ b/model/PublicVolume.cpp @@ -52,7 +52,7 @@ PublicVolume::~PublicVolume() { } status_t PublicVolume::readMetadata() { - status_t res = ReadMetadataUntrusted(mDevPath, mFsType, mFsUuid, mFsLabel); + status_t res = ReadMetadataUntrusted(mDevPath, &mFsType, &mFsUuid, &mFsLabel); auto listener = getListener(); if (listener) listener->onVolumeMetadataChanged(getId(), mFsType, mFsUuid, mFsLabel); diff --git a/tests/Android.mk b/tests/Android.mk index 3127352..8f2cda7 100644 --- a/tests/Android.mk +++ b/tests/Android.mk @@ -12,6 +12,7 @@ LOCAL_STATIC_LIBRARIES := libbase libselinux libvold liblog libcrypto LOCAL_SRC_FILES := \ cryptfs_test.cpp \ + Utils_test.cpp \ VolumeManager_test.cpp \ LOCAL_MODULE := vold_tests diff --git a/tests/Utils_test.cpp b/tests/Utils_test.cpp new file mode 100644 index 0000000..ab9809e --- /dev/null +++ b/tests/Utils_test.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2017 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 + +#include "../Utils.h" + +namespace android { +namespace vold { + +class UtilsTest : public testing::Test { +}; + +TEST_F(UtilsTest, FindValueTest) { + std::string tmp; + + ASSERT_FALSE(FindValue("", "KEY", &tmp)); + ASSERT_FALSE(FindValue("BADKEY=\"VALUE\"", "KEY", &tmp)); + + ASSERT_TRUE(FindValue("KEY=\"VALUE\"", "KEY", &tmp)); + ASSERT_EQ("VALUE", tmp); + + ASSERT_TRUE(FindValue("FOO=\"BAR\" KEY=\"VALUE VALUE\" BAR=\"BAZ\"", "KEY", &tmp)); + ASSERT_EQ("VALUE VALUE", tmp); + + ASSERT_TRUE(FindValue("BADKEY=\"VALUE\" KEY=\"BAZ\"", "KEY", &tmp)); + ASSERT_EQ("BAZ", tmp); +} + +} +}