2
0
mirror of https://github.com/sudo-project/sudo.git synced 2025-09-02 23:35:36 +00:00

Try to make sudo less vulnerable to ROWHAMMER attacks.

We now use ROWHAMMER-resistent values for ALLOW, DENY, AUTH_SUCCESS,
AUTH_FAILURE, AUTH_ERROR and AUTH_NONINTERACTIVE.  In addition, we
explicitly test for expected values instead of using a negated test
against an error value.  In the parser match functions this means
explicitly checking for ALLOW or DENY instead of accepting anything
that is not set to UNSPEC.

Thanks to Andrew J. Adiletta, M. Caner Tol, Yarkin Doroz, and Berk
Sunar, all affiliated with the Vernam Applied Cryptography and
Cybersecurity Lab at Worcester Polytechnic Institute, for the report.
Paper preprint: https://arxiv.org/abs/2309.02545
This commit is contained in:
Todd C. Miller
2023-09-09 14:07:04 -06:00
parent 525803db23
commit 7873f8334c
6 changed files with 96 additions and 54 deletions

View File

@@ -116,10 +116,16 @@ sudo_auth_init(const struct sudoers_context *ctx, struct passwd *pw,
if (auth->init && !IS_DISABLED(auth)) {
/* Disable if it failed to init unless there was a fatal error. */
status = (auth->init)(ctx, pw, auth);
if (status == AUTH_FAILURE)
switch (status) {
case AUTH_SUCCESS:
break;
case AUTH_FAILURE:
SET(auth->flags, FLAG_DISABLED);
else if (status == AUTH_ERROR)
break; /* assume error msg already printed */
break;
default:
/* Assume error msg already printed. */
debug_return_int(-1);
}
}
}
@@ -166,7 +172,7 @@ sudo_auth_init(const struct sudoers_context *ctx, struct passwd *pw,
}
}
debug_return_int(status == AUTH_ERROR ? -1 : 0);
debug_return_int(0);
}
/*
@@ -209,7 +215,7 @@ sudo_auth_cleanup(const struct sudoers_context *ctx, struct passwd *pw,
for (auth = auth_switch; auth->name; auth++) {
if (auth->cleanup && !IS_DISABLED(auth)) {
int status = (auth->cleanup)(ctx, pw, auth, force);
if (status == AUTH_ERROR) {
if (status != AUTH_SUCCESS) {
/* Assume error msg already printed. */
debug_return_int(-1);
}
@@ -306,7 +312,7 @@ verify_user(const struct sudoers_context *ctx, struct passwd *pw, char *prompt,
SET(auth->flags, FLAG_DISABLED);
else if (status == AUTH_NONINTERACTIVE)
goto done;
else if (status == AUTH_ERROR || user_interrupted())
else if (status != AUTH_SUCCESS || user_interrupted())
goto done; /* assume error msg already printed */
}
}
@@ -365,7 +371,6 @@ done:
case AUTH_NONINTERACTIVE:
SET(validated, FLAG_NO_USER_INPUT);
FALLTHROUGH;
case AUTH_ERROR:
default:
log_auth_failure(ctx, validated, 0);
ret = -1;
@@ -377,25 +382,33 @@ done:
/*
* Call authentication method begin session hooks.
* Returns 1 on success and -1 on error.
* Returns true on success, false on failure and -1 on error.
*/
int
sudo_auth_begin_session(const struct sudoers_context *ctx, struct passwd *pw,
char **user_env[])
{
sudo_auth *auth;
int ret = true;
debug_decl(sudo_auth_begin_session, SUDOERS_DEBUG_AUTH);
for (auth = auth_switch; auth->name; auth++) {
if (auth->begin_session && !IS_DISABLED(auth)) {
int status = (auth->begin_session)(ctx, pw, user_env, auth);
if (status != AUTH_SUCCESS) {
switch (status) {
case AUTH_SUCCESS:
break;
case AUTH_FAILURE:
ret = false;
break;
default:
/* Assume error msg already printed. */
debug_return_int(-1);
ret = -1;
break;
}
}
}
debug_return_int(1);
debug_return_int(ret);
}
bool
@@ -416,25 +429,33 @@ sudo_auth_needs_end_session(void)
/*
* Call authentication method end session hooks.
* Returns 1 on success and -1 on error.
* Returns true on success, false on failure and -1 on error.
*/
int
sudo_auth_end_session(void)
{
sudo_auth *auth;
int ret = true;
int status;
debug_decl(sudo_auth_end_session, SUDOERS_DEBUG_AUTH);
for (auth = auth_switch; auth->name; auth++) {
if (auth->end_session && !IS_DISABLED(auth)) {
status = (auth->end_session)(auth);
if (status == AUTH_ERROR) {
switch (status) {
case AUTH_SUCCESS:
break;
case AUTH_FAILURE:
ret = false;
break;
default:
/* Assume error msg already printed. */
debug_return_int(-1);
ret = -1;
break;
}
}
}
debug_return_int(1);
debug_return_int(ret);
}
/*