Merge "Remove netcfg's unused options."
diff --git a/init/Android.mk b/init/Android.mk
index 4df4489..606c199 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -17,7 +17,11 @@
ueventd_parser.c \
watchdogd.c
-LOCAL_CFLAGS += -Wno-unused-parameter
+LOCAL_CFLAGS += \
+ -std=gnu11 \
+ -Wall \
+ -Werror -Wno-error=deprecated-declarations \
+ -Wno-unused-parameter \
ifeq ($(strip $(INIT_BOOTCHART)),true)
LOCAL_SRC_FILES += bootchart.c
diff --git a/init/bootchart.c b/init/bootchart.c
index a514261..27c7f65 100644
--- a/init/bootchart.c
+++ b/init/bootchart.c
@@ -66,7 +66,7 @@
proc_read(const char* filename, char* buff, size_t buffsize)
{
int len = 0;
- int fd = open(filename, O_RDONLY);
+ int fd = open(filename, O_RDONLY | O_CLOEXEC);
if (fd >= 0) {
len = unix_read(fd, buff, buffsize-1);
close(fd);
@@ -144,7 +144,7 @@
struct tm now = *localtime(&now_t);
strftime(date, sizeof(date), "%x %X", &now);
- out = fopen( LOG_HEADER, "w" );
+ out = fopen( LOG_HEADER, "we" );
if (out == NULL)
return;
@@ -170,12 +170,6 @@
}
static void
-close_on_exec(int fd)
-{
- fcntl(fd, F_SETFD, FD_CLOEXEC);
-}
-
-static void
open_log_file(int* plogfd, const char* logfile)
{
int logfd = *plogfd;
@@ -183,12 +177,11 @@
/* create log file if needed */
if (logfd < 0)
{
- logfd = open(logfile,O_WRONLY|O_CREAT|O_TRUNC,0755);
+ logfd = open(logfile,O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC,0755);
if (logfd < 0) {
*plogfd = -2;
return;
}
- close_on_exec(logfd);
*plogfd = logfd;
}
}
@@ -220,9 +213,8 @@
do_log_uptime(log);
/* append file content */
- fd = open(procfile,O_RDONLY);
+ fd = open(procfile,O_RDONLY|O_CLOEXEC);
if (fd >= 0) {
- close_on_exec(fd);
for (;;) {
int ret;
ret = unix_read(fd, buff, sizeof(buff));
@@ -264,7 +256,7 @@
/* read process stat line */
snprintf(filename,sizeof(filename),"/proc/%d/stat",pid);
- fd = open(filename,O_RDONLY);
+ fd = open(filename,O_RDONLY|O_CLOEXEC);
if (fd >= 0) {
len = unix_read(fd, buff, sizeof(buff)-1);
close(fd);
@@ -340,7 +332,7 @@
/* create kernel process accounting file */
{
- int fd = open( LOG_ACCT, O_WRONLY|O_CREAT|O_TRUNC,0644);
+ int fd = open( LOG_ACCT, O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC,0644);
if (fd >= 0) {
close(fd);
acct( LOG_ACCT );
diff --git a/init/builtins.c b/init/builtins.c
index 76c0a18..2521daf 100644
--- a/init/builtins.c
+++ b/init/builtins.c
@@ -59,7 +59,7 @@
{
int fd, ret, len;
- fd = open(path, O_WRONLY|O_CREAT|O_NOFOLLOW, 0600);
+ fd = open(path, O_WRONLY|O_CREAT|O_NOFOLLOW|O_CLOEXEC, 0600);
if (fd < 0)
return -errno;
@@ -99,7 +99,7 @@
{
int fd, ret;
- fd = open("/dev/tty0", O_RDWR | O_SYNC);
+ fd = open("/dev/tty0", O_RDWR | O_SYNC | O_CLOEXEC);
if (fd < 0)
return -1;
@@ -205,6 +205,67 @@
return -1;
}
+int do_execonce(int nargs, char **args)
+{
+ pid_t child;
+ int child_status = 0;
+ static int already_done;
+
+ if (already_done) {
+ return -1;
+ }
+ already_done = 1;
+ if (!(child = fork())) {
+ /*
+ * Child process.
+ */
+ zap_stdio();
+ char *exec_args[100];
+ size_t num_process_args = nargs;
+
+ memset(exec_args, 0, sizeof(exec_args));
+ if (num_process_args > ARRAY_SIZE(exec_args) - 1) {
+ ERROR("exec called with %zu args, limit is %zu", num_process_args,
+ ARRAY_SIZE(exec_args) - 1);
+ _exit(1);
+ }
+ for (size_t i = 1; i < num_process_args; i++)
+ exec_args[i - 1] = args[i];
+
+ if (execv(exec_args[0], exec_args) == -1) {
+ ERROR("Failed to execv '%s' (%s)", exec_args[0], strerror(errno));
+ _exit(1);
+ }
+ ERROR("Returned from execv()!");
+ _exit(1);
+ }
+
+ /*
+ * Parent process.
+ */
+ if (child == -1) {
+ ERROR("Fork failed\n");
+ return -1;
+ }
+
+ if (TEMP_FAILURE_RETRY(waitpid(child, &child_status, 0)) == -1) {
+ ERROR("waitpid(): failed (%s)\n", strerror(errno));
+ return -1;
+ }
+
+ if (WIFSIGNALED(child_status)) {
+ INFO("Child exited due to signal %d\n", WTERMSIG(child_status));
+ return -1;
+ } else if (WIFEXITED(child_status)) {
+ INFO("Child exited normally (exit code %d)\n", WEXITSTATUS(child_status));
+ return WEXITSTATUS(child_status);
+ }
+
+ ERROR("Abnormal child process exit\n");
+
+ return -1;
+}
+
int do_export(int nargs, char **args)
{
return add_environment(args[1], args[2]);
@@ -370,14 +431,14 @@
struct loop_info info;
mode = (flags & MS_RDONLY) ? O_RDONLY : O_RDWR;
- fd = open(source + 5, mode);
+ fd = open(source + 5, mode | O_CLOEXEC);
if (fd < 0) {
return -1;
}
for (n = 0; ; n++) {
sprintf(tmp, "/dev/block/loop%d", n);
- loop = open(tmp, mode);
+ loop = open(tmp, mode | O_CLOEXEC);
if (loop < 0) {
close(fd);
return -1;
@@ -423,7 +484,7 @@
static int wipe_data_via_recovery()
{
mkdir("/cache/recovery", 0700);
- int fd = open("/cache/recovery/command", O_RDWR|O_CREAT|O_TRUNC, 0600);
+ int fd = open("/cache/recovery/command", O_RDWR|O_CREAT|O_TRUNC|O_CLOEXEC, 0600);
if (fd >= 0) {
write(fd, "--wipe_data\n", strlen("--wipe_data\n") + 1);
write(fd, "--reason=wipe_data_via_recovery\n", strlen("--reason=wipe_data_via_recovery\n") + 1);
@@ -709,10 +770,10 @@
if (stat(args[1], &info) < 0)
return -1;
- if ((fd1 = open(args[1], O_RDONLY)) < 0)
+ if ((fd1 = open(args[1], O_RDONLY|O_CLOEXEC)) < 0)
goto out_err;
- if ((fd2 = open(args[2], O_WRONLY|O_CREAT|O_TRUNC, 0660)) < 0)
+ if ((fd2 = open(args[2], O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0660)) < 0)
goto out_err;
if (!(buffer = malloc(info.st_size)))
diff --git a/init/devices.c b/init/devices.c
index dde43df..0de92f5 100644
--- a/init/devices.c
+++ b/init/devices.c
@@ -865,20 +865,20 @@
if (l == -1)
goto data_free_out;
- loading_fd = open(loading, O_WRONLY);
+ loading_fd = open(loading, O_WRONLY|O_CLOEXEC);
if(loading_fd < 0)
goto file_free_out;
- data_fd = open(data, O_WRONLY);
+ data_fd = open(data, O_WRONLY|O_CLOEXEC);
if(data_fd < 0)
goto loading_close_out;
try_loading_again:
- fw_fd = open(file1, O_RDONLY);
+ fw_fd = open(file1, O_RDONLY|O_CLOEXEC);
if(fw_fd < 0) {
- fw_fd = open(file2, O_RDONLY);
+ fw_fd = open(file2, O_RDONLY|O_CLOEXEC);
if (fw_fd < 0) {
- fw_fd = open(file3, O_RDONLY);
+ fw_fd = open(file3, O_RDONLY|O_CLOEXEC);
if (fw_fd < 0) {
if (booting) {
/* If we're not fully booted, we may be missing
@@ -1044,7 +1044,7 @@
coldboot("/sys/block");
coldboot("/sys/devices");
t1 = get_usecs();
- fd = open(COLDBOOT_DONE, O_WRONLY|O_CREAT, 0000);
+ fd = open(COLDBOOT_DONE, O_WRONLY|O_CREAT|O_CLOEXEC, 0000);
close(fd);
log_event_print("coldboot %ld uS\n", ((long) (t1 - t0)));
// t0 & t1 are unused if the log isn't doing anything.
diff --git a/init/init.c b/init/init.c
index 7ddab80..096d898 100644
--- a/init/init.c
+++ b/init/init.c
@@ -126,7 +126,7 @@
return -1;
}
-static void zap_stdio(void)
+void zap_stdio(void)
{
int fd;
fd = open("/dev/null", O_RDWR);
@@ -540,17 +540,35 @@
return (list_tail(&act->commands) == &cmd->clist);
}
+
+void build_triggers_string(char *name_str, int length, struct action *cur_action) {
+ struct listnode *node;
+ struct trigger *cur_trigger;
+
+ list_for_each(node, &cur_action->triggers) {
+ cur_trigger = node_to_item(node, struct trigger, nlist);
+ if (node != cur_action->triggers.next) {
+ strlcat(name_str, " " , length);
+ }
+ strlcat(name_str, cur_trigger->name , length);
+ }
+}
+
void execute_one_command(void)
{
int ret, i;
char cmd_str[256] = "";
+ char name_str[256] = "";
if (!cur_action || !cur_command || is_last_command(cur_action, cur_command)) {
cur_action = action_remove_queue_head();
cur_command = NULL;
if (!cur_action)
return;
- INFO("processing action %p (%s)\n", cur_action, cur_action->name);
+
+ build_triggers_string(name_str, sizeof(name_str), cur_action);
+
+ INFO("processing action %p (%s)\n", cur_action, name_str);
cur_command = get_first_command(cur_action);
} else {
cur_command = get_next_command(cur_action, cur_command);
@@ -568,7 +586,7 @@
}
}
INFO("command '%s' action=%s status=%d (%s:%d)\n",
- cmd_str, cur_action ? cur_action->name : "", ret, cur_command->filename,
+ cmd_str, cur_action ? name_str : "", ret, cur_command->filename,
cur_command->line);
}
}
@@ -608,7 +626,7 @@
size_t total_bytes_written = 0;
hwrandom_fd = TEMP_FAILURE_RETRY(
- open("/dev/hw_random", O_RDONLY | O_NOFOLLOW));
+ open("/dev/hw_random", O_RDONLY | O_NOFOLLOW | O_CLOEXEC));
if (hwrandom_fd == -1) {
if (errno == ENOENT) {
ERROR("/dev/hw_random not found\n");
@@ -621,7 +639,7 @@
}
urandom_fd = TEMP_FAILURE_RETRY(
- open("/dev/urandom", O_WRONLY | O_NOFOLLOW));
+ open("/dev/urandom", O_WRONLY | O_NOFOLLOW | O_CLOEXEC));
if (urandom_fd == -1) {
ERROR("Failed to open /dev/urandom: %s\n", strerror(errno));
goto ret;
@@ -675,12 +693,12 @@
snprintf(console_name, sizeof(console_name), "/dev/%s", console);
}
- fd = open(console_name, O_RDWR);
+ fd = open(console_name, O_RDWR | O_CLOEXEC);
if (fd >= 0)
have_console = 1;
close(fd);
- fd = open("/dev/tty0", O_WRONLY);
+ fd = open("/dev/tty0", O_WRONLY | O_CLOEXEC);
if (fd >= 0) {
const char *msg;
msg = "\n"
@@ -1011,7 +1029,7 @@
mount("sysfs", "/sys", "sysfs", 0, NULL);
/* indicate that booting is in progress to background fw loaders, etc */
- close(open("/dev/.booting", O_WRONLY | O_CREAT, 0000));
+ close(open("/dev/.booting", O_WRONLY | O_CREAT | O_CLOEXEC, 0000));
/* We must have some place other than / to create the
* device nodes for kmsg and null, otherwise we won't
diff --git a/init/init.h b/init/init.h
index a7615a3..654a80b 100644
--- a/init/init.h
+++ b/init/init.h
@@ -37,6 +37,11 @@
char *args[1];
};
+struct trigger {
+ struct listnode nlist;
+ const char *name;
+};
+
struct action {
/* node in list of all actions */
struct listnode alist;
@@ -46,12 +51,15 @@
struct listnode tlist;
unsigned hash;
- const char *name;
+ /* list of actions which triggers the commands*/
+ struct listnode triggers;
struct listnode commands;
struct command *current;
};
+void build_triggers_string(char *name_str, int length, struct action *cur_action);
+
struct socketinfo {
struct socketinfo *next;
const char *name;
@@ -141,5 +149,6 @@
extern struct selabel_handle *sehandle;
extern struct selabel_handle *sehandle_prop;
extern int selinux_reload_policy(void);
+void zap_stdio(void);
#endif /* _INIT_INIT_H */
diff --git a/init/init_parser.c b/init/init_parser.c
index 2b4db8e..02cbf3d 100644
--- a/init/init_parser.c
+++ b/init/init_parser.c
@@ -97,6 +97,7 @@
case 'e':
if (!strcmp(s, "nable")) return K_enable;
if (!strcmp(s, "xec")) return K_exec;
+ if (!strcmp(s, "xeconce")) return K_execonce;
if (!strcmp(s, "xport")) return K_export;
break;
case 'g':
@@ -499,77 +500,92 @@
void action_for_each_trigger(const char *trigger,
void (*func)(struct action *act))
{
- struct listnode *node;
+ struct listnode *node, *node2;
struct action *act;
+ struct trigger *cur_trigger;
+
list_for_each(node, &action_list) {
act = node_to_item(node, struct action, alist);
- if (!strcmp(act->name, trigger)) {
- func(act);
+ list_for_each(node2, &act->triggers) {
+ cur_trigger = node_to_item(node2, struct trigger, nlist);
+ if (!strcmp(cur_trigger->name, trigger)) {
+ func(act);
+ }
}
}
}
+
void queue_property_triggers(const char *name, const char *value)
{
- struct listnode *node;
+ struct listnode *node, *node2;
struct action *act;
+ struct trigger *cur_trigger;
+ bool match;
+ int name_length;
+
list_for_each(node, &action_list) {
act = node_to_item(node, struct action, alist);
- if (!strncmp(act->name, "property:", strlen("property:"))) {
- const char *test = act->name + strlen("property:");
- int name_length = strlen(name);
+ match = !name;
+ list_for_each(node2, &act->triggers) {
+ cur_trigger = node_to_item(node2, struct trigger, nlist);
+ if (!strncmp(cur_trigger->name, "property:", strlen("property:"))) {
+ const char *test = cur_trigger->name + strlen("property:");
+ if (!match) {
+ name_length = strlen(name);
+ if (!strncmp(name, test, name_length) &&
+ test[name_length] == '=' &&
+ (!strcmp(test + name_length + 1, value) ||
+ !strcmp(test + name_length + 1, "*"))) {
+ match = true;
+ continue;
+ }
+ } else {
+ const char* equals = strchr(test, '=');
+ if (equals) {
+ char prop_name[PROP_NAME_MAX + 1];
+ char value[PROP_VALUE_MAX];
+ int length = equals - test;
+ if (length <= PROP_NAME_MAX) {
+ int ret;
+ memcpy(prop_name, test, length);
+ prop_name[length] = 0;
- if (!strncmp(name, test, name_length) &&
- test[name_length] == '=' &&
- (!strcmp(test + name_length + 1, value) ||
- !strcmp(test + name_length + 1, "*"))) {
- action_add_queue_tail(act);
- }
+ /* does the property exist, and match the trigger value? */
+ ret = property_get(prop_name, value);
+ if (ret > 0 && (!strcmp(equals + 1, value) ||
+ !strcmp(equals + 1, "*"))) {
+ continue;
+ }
+ }
+ }
+ }
+ }
+ match = false;
+ break;
+ }
+ if (match) {
+ action_add_queue_tail(act);
}
}
}
void queue_all_property_triggers()
{
- struct listnode *node;
- struct action *act;
- list_for_each(node, &action_list) {
- act = node_to_item(node, struct action, alist);
- if (!strncmp(act->name, "property:", strlen("property:"))) {
- /* parse property name and value
- syntax is property:<name>=<value> */
- const char* name = act->name + strlen("property:");
- const char* equals = strchr(name, '=');
- if (equals) {
- char prop_name[PROP_NAME_MAX + 1];
- char value[PROP_VALUE_MAX];
- int length = equals - name;
- if (length > PROP_NAME_MAX) {
- ERROR("property name too long in trigger %s", act->name);
- } else {
- int ret;
- memcpy(prop_name, name, length);
- prop_name[length] = 0;
-
- /* does the property exist, and match the trigger value? */
- ret = property_get(prop_name, value);
- if (ret > 0 && (!strcmp(equals + 1, value) ||
- !strcmp(equals + 1, "*"))) {
- action_add_queue_tail(act);
- }
- }
- }
- }
- }
+ queue_property_triggers(NULL, NULL);
}
void queue_builtin_action(int (*func)(int nargs, char **args), char *name)
{
struct action *act;
struct command *cmd;
+ struct trigger *cur_trigger;
act = calloc(1, sizeof(*act));
- act->name = name;
+ cur_trigger = calloc(1, sizeof(*cur_trigger));
+ cur_trigger->name = name;
+ list_init(&act->triggers);
+ list_add_tail(&act->triggers, &cur_trigger->nlist);
list_init(&act->commands);
list_init(&act->qlist);
@@ -611,6 +627,7 @@
static void *parse_service(struct parse_state *state, int nargs, char **args)
{
struct service *svc;
+ struct trigger *cur_trigger;
if (nargs < 3) {
parse_error(state, "services must have a name and a program\n");
return 0;
@@ -635,9 +652,12 @@
svc->name = args[1];
svc->classname = "default";
memcpy(svc->args, args + 2, sizeof(char*) * nargs);
+ cur_trigger = calloc(1, sizeof(*cur_trigger));
svc->args[nargs] = 0;
svc->nargs = nargs;
- svc->onrestart.name = "onrestart";
+ list_init(&svc->onrestart.triggers);
+ cur_trigger->name = "onrestart";
+ list_add_tail(&svc->onrestart.triggers, &cur_trigger->nlist);
list_init(&svc->onrestart.commands);
list_add_tail(&service_list, &svc->slist);
return svc;
@@ -821,16 +841,29 @@
static void *parse_action(struct parse_state *state, int nargs, char **args)
{
struct action *act;
+ struct trigger *cur_trigger;
+ int i;
if (nargs < 2) {
parse_error(state, "actions must have a trigger\n");
return 0;
}
- if (nargs > 2) {
- parse_error(state, "actions may not have extra parameters\n");
- return 0;
- }
+
act = calloc(1, sizeof(*act));
- act->name = args[1];
+ list_init(&act->triggers);
+
+ for (i = 1; i < nargs; i++) {
+ if (!(i % 2)) {
+ if (strcmp(args[i], "&&")) {
+ parse_error(state, "& is the only symbol allowed to concatenate actions\n");
+ return 0;
+ } else
+ continue;
+ }
+ cur_trigger = calloc(1, sizeof(*cur_trigger));
+ cur_trigger->name = args[i];
+ list_add_tail(&act->triggers, &cur_trigger->nlist);
+ }
+
list_init(&act->commands);
list_init(&act->qlist);
list_add_tail(&action_list, &act->alist);
diff --git a/init/keychords.c b/init/keychords.c
index 4a64042..5a9e45f 100644
--- a/init/keychords.c
+++ b/init/keychords.c
@@ -72,12 +72,11 @@
if (!keychords)
return;
- fd = open("/dev/keychord", O_RDWR);
+ fd = open("/dev/keychord", O_RDWR | O_CLOEXEC);
if (fd < 0) {
ERROR("could not open /dev/keychord\n");
return;
}
- fcntl(fd, F_SETFD, FD_CLOEXEC);
ret = write(fd, keychords, keychords_length);
if (ret != keychords_length) {
diff --git a/init/keywords.h b/init/keywords.h
index 2d97e5b..7473586 100644
--- a/init/keywords.h
+++ b/init/keywords.h
@@ -8,6 +8,7 @@
int do_domainname(int nargs, char **args);
int do_enable(int nargs, char **args);
int do_exec(int nargs, char **args);
+int do_execonce(int nargs, char **args);
int do_export(int nargs, char **args);
int do_hostname(int nargs, char **args);
int do_ifup(int nargs, char **args);
@@ -59,6 +60,7 @@
KEYWORD(domainname, COMMAND, 1, do_domainname)
KEYWORD(enable, COMMAND, 1, do_enable)
KEYWORD(exec, COMMAND, 1, do_exec)
+ KEYWORD(execonce, COMMAND, 1, do_execonce)
KEYWORD(export, COMMAND, 2, do_export)
KEYWORD(group, OPTION, 0, 0)
KEYWORD(hostname, COMMAND, 1, do_hostname)
diff --git a/init/parser.c b/init/parser.c
index 48e7aec..80bfb09 100644
--- a/init/parser.c
+++ b/init/parser.c
@@ -15,9 +15,10 @@
struct command *cmd;
struct listnode *node;
struct listnode *node2;
+ char name_str[256] = "";
struct socketinfo *si;
int n;
-
+
list_for_each(node, &service_list) {
svc = node_to_item(node, struct service, slist);
RAW("service %s\n", svc->name);
@@ -34,7 +35,11 @@
list_for_each(node, &action_list) {
act = node_to_item(node, struct action, alist);
- RAW("on %s\n", act->name);
+ RAW("on ");
+ build_triggers_string(name_str, sizeof(name_str), act);
+ RAW("%s", name_str);
+ RAW("\n");
+
list_for_each(node2, &act->commands) {
cmd = node_to_item(node2, struct command, clist);
RAW(" %p", cmd->func);
diff --git a/init/readme.txt b/init/readme.txt
index 750d953..e5406ed 100644
--- a/init/readme.txt
+++ b/init/readme.txt
@@ -123,14 +123,27 @@
Triggers of this form occur when the property <name> is set
to the specific value <value>.
+ One can also test multiple properties to execute a group
+ of commands. For example:
+
+ on property:test.a=1 && property:test.b=1
+ setprop test.c 1
+
+ The above stub sets test.c to 1 only when
+ both test.a=1 and test.b=1
+
Commands
--------
exec <path> [ <argument> ]*
+ This command is not implemented.
+
+execonce <path> [ <argument> ]*
Fork and execute a program (<path>). This will block until
- the program completes execution. It is best to avoid exec
- as unlike the builtin commands, it runs the risk of getting
- init "stuck". (??? maybe there should be a timeout?)
+ the program completes execution. This command can be run at most
+ once during init's lifetime. Subsequent invocations are ignored.
+ It is best to avoid exec as unlike the builtin commands, it runs
+ the risk of getting init "stuck".
export <name> <value>
Set the environment variable <name> equal to <value> in the
diff --git a/init/signal_handler.c b/init/signal_handler.c
index 7e8e1a7..952f970 100644
--- a/init/signal_handler.c
+++ b/init/signal_handler.c
@@ -147,13 +147,9 @@
sigaction(SIGCHLD, &act, 0);
/* create a signalling mechanism for the sigchld handler */
- if (socketpair(AF_UNIX, SOCK_STREAM, 0, s) == 0) {
+ if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0, s) == 0) {
signal_fd = s[0];
signal_recv_fd = s[1];
- fcntl(s[0], F_SETFD, FD_CLOEXEC);
- fcntl(s[0], F_SETFL, O_NONBLOCK);
- fcntl(s[1], F_SETFD, FD_CLOEXEC);
- fcntl(s[1], F_SETFL, O_NONBLOCK);
}
handle_signal();
diff --git a/init/util.c b/init/util.c
index e1a3ee3..8f27ee9 100644
--- a/init/util.c
+++ b/init/util.c
@@ -155,7 +155,7 @@
struct stat sb;
data = 0;
- fd = open(fn, O_RDONLY);
+ fd = open(fn, O_RDONLY|O_CLOEXEC);
if(fd < 0) return 0;
// for security reasons, disallow world-writable
@@ -207,7 +207,7 @@
ssize_t pmtdsize;
int r;
- fd = open("/proc/mtd", O_RDONLY);
+ fd = open("/proc/mtd", O_RDONLY|O_CLOEXEC);
if (fd < 0)
return;
@@ -416,7 +416,7 @@
if (hardware[0])
return;
- fd = open(cpuinfo, O_RDONLY);
+ fd = open(cpuinfo, O_RDONLY | O_CLOEXEC);
if (fd < 0) return;
for (;;) {
@@ -479,7 +479,7 @@
char *ptr;
int fd;
- fd = open("/proc/cmdline", O_RDONLY);
+ fd = open("/proc/cmdline", O_RDONLY | O_CLOEXEC);
if (fd >= 0) {
int n = read(fd, cmdline, sizeof(cmdline) - 1);
if (n < 0) n = 0;
diff --git a/init/watchdogd.c b/init/watchdogd.c
index 7f64fc4..0790811 100644
--- a/init/watchdogd.c
+++ b/init/watchdogd.c
@@ -48,7 +48,7 @@
timeout = interval + margin;
- fd = open(DEV_NAME, O_RDWR);
+ fd = open(DEV_NAME, O_RDWR|O_CLOEXEC);
if (fd < 0) {
ERROR("watchdogd: Failed to open %s: %s\n", DEV_NAME, strerror(errno));
return 1;