Extend run-as with optional --user argument.

1. Calculate AID for spawned process as (100000 * $user) + uid_from_packages.list
2. Use /data/user/$user/$packageDir as a root of a new process if $user != 0.

Change-Id: I761dfb481114bd51e5a950307fcaf403e96eef10
(cherry picked from commit da31778f3b)
This commit is contained in:
Oleksiy Vyalov 2015-06-03 16:56:29 -07:00
parent 4d7f052afb
commit a08d313bb8
3 changed files with 48 additions and 13 deletions

View file

@ -16,6 +16,7 @@
*/
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
@ -421,7 +422,7 @@ parse_positive_decimal(const char** pp, const char* end)
* If the package database is corrupted, return -1 and set errno to EINVAL
*/
int
get_package_info(const char* pkgName, PackageInfo *info)
get_package_info(const char* pkgName, uid_t userId, PackageInfo *info)
{
char* buffer;
size_t buffer_len;
@ -506,7 +507,20 @@ get_package_info(const char* pkgName, PackageInfo *info)
if (q == p)
goto BAD_FORMAT;
p = string_copy(info->dataDir, sizeof info->dataDir, p, q - p);
/* If userId == 0 (i.e. user is device owner) we can use dataDir value
* from packages.list, otherwise compose data directory as
* /data/user/$uid/$packageId
*/
if (userId == 0) {
p = string_copy(info->dataDir, sizeof info->dataDir, p, q - p);
} else {
snprintf(info->dataDir,
sizeof info->dataDir,
"/data/user/%d/%s",
userId,
pkgName);
p = q;
}
/* skip spaces */
if (parse_spaces(&p, end) < 0)

View file

@ -33,9 +33,11 @@ typedef struct {
char seinfo[PATH_MAX];
} PackageInfo;
/* see documentation in package.c for these functiosn */
/* see documentation in package.c for these functions */
extern int get_package_info(const char* packageName, PackageInfo* info);
extern int get_package_info(const char* packageName,
uid_t userId,
PackageInfo* info);
extern int check_data_path(const char* dataDir, uid_t uid);

View file

@ -102,13 +102,14 @@ panic(const char* format, ...)
static void
usage(void)
{
panic("Usage:\n " PROGNAME " <package-name> <command> [<args>]\n");
panic("Usage:\n " PROGNAME " <package-name> [--user <uid>] <command> [<args>]\n");
}
int main(int argc, char **argv)
{
const char* pkgname;
int myuid, uid, gid;
uid_t myuid, uid, gid, userAppId = 0;
int commandArgvOfs = 2, userId = 0;
PackageInfo info;
struct __user_cap_header_struct capheader;
struct __user_cap_data_struct capdata[2];
@ -136,14 +137,31 @@ int main(int argc, char **argv)
panic("Could not set capabilities: %s\n", strerror(errno));
}
/* retrieve package information from system (does setegid) */
pkgname = argv[1];
if (get_package_info(pkgname, &info) < 0) {
/* get user_id from command line if provided */
if ((argc >= 4) && !strcmp(argv[2], "--user")) {
userId = atoi(argv[3]);
if (userId < 0)
panic("Negative user id %d is provided\n", userId);
commandArgvOfs += 2;
}
/* retrieve package information from system (does setegid) */
if (get_package_info(pkgname, userId, &info) < 0) {
panic("Package '%s' is unknown\n", pkgname);
}
/* verify that user id is not too big. */
if ((UID_MAX - info.uid) / AID_USER < (uid_t)userId) {
panic("User id %d is too big\n", userId);
}
/* calculate user app ID. */
userAppId = (AID_USER * userId) + info.uid;
/* reject system packages */
if (info.uid < AID_APP) {
if (userAppId < AID_APP) {
panic("Package '%s' is not an application\n", pkgname);
}
@ -153,14 +171,14 @@ int main(int argc, char **argv)
}
/* check that the data directory path is valid */
if (check_data_path(info.dataDir, info.uid) < 0) {
if (check_data_path(info.dataDir, userAppId) < 0) {
panic("Package '%s' has corrupt installation\n", pkgname);
}
/* Ensure that we change all real/effective/saved IDs at the
* same time to avoid nasty surprises.
*/
uid = gid = info.uid;
uid = gid = userAppId;
if(setresgid(gid,gid,gid) || setresuid(uid,uid,uid)) {
panic("Permission denied\n");
}
@ -181,8 +199,9 @@ int main(int argc, char **argv)
}
/* User specified command for exec. */
if ((argc >= 3) && (execvp(argv[2], argv+2) < 0)) {
panic("exec failed for %s: %s\n", argv[2], strerror(errno));
if ((argc >= commandArgvOfs + 1) &&
(execvp(argv[commandArgvOfs], argv+commandArgvOfs) < 0)) {
panic("exec failed for %s: %s\n", argv[commandArgvOfs], strerror(errno));
}
/* Default exec shell. */