Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5792ce79 authored by David 'Digit' Turner's avatar David 'Digit' Turner Committed by Jean-Baptiste Queru
Browse files

run-as: use mmap to read package list file

This patch uses mmap() to read /data/system/packages.list

This avoids depending on the size of a fixed static buffer
which may happen to be too short for systems with a lot of
packages installed.

Also avoids calling malloc() which we don't want to trust here
since run-as is a setuid program.

Change-Id: I1d640a08b5d73af2fc80546b01c8d970c7f6b514
parent de90da4d
Loading
Loading
Loading
Loading
+59 −32
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <private/android_filesystem_config.h>
#include "package.h"

@@ -43,9 +44,6 @@
/* The file containing the list of installed packages on the system */
#define PACKAGES_LIST_FILE  "/data/system/packages.list"

/* This should be large enough to hold the content of the package database file */
#define PACKAGES_LIST_BUFFER_SIZE  65536

/* Copy 'srclen' string bytes from 'src' into buffer 'dst' of size 'dstlen'
 * This function always zero-terminate the destination buffer unless
 * 'dstlen' is 0, even in case of overflow.
@@ -67,40 +65,63 @@ string_copy(char* dst, size_t dstlen, const char* src, size_t srclen)
    *dst = '\0'; /* zero-terminate result */
}

/* Read up to 'buffsize' bytes into 'buff' from the file
 * named 'filename'. Return byte length on success, or -1
 * on error.
/* Open 'filename' and map it into our address-space.
 * Returns buffer address, or NULL on error
 * On exit, *filesize will be set to the file's size, or 0 on error
 */
static int
read_file(const char* filename, char* buff, size_t buffsize)
static void*
map_file(const char* filename, size_t* filesize)
{
    int  fd, len, old_errno;
    int  fd, ret, old_errno;
    struct stat  st;
    size_t  length = 0;
    void*   address = NULL;

    /* check the input buffer size */
    if (buffsize >= INT_MAX) {
        errno = EINVAL;
        return -1;
    }
    *filesize = 0;

    /* open the file for reading */
    do {
        fd = open(filename, O_RDONLY);
    } while (fd < 0 && errno == EINTR);

    fd = TEMP_FAILURE_RETRY(open(filename, O_RDONLY));
    if (fd < 0)
        return -1;
        return NULL;

    /* read the content */
    do {
        len = read(fd, buff, buffsize);
    } while (len < 0 && errno == EINTR);
    /* get its size */
    ret = TEMP_FAILURE_RETRY(fstat(fd, &st));
    if (ret < 0)
        goto EXIT;

    /* Ensure that the size is not ridiculously large */
    length = (size_t)st.st_size;
    if ((off_t)length != st.st_size) {
        errno = ENOMEM;
        goto EXIT;
    }

    /* Memory-map the file now */
    address = TEMP_FAILURE_RETRY(mmap(NULL, length, PROT_READ, MAP_PRIVATE, fd, 0));
    if (address == MAP_FAILED) {
        address = NULL;
        goto EXIT;
    }

    /* We're good, return size */
    *filesize = length;

EXIT:
    /* close the file, preserve old errno for better diagnostics */
    old_errno = errno;
    close(fd);
    errno = old_errno;

    return len;
    return address;
}

/* unmap the file, but preserve errno */
static void
unmap_file(void*  address, size_t  size)
{
    int old_errno = errno;
    TEMP_FAILURE_RETRY(munmap(address, size));
    errno = old_errno;
}

/* Check that a given directory:
@@ -371,18 +392,18 @@ BAD:
int
get_package_info(const char* pkgName, PackageInfo *info)
{
    static char  buffer[PACKAGES_LIST_BUFFER_SIZE];
    int          buffer_len;
    char*        buffer;
    size_t       buffer_len;
    const char*  p;
    const char*  buffer_end;
    int          result;
    int          result = -1;

    info->uid          = 0;
    info->isDebuggable = 0;
    info->dataDir[0]   = '\0';

    buffer_len = read_file(PACKAGES_LIST_FILE, buffer, sizeof buffer);
    if (buffer_len < 0)
    buffer = map_file(PACKAGES_LIST_FILE, &buffer_len);
    if (buffer == NULL)
        return -1;

    p          = buffer;
@@ -455,7 +476,8 @@ get_package_info(const char* pkgName, PackageInfo *info)
        string_copy(info->dataDir, sizeof info->dataDir, p, q - p);

        /* Ignore the rest */
        return 0;
        result = 0;
        goto EXIT;

    NEXT_LINE:
        p = next;
@@ -463,9 +485,14 @@ get_package_info(const char* pkgName, PackageInfo *info)

    /* the package is unknown */
    errno = ENOENT;
    return -1;
    result = -1;
    goto EXIT;

BAD_FORMAT:
    errno = EINVAL;
    return -1;
    result = -1;

EXIT:
    unmap_file(buffer, buffer_len);
    return result;
}