fix: fix possible race condition

This commit is contained in:
MusiKid 2021-07-28 12:16:09 +02:00 committed by musikid
parent 5503cfb4e2
commit 039217152d
No known key found for this signature in database
GPG key ID: 7567D43648C6E2F4

View file

@ -133,7 +133,7 @@ int identify(pam_handle_t *pamh, int flags, int argc, const char **argv,
string workaround = reader.GetString("core", "workaround", "input"); string workaround = reader.GetString("core", "workaround", "input");
// In this case, we are not asking for the password // In this case, we are not asking for the password
if (workaround == Workaround::Off) if (workaround == Workaround::Off && auth_tok)
auth_tok = false; auth_tok = false;
// Will contain PAM conversation function // Will contain PAM conversation function
@ -241,6 +241,8 @@ int identify(pam_handle_t *pamh, int flags, int argc, const char **argv,
mutex m; mutex m;
condition_variable cv; condition_variable cv;
Type confirmation_type; Type confirmation_type;
// TODO: Find a clean way to do this
Type final_type;
// This task wait for the status of the python subprocess (we don't want a // This task wait for the status of the python subprocess (we don't want a
// zombie process) // zombie process)
@ -278,14 +280,11 @@ int identify(pam_handle_t *pamh, int flags, int argc, const char **argv,
{ {
unique_lock<mutex> lk(m); unique_lock<mutex> lk(m);
cv.wait(lk); cv.wait(lk);
final_type = confirmation_type;
} }
if (workaround != Workaround::Native && auth_tok) { if (final_type == Type::Howdy) {
pass_task.stop(false); // We need to be sure that we're not going to block forever if the
}
if (confirmation_type == Type::Howdy) {
// This one is just to be sure that we're not going to block forever if the
// child has a problem // child has a problem
if (child_task.wait(3s) == future_status::timeout) { if (child_task.wait(3s) == future_status::timeout) {
kill(child_pid, SIGTERM); kill(child_pid, SIGTERM);
@ -317,43 +316,50 @@ int identify(pam_handle_t *pamh, int flags, int argc, const char **argv,
} else { } else {
return on_howdy_auth(howdy_status, conv_function); return on_howdy_auth(howdy_status, conv_function);
} }
} else {
if (workaround != Workaround::Native) {
if (child_task.wait(1s) == future_status::timeout) {
kill(child_pid, SIGTERM);
}
child_task.stop(false);
} else {
pass_task.stop(false);
}
char *token = nullptr;
tie(pam_res, token) = pass_task.get();
if (pam_res != PAM_SUCCESS)
return pam_res;
int howdy_status = child_task.get();
if (strlen(token) == 0) {
if (howdy_status == 0) {
if (!reader.GetBoolean("core", "no_confirmation", true)) {
// Construct confirmation text from i18n string
string confirm_text = dgettext("pam", "Identified face as {}");
string identify_msg(confirm_text.replace(confirm_text.find("{}"), 2,
string(user_ptr)));
// Send confirmation message to user
conv_function(PAM_TEXT_INFO, identify_msg.c_str());
}
syslog(LOG_INFO, "Login approved");
return PAM_SUCCESS;
} else {
return on_howdy_auth(howdy_status, conv_function);
}
}
// The password has been entered, we are passing it to PAM stack
return PAM_IGNORE;
} }
// The branch with Howdy confirmation type returns early, so we don't need an
// else statement
// Again, we need to be sure that we're not going to block forever if the
// child has a problem
if (child_task.wait(1.5s) == future_status::timeout) {
kill(child_pid, SIGTERM);
}
child_task.stop(false);
// We just wait for the thread to stop since it's this one which sent us the
// confirmation type
if (workaround == Workaround::Input && auth_tok) {
pass_task.stop(false);
}
char *token = nullptr;
tie(pam_res, token) = pass_task.get();
if (pam_res != PAM_SUCCESS)
return pam_res;
int howdy_status = child_task.get();
if (strlen(token) == 0) {
if (howdy_status == 0) {
if (!reader.GetBoolean("core", "no_confirmation", true)) {
// Construct confirmation text from i18n string
string confirm_text = dgettext("pam", "Identified face as {}");
string identify_msg(
confirm_text.replace(confirm_text.find("{}"), 2, string(user_ptr)));
// Send confirmation message to user
conv_function(PAM_TEXT_INFO, identify_msg.c_str());
}
syslog(LOG_INFO, "Login approved");
return PAM_SUCCESS;
} else {
return on_howdy_auth(howdy_status, conv_function);
}
}
// The password has been entered, we are passing it to PAM stack
return PAM_IGNORE;
} }
// Called by PAM when a user needs to be authenticated, for example by running // Called by PAM when a user needs to be authenticated, for example by running