Index: sys/kern/subr_syscall.c =================================================================== --- sys/kern/subr_syscall.c +++ sys/kern/subr_syscall.c @@ -154,7 +154,22 @@ td->td_pflags &= ~TDP_NERRNO; else td->td_errno = error; - AUDIT_SYSCALL_EXIT(error, td); + + /* + * We must be careful about the value that we're reporting to + * the audit system here. The main concern is with syscalls + * that have set TDP_NERRNO, given that td->td_errno already + * reflects `error` in the !TDP_NERRNO case. In this instance, + * the return value may not actually reflect what's getting + * returned to userland. e.g., sigsuspend(2) will return + * EJUSTRETURN to avoid clobbering registers on the way out, + * but it's actually returning EINTR. In the case of + * kern_posix_error(), we'll still do the right thing as it + * returns 0, causing the audit system to consider it + * "successful" but with the correct error as a return value. + */ + AUDIT_SYSCALL_EXIT(error == 0 ? 0 : td->td_errno, td); + #ifdef KDTRACE_HOOKS /* Give the syscall:::return DTrace probe a chance to fire. */ if (__predict_false(sa->callp->sy_return != 0)) Index: sys/security/audit/audit.c =================================================================== --- sys/security/audit/audit.c +++ sys/security/audit/audit.c @@ -720,11 +720,19 @@ * return value from the system call is stored on the user thread. * If there was an error, the return value is set to -1, imitating * the behavior of the cerror routine. + * + * Note that EJUSTRETURN may also be returned, which is typically not + * indicative of an error. The retval recorded here for this scenario + * may be technically incorrect, but odds are good that the syscall will + * not be returning in the traditional sense; the main objective is to + * make sure it's recorded as a success. */ - if (error) - retval = -1; - else + if (error == 0) retval = td->td_retval[0]; + else if (error == EJUSTRETURN) + error = retval = 0; + else + retval = -1; audit_commit(td->td_ar, error, retval); td->td_ar = NULL;