summaryrefslogtreecommitdiff
path: root/usr.bin/passwd
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>2017-08-21 21:41:14 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>2017-08-21 21:41:14 +0000
commitc2cdcf41ccf92e65434001bc73d5d81b4c4210dd (patch)
treeb806cd4f2e6e8fcd9ec7d6f315a0aa469b48521d /usr.bin/passwd
parente9d6f86c3468c07e6b1b12c0dd0b46516528e450 (diff)
Use waitpid()/EINTR idiom for the specific pid, rather than generic wait(),
in case the parent process was started with a dangling child. This style ensures any potential parent:child interlock isn't disrupted due to the "wrong" child being waited on first. Then the other other childs can safely zombie. ok millert jca brynet
Diffstat (limited to 'usr.bin/passwd')
-rw-r--r--usr.bin/passwd/pwd_check.c15
1 files changed, 10 insertions, 5 deletions
diff --git a/usr.bin/passwd/pwd_check.c b/usr.bin/passwd/pwd_check.c
index fcb3dfdeb41..cfdd1f65ed2 100644
--- a/usr.bin/passwd/pwd_check.c
+++ b/usr.bin/passwd/pwd_check.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pwd_check.c,v 1.15 2015/12/09 19:39:10 mmcc Exp $ */
+/* $OpenBSD: pwd_check.c,v 1.16 2017/08/21 21:41:13 deraadt Exp $ */
/*
* Copyright 2000 Niels Provos <provos@citi.umich.edu>
@@ -138,12 +138,14 @@ pwd_check(login_cap_t *lc, char *password)
err(1, "pledge");
for (i = 0; i < sizeof(patterns) / sizeof(*patterns); i++) {
+ int ret;
+
if (regcomp(&rgx, patterns[i].match,
patterns[i].flags) != 0)
continue;
- res = regexec(&rgx, password, 0, NULL, 0);
+ ret = regexec(&rgx, password, 0, NULL, 0);
regfree(&rgx);
- if (res == 0) {
+ if (ret == 0) {
printf("%s\n", patterns[i].response);
exit(1);
}
@@ -181,8 +183,11 @@ pwd_check(login_cap_t *lc, char *password)
}
/* get the return value from the child */
- wait(&child);
- if (WIFEXITED(child) && WEXITSTATUS(child) == 0) {
+ while (waitpid(child, &res, 0) == -1) {
+ if (errno != EINTR)
+ break;
+ }
+ if (WIFEXITED(res) && WEXITSTATUS(res) == 0) {
free(checker);
return (1);
}