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:
parent
de90da4d8a
commit
5792ce79cc
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue