summaryrefslogtreecommitdiffstats
path: root/run-as
diff options
context:
space:
mode:
authorDavid 'Digit' Turner <digit@android.com>2011-08-27 18:48:45 +0200
committerJean-Baptiste Queru <jbq@google.com>2011-12-06 14:22:30 -0800
commit5792ce79cc79cd0eef9fadd6351521b128b4e85c (patch)
tree9333a01e3336e4d4195152ad2a1fbce9b10b6cf9 /run-as
parentde90da4d8ac11c6794d0a7751633224c3ec11d90 (diff)
downloadsystem_core-5792ce79cc79cd0eef9fadd6351521b128b4e85c.zip
system_core-5792ce79cc79cd0eef9fadd6351521b128b4e85c.tar.gz
system_core-5792ce79cc79cd0eef9fadd6351521b128b4e85c.tar.bz2
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
Diffstat (limited to 'run-as')
-rw-r--r--run-as/package.c91
1 files changed, 59 insertions, 32 deletions
diff --git a/run-as/package.c b/run-as/package.c
index ca08436..8f11646 100644
--- a/run-as/package.c
+++ b/run-as/package.c
@@ -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;
}