init: refuse to start process if domain transition not defined

When SELinux is in enforcing mode, any process executed by
init must have a domain transition defined. See
https://android-review.googlesource.com/108640 for details. This
prevents an executable spawned by init from remaining in init's
(very powerful) SELinux domain.

However, this is only enforced when SELinux is in enforcing mode.
During new device bringup, it's common to run an Android device
in globally permissive mode. In globally permissive mode, SELinux
denials are logged only, but otherwise ignored. If appropriate
SELinux domain transitions are not defined from init to init spawned
processes, this could cause misleading SELinux denials attributed
to init instead of the child process.

To help address these misleading denials, modify init to not spawn
processes unless a domain transition is defined. This essentially
enforces the rules in https://android-review.googlesource.com/108640
on both permissive and enforcing kernels.

While I'm here, change some "freecon()" calls to "free()", with the
long term goal of deleting freecon() entirely.

Change-Id: I3ef3a372bb85df61a3f6234cb1113cc25fc6506a
This commit is contained in:
Nick Kralevich 2015-07-16 10:49:51 -07:00
parent 759717ee63
commit 4800dbf1da
1 changed files with 10 additions and 6 deletions

View File

@ -239,16 +239,20 @@ void service_start(struct service *svc, const char *dynamic_args)
rc = getfilecon(svc->args[0], &fcon);
if (rc < 0) {
ERROR("could not get context while starting '%s'\n", svc->name);
freecon(mycon);
free(mycon);
return;
}
rc = security_compute_create(mycon, fcon, string_to_security_class("process"), &scon);
if (rc == 0 && !strcmp(scon, mycon)) {
ERROR("Warning! Service %s needs a SELinux domain defined; please fix!\n", svc->name);
ERROR("Service %s does not have a SELinux domain defined.\n", svc->name);
free(mycon);
free(fcon);
free(scon);
return;
}
freecon(mycon);
freecon(fcon);
free(mycon);
free(fcon);
if (rc < 0) {
ERROR("could not get context while starting '%s'\n", svc->name);
return;
@ -285,7 +289,7 @@ void service_start(struct service *svc, const char *dynamic_args)
}
}
freecon(scon);
free(scon);
scon = NULL;
if (svc->writepid_files_) {
@ -374,7 +378,7 @@ void service_start(struct service *svc, const char *dynamic_args)
_exit(127);
}
freecon(scon);
free(scon);
if (pid < 0) {
ERROR("failed to start '%s'\n", svc->name);