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
This commit is contained in:
David 'Digit' Turner 2011-08-27 18:48:45 +02:00 committed by Jean-Baptiste Queru
parent de90da4d8a
commit 5792ce79cc
1 changed files with 59 additions and 32 deletions

View File

@ -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;
}