init: cleanup environment handling

Init keep its own copy of the environment that it uses for execve when
starting services.  This is unnecessary however as libc already has
functions that mutate the environment and the environment that init
uses is clean for starting services.  This change removes init's copy
of the environment and uses the libc functions instead.

This also makes small clean-up to the way the Service class stores
service specific environment variables.

Test: boot bullhead
Change-Id: I7c98a0b7aac9fa8f195ae33bd6a7515bb56faf78
This commit is contained in:
Tom Cherry 2017-08-22 15:41:03 -07:00
parent 7f16cad877
commit 6de21f1112
7 changed files with 11 additions and 67 deletions

View file

@ -159,8 +159,8 @@ static Result<Success> do_exec_start(const std::vector<std::string>& args) {
}
static Result<Success> do_export(const std::vector<std::string>& args) {
if (!add_environment(args[1].c_str(), args[2].c_str())) {
return Error();
if (setenv(args[1].c_str(), args[2].c_str(), 1) == -1) {
return ErrnoError() << "setenv() failed";
}
return Success();
}

View file

@ -28,7 +28,6 @@
#include <cutils/android_get_control_file.h>
#include <cutils/sockets.h>
#include "init.h"
#include "util.h"
namespace android {
@ -62,7 +61,7 @@ void DescriptorInfo::CreateAndPublish(const std::string& globalContext) const {
[] (char& c) { c = isalnum(c) ? c : '_'; });
std::string val = std::to_string(fd);
add_environment(publishedName.c_str(), val.c_str());
setenv(publishedName.c_str(), val.c_str(), 1);
// make sure we don't close on exec
fcntl(fd, F_SETFD, 0);

View file

@ -71,8 +71,6 @@ static char qemu[32];
std::string default_console = "/dev/console";
const char *ENV[32];
static int epoll_fd = -1;
static std::unique_ptr<Timer> waiting_for_prop(nullptr);
@ -126,38 +124,6 @@ void register_epoll_handler(int fd, void (*fn)()) {
}
}
/* add_environment - add "key=value" to the current environment */
int add_environment(const char *key, const char *val)
{
size_t n;
size_t key_len = strlen(key);
/* The last environment entry is reserved to terminate the list */
for (n = 0; n < (arraysize(ENV) - 1); n++) {
/* Delete any existing entry for this key */
if (ENV[n] != NULL) {
size_t entry_key_len = strcspn(ENV[n], "=");
if ((entry_key_len == key_len) && (strncmp(ENV[n], key, entry_key_len) == 0)) {
free((char*)ENV[n]);
ENV[n] = NULL;
}
}
/* Add entry if a free slot is available */
if (ENV[n] == NULL) {
char* entry;
asprintf(&entry, "%s=%s", key, val);
ENV[n] = entry;
return 0;
}
}
LOG(ERROR) << "No env. room to store: '" << key << "':'" << val << "'";
return -1;
}
bool start_waiting_for_property(const char *name, const char *value)
{
if (waiting_for_prop) {
@ -429,8 +395,6 @@ int main(int argc, char** argv) {
install_reboot_signal_handlers();
}
add_environment("PATH", _PATH_DEFPATH);
bool is_first_stage = (getenv("INIT_SECOND_STAGE") == nullptr);
if (is_first_stage) {
@ -439,6 +403,8 @@ int main(int argc, char** argv) {
// Clear the umask.
umask(0);
clearenv();
setenv("PATH", _PATH_DEFPATH, 1);
// Get the basic filesystem setup we need put together in the initramdisk
// on / and then we'll let the rc file figure out the rest.
mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");

View file

@ -30,9 +30,7 @@ namespace init {
// Note: These globals are *only* valid in init, so they should not be used in ueventd,
// watchdogd, or any files that may be included in those, such as devices.cpp and util.cpp.
// TODO: Have an Init class and remove all globals.
extern const char *ENV[32];
extern std::string default_console;
extern std::vector<std::string> late_import_paths;
Parser CreateParser(ActionManager& action_manager, ServiceList& service_list);
@ -43,8 +41,6 @@ void property_changed(const std::string& name, const std::string& value);
void register_epoll_handler(int fd, void (*fn)());
int add_environment(const char* key, const char* val);
bool start_waiting_for_property(const char *name, const char *value);
void DumpState();

View file

@ -48,7 +48,6 @@
#include "selinux.h"
#include <fcntl.h>
#include <paths.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
@ -126,8 +125,7 @@ bool ForkExecveAndWaitForCompletion(const char* filename, char* const argv[]) {
}
TEMP_FAILURE_RETRY(close(pipe_fds[1]));
const char* envp[] = {_PATH_DEFPATH, nullptr};
if (execve(filename, argv, (char**)envp) == -1) {
if (execv(filename, argv) == -1) {
PLOG(ERROR) << "Failed to execve " << filename;
return false;
}

View file

@ -147,14 +147,6 @@ static void ExpandArgs(const std::vector<std::string>& args, std::vector<char*>*
strs->push_back(nullptr);
}
ServiceEnvironmentInfo::ServiceEnvironmentInfo() {
}
ServiceEnvironmentInfo::ServiceEnvironmentInfo(const std::string& name,
const std::string& value)
: name(name), value(value) {
}
unsigned long Service::next_start_order_ = 1;
bool Service::is_exec_service_running_ = false;
@ -507,7 +499,7 @@ Result<Success> Service::ParseSeclabel(const std::vector<std::string>& args) {
}
Result<Success> Service::ParseSetenv(const std::vector<std::string>& args) {
envvars_.emplace_back(args[1], args[2]);
environment_vars_.emplace_back(args[1], args[2]);
return Success();
}
@ -723,8 +715,8 @@ bool Service::Start() {
SetUpPidNamespace(name_);
}
for (const auto& ei : envvars_) {
add_environment(ei.name.c_str(), ei.value.c_str());
for (const auto& [key, value] : environment_vars_) {
setenv(key.c_str(), value.c_str(), 1);
}
std::for_each(descriptors_.begin(), descriptors_.end(),
@ -779,7 +771,7 @@ bool Service::Start() {
std::vector<char*> strs;
ExpandArgs(args_, &strs);
if (execve(strs[0], (char**) &strs[0], (char**) ENV) < 0) {
if (execv(strs[0], (char**)&strs[0]) < 0) {
PLOG(ERROR) << "cannot execve('" << strs[0] << "')";
}

View file

@ -57,13 +57,6 @@
namespace android {
namespace init {
struct ServiceEnvironmentInfo {
ServiceEnvironmentInfo();
ServiceEnvironmentInfo(const std::string& name, const std::string& value);
std::string name;
std::string value;
};
class Service {
public:
Service(const std::string& name, const std::vector<std::string>& args);
@ -178,7 +171,7 @@ class Service {
std::string seclabel_;
std::vector<std::unique_ptr<DescriptorInfo>> descriptors_;
std::vector<ServiceEnvironmentInfo> envvars_;
std::vector<std::pair<std::string, std::string>> environment_vars_;
Action onrestart_; // Commands to execute on restart.