One theory: Android uses prctl(PR_SET_NO_NEW_PRIVS) to prevent gaining additional privileges across an exec. See
Android L: https://android-review.googlesource.com/92350 Prior versions: https://android.googlesource.com/platform/dalvik/+/b64e9cb For SELinux, this inhibits domain transitions, as an exec domain transition could cause an app to gain privileges, similar to a setuid root program. -- Nick On Thu, Oct 23, 2014 at 6:29 PM, Chris Stone < [email protected]> wrote: > I have written a new daemon for Android that gets started by zygote. It is > actually part of our namespaces security extensions, and the daemon is the > init process for each namespace. So, when zygote is launching an app, it > decides if a new namespace needs to be created, and if so, it execve's the > init process for that namespace, then adds the app to it. Up to now, to > keep things simple, this init process runs in the zygote seandroid domain, > because zygote starts it. However, as I continue to enhance this work, I am > now trying to change this so the init process runs in it's own selinux > domain, so we don't have to give unneeded permissions to zygote. > > The namespaceinit domain is defined as follows: > > # namespace init process > type namespaceinit, domain; > type namespaceinit_exec, exec_type, file_type; > > typeattribute namespaceinit mlstrustedsubject; > > net_domain(namespaceinit) > > domain_auto_trans(zygote, namespaceinit_exec, namespaceinit) > tmpfs_domain(namespaceinit) > > type_transition namespaceinit socket_device:sock_file namespace_socket; > > allow namespaceinit self:capability { net_admin net_raw }; > > > > I have also added the following to the file_contexts file: > /system/bin/namespaceInit u:object_r:namespaceinit_exec:s0 > > And this to file.te: > type namespace_socket, file_type; > > > > The function that creates a namespace, and launches the > /system/bin/namespaceInit process is as follows (note that this function is > invoked in the zygote domain from the dalvik vm): > static int create_namespace(userid_t uid) > { > pid_t initPid, ppid; > char socketName[UNIX_PATH_MAX]; > char indexNum[12]; > char *argv[4] = {"/system/bin/namespaceInit", socketName, > indexNum, NULL}; > int retries=0, tfd, i; > struct timespec req; > char *environ[] = { NULL }; > > req.tv_sec = MALLOC_DELAY_SECS; > req.tv_nsec = MALLOC_DELAY_NSECS; > > // remember the parent pid so we can move original pid back to parent > pid namespace > ppid = getppid(); > > while (retries++ < MALLOC_RETRIES) { > // Move into a new pid namespace > if (unshare(CLONE_NEWPID) == -1) { > ALOG(LOG_ERROR, logCatTag, "%s:%d Error creating init process > - %s.\n", __FUNCTION__, __LINE__, strerror(errno)); > return -1 * errno; > } > initPid = fork(); > > if (initPid == 0) { > // Set a new session leader > if (setsid() < 0) { > ALOG(LOG_ERROR, logCatTag, "%s:%d Error setting new > session id - %s.\n", __FUNCTION__, __LINE__, strerror(errno)); > } > // Move child into new mount namespace > if (unshare(CLONE_NEWNS) == -1) { > ALOG(LOG_ERROR, logCatTag, "%s:%d Error creating init > process mount namespace - %s.\n", __FUNCTION__, __LINE__, strerror(errno)); > } else { > > // mount a new /proc filesystem > if (mount("none", "/proc", "proc", 0, NULL) == -1) { > ALOG(LOG_ERROR, logCatTag, "%s:%d Error %s mounting > /proc filesystem.\n", __FUNCTION__, __LINE__, strerror(errno)); > } > > // mount emulated storage > if (uid == 2) > mountEmulatedStorage(0); > else > mountEmulatedStorage(uid); > } > > // Move child into new net namespace > if (!namespaceData->netdisabled) { > if (unshare(CLONE_NEWNET) == -1) { > ALOG(LOG_ERROR, logCatTag, "%s:%d Error creating init > process net namespace - %s.\n", __FUNCTION__, __LINE__, strerror(errno)); > } > } > > // Now that we are in a new pid and mount namespace, exec the > actual init process > // This gets rid of all the overhead of zygote in the init > process, and leaves a very > // lean and mean process running. > snprintf(socketName, UNIX_PATH_MAX, "%s/namespaceInit%d", > socketDir, uid); > snprintf(indexNum, 12, "%d", uid); > execve(argv[0], argv, environ); > > // It is an error if we get here. > ALOG(LOG_ERROR, logCatTag, "%s:%d namespaceInit process > terminated.\n", __FUNCTION__, __LINE__); > return -1; > } else { > // Move parent back to original parent pid namespace > unset_namespace(ppid, NAMESPACE_TYPE_PID); > > if (initPid == -1) { > if (((errno == ENOMEM) && (retries == MALLOC_RETRIES)) || > (errno != ENOMEM)) { > ALOG(LOG_ERROR, logCatTag, "%s:%d Error creating init > process - %s.\n", __FUNCTION__, __LINE__, strerror(errno)); > return errno; > } else { > // Give Android a chance to release some memory > while ((nanosleep(&req, &req) == -1) && (errno == > EINTR)); > } > } else { > namespaceData->namespaceTable[uid].pid = initPid; > namespaceData->namespaceTable[uid].id = uid; > snprintf(socketName, UNIX_PATH_MAX, "%s/namespaceInit%d", > socketDir, uid); > > memset(&namespaceData->namespaceTable[uid].initServiceAddr, 0, > sizeof(namespaceData->namespaceTable[uid].initServiceAddr)); > > namespaceData->namespaceTable[uid].initServiceAddr.sun_family = AF_UNIX; > > strcpy(namespaceData->namespaceTable[uid].initServiceAddr.sun_path, > socketName); > > // Wait for init process to be ready > if (sem_wait(&namespaceData->clone_sem) == -1) { > ALOG(LOG_ERROR, logCatTag, "%s:%d Error waiting on > namespace semaphore - %s.\n", __FUNCTION__, __LINE__, strerror(errno)); > return -1 * errno; > } > ALOG(LOG_INFO, logCatTag, "%s:%d Namespace init process > gets pid=%d\n", __FUNCTION__, __LINE__, > namespaceData->namespaceTable[uid].pid); > > // Configure ethernet access in network namespace > if (!namespaceData->netdisabled) { > mntbndnet_uid(initPid, uid); > return netns_connect_setup(uid); > } > return 0; > } > } > } > > return 0; > } > > > But, the /system/bin/namespaceInit process remains in the zygote domain. > When I run the audit.log through audit2allow, I get the following: > allow zygote namespaceinit_exec:file execute_no_trans; > > This seems to indicate that zygote wants to execute without transitioning, > but I thought I explicitly allowed transitioning with the > domain_auto_trans(zygote, namespaceinit_exec, namespaceinit) statement. > > What am I missing? How come the /system/bin/namespaceInit process is not > transitioning into the namespaceinit domain? > > Cheers, > Chris > > > _______________________________________________ > Seandroid-list mailing list > [email protected] > To unsubscribe, send email to [email protected]. > To get help, send an email containing "help" to > [email protected]. > -- Nick Kralevich | Android Security | [email protected] | 650.214.4037
_______________________________________________ Seandroid-list mailing list [email protected] To unsubscribe, send email to [email protected]. To get help, send an email containing "help" to [email protected].
