Switch from memset_s() -> explicit_bzero().

memset_s() (and all of Annex K) is likely to be removed from the
a future version of the standard.
This commit is contained in:
Todd C. Miller
2020-08-10 19:24:32 -06:00
parent 8a97150f56
commit cef6e3687e
25 changed files with 168 additions and 192 deletions

View File

@@ -138,6 +138,7 @@ lib/util/dup3.c
lib/util/event.c lib/util/event.c
lib/util/event_poll.c lib/util/event_poll.c
lib/util/event_select.c lib/util/event_select.c
lib/util/explicit_bzero.c
lib/util/fatal.c lib/util/fatal.c
lib/util/fchmodat.c lib/util/fchmodat.c
lib/util/fnmatch.c lib/util/fnmatch.c
@@ -163,7 +164,6 @@ lib/util/locking.c
lib/util/logfac.c lib/util/logfac.c
lib/util/logpri.c lib/util/logpri.c
lib/util/memrchr.c lib/util/memrchr.c
lib/util/memset_s.c
lib/util/mkdir_parents.c lib/util/mkdir_parents.c
lib/util/mksiglist.c lib/util/mksiglist.c
lib/util/mksiglist.h lib/util/mksiglist.h

View File

@@ -88,6 +88,9 @@
/* Define to 1 to enable BSM audit support. */ /* Define to 1 to enable BSM audit support. */
#undef HAVE_BSM_AUDIT #undef HAVE_BSM_AUDIT
/* Define to 1 if you have the `bzero' function. */
#undef HAVE_BZERO
/* Define to 1 if you have the `cfmakeraw' function. */ /* Define to 1 if you have the `cfmakeraw' function. */
#undef HAVE_CFMAKERAW #undef HAVE_CFMAKERAW
@@ -255,6 +258,12 @@
/* Define to 1 if you have the `execvpe' function. */ /* Define to 1 if you have the `execvpe' function. */
#undef HAVE_EXECVPE #undef HAVE_EXECVPE
/* Define to 1 if you have the `explicit_bzero' function. */
#undef HAVE_EXPLICIT_BZERO
/* Define to 1 if you have the `explicit_memset' function. */
#undef HAVE_EXPLICIT_MEMSET
/* Define to 1 if you have the `faccessat' function. */ /* Define to 1 if you have the `faccessat' function. */
#undef HAVE_FACCESSAT #undef HAVE_FACCESSAT
@@ -535,6 +544,9 @@
/* Define to 1 if you have the `memrchr' function. */ /* Define to 1 if you have the `memrchr' function. */
#undef HAVE_MEMRCHR #undef HAVE_MEMRCHR
/* Define to 1 if you have the `memset_explicit' function. */
#undef HAVE_MEMSET_EXPLICIT
/* Define to 1 if you have the `memset_s' function. */ /* Define to 1 if you have the `memset_s' function. */
#undef HAVE_MEMSET_S #undef HAVE_MEMSET_S
@@ -1263,9 +1275,6 @@
/* Define to empty if `const' does not conform to ANSI C. */ /* Define to empty if `const' does not conform to ANSI C. */
#undef const #undef const
/* Define to `int' if <sys/types.h> does not define. */
#undef errno_t
/* Define to `int' if <sys/types.h> doesn't define. */ /* Define to `int' if <sys/types.h> doesn't define. */
#undef gid_t #undef gid_t
@@ -1284,9 +1293,6 @@
/* Define to an OS-specific initialization function or `os_init_common'. */ /* Define to an OS-specific initialization function or `os_init_common'. */
#undef os_init #undef os_init
/* Define to `size_t' if <sys/types.h> does not define. */
#undef rsize_t
/* Define to `int' if <signal.h> does not define. */ /* Define to `int' if <signal.h> does not define. */
#undef sig_atomic_t #undef sig_atomic_t

88
configure vendored
View File

@@ -18057,8 +18057,6 @@ fi
fi fi
$as_echo "#define __STDC_WANT_LIB_EXT1__ 1" >>confdefs.h
ac_fn_c_check_type "$LINENO" "mode_t" "ac_cv_type_mode_t" "$ac_includes_default" ac_fn_c_check_type "$LINENO" "mode_t" "ac_cv_type_mode_t" "$ac_includes_default"
if test "x$ac_cv_type_mode_t" = xyes; then : if test "x$ac_cv_type_mode_t" = xyes; then :
@@ -18318,28 +18316,6 @@ else
fi fi
ac_fn_c_check_type "$LINENO" "rsize_t" "ac_cv_type_rsize_t" "$ac_includes_default"
if test "x$ac_cv_type_rsize_t" = xyes; then :
else
cat >>confdefs.h <<_ACEOF
#define rsize_t size_t
_ACEOF
fi
ac_fn_c_check_type "$LINENO" "errno_t" "ac_cv_type_errno_t" "$ac_includes_default"
if test "x$ac_cv_type_errno_t" = xyes; then :
else
cat >>confdefs.h <<_ACEOF
#define errno_t int
_ACEOF
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking max length of uid_t" >&5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking max length of uid_t" >&5
$as_echo_n "checking max length of uid_t... " >&6; } $as_echo_n "checking max length of uid_t... " >&6; }
@@ -20513,6 +20489,44 @@ fi
done done
fi
done
for ac_func in explicit_bzero
do :
ac_fn_c_check_func "$LINENO" "explicit_bzero" "ac_cv_func_explicit_bzero"
if test "x$ac_cv_func_explicit_bzero" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_EXPLICIT_BZERO 1
_ACEOF
else
case " $LIBOBJS " in
*" explicit_bzero.$ac_objext "* ) ;;
*) LIBOBJS="$LIBOBJS explicit_bzero.$ac_objext"
;;
esac
for _sym in sudo_explicit_bzero; do
COMPAT_EXP="${COMPAT_EXP}${_sym}
"
done
for ac_func in explicit_memset memset_explicit memset_s bzero
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF
break
fi
done
fi fi
done done
@@ -20659,32 +20673,6 @@ esac
done done
fi
done
for ac_func in memset_s
do :
ac_fn_c_check_func "$LINENO" "memset_s" "ac_cv_func_memset_s"
if test "x$ac_cv_func_memset_s" = xyes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_MEMSET_S 1
_ACEOF
else
case " $LIBOBJS " in
*" memset_s.$ac_objext "* ) ;;
*) LIBOBJS="$LIBOBJS memset_s.$ac_objext"
;;
esac
for _sym in sudo_memset_s; do
COMPAT_EXP="${COMPAT_EXP}${_sym}
"
done
fi fi
done done

View File

@@ -2504,9 +2504,7 @@ if test ${with_project-'no'} != "no"; then
fi fi
dnl dnl
dnl typedef checks dnl typedef checks
dnl We need to define __STDC_WANT_LIB_EXT1__ for errno_t and rsize_t
dnl dnl
AC_DEFINE([__STDC_WANT_LIB_EXT1__])
AC_TYPE_MODE_T AC_TYPE_MODE_T
AC_TYPE_UID_T AC_TYPE_UID_T
AC_CHECK_TYPE([clockid_t], [], [AC_DEFINE(clockid_t, int)], [#include <sys/types.h> AC_CHECK_TYPE([clockid_t], [], [AC_DEFINE(clockid_t, int)], [#include <sys/types.h>
@@ -2527,8 +2525,6 @@ AC_CHECK_TYPE(uint64_t, unsigned long long)
AC_CHECK_TYPE(socklen_t, [], [AC_DEFINE(socklen_t, unsigned int)], [ AC_CHECK_TYPE(socklen_t, [], [AC_DEFINE(socklen_t, unsigned int)], [
AC_INCLUDES_DEFAULT AC_INCLUDES_DEFAULT
#include <sys/socket.h>]) #include <sys/socket.h>])
AC_CHECK_TYPE(rsize_t, size_t)
AC_CHECK_TYPE(errno_t, int)
SUDO_UID_T_LEN SUDO_UID_T_LEN
SUDO_SOCK_SA_LEN SUDO_SOCK_SA_LEN
SUDO_SOCK_SIN_LEN SUDO_SOCK_SIN_LEN
@@ -2810,6 +2806,11 @@ AC_CHECK_FUNCS([futimens], [], [
SUDO_APPEND_COMPAT_EXP(sudo_futimens) SUDO_APPEND_COMPAT_EXP(sudo_futimens)
AC_CHECK_FUNCS([futimes futimesat futime], [break]) AC_CHECK_FUNCS([futimes futimesat futime], [break])
]) ])
AC_CHECK_FUNCS([explicit_bzero], [], [
AC_LIBOBJ(explicit_bzero)
SUDO_APPEND_COMPAT_EXP(sudo_explicit_bzero)
AC_CHECK_FUNCS([explicit_memset memset_explicit memset_s bzero], [break])
])
SUDO_FUNC_FNMATCH([AC_DEFINE(HAVE_FNMATCH)], [ SUDO_FUNC_FNMATCH([AC_DEFINE(HAVE_FNMATCH)], [
AC_LIBOBJ(fnmatch) AC_LIBOBJ(fnmatch)
SUDO_APPEND_COMPAT_EXP(sudo_fnmatch) SUDO_APPEND_COMPAT_EXP(sudo_fnmatch)
@@ -2824,10 +2825,6 @@ AC_CHECK_FUNCS([memrchr], [], [
AC_LIBOBJ(memrchr) AC_LIBOBJ(memrchr)
SUDO_APPEND_COMPAT_EXP(sudo_memrchr) SUDO_APPEND_COMPAT_EXP(sudo_memrchr)
]) ])
AC_CHECK_FUNCS([memset_s], [], [
AC_LIBOBJ(memset_s)
SUDO_APPEND_COMPAT_EXP(sudo_memset_s)
])
AC_CHECK_FUNCS(nanosleep, [], [ AC_CHECK_FUNCS(nanosleep, [], [
# On Solaris, nanosleep is in librt # On Solaris, nanosleep is in librt
AC_CHECK_LIB(rt, nanosleep, [ AC_CHECK_LIB(rt, nanosleep, [

View File

@@ -4481,9 +4481,6 @@ the trailing NUL character).
In practical terms, this is the longest password In practical terms, this is the longest password
\fBsudo\fR \fBsudo\fR
will support. will support.
It is also useful as a maximum value for the
\fBmemset_s\fR()
function when clearing passwords filled in by the conversation function.
.PP .PP
The The
\fBprintf\fR()-style \fBprintf\fR()-style

View File

@@ -3960,9 +3960,6 @@ the trailing NUL character).
In practical terms, this is the longest password In practical terms, this is the longest password
.Nm sudo .Nm sudo
will support. will support.
It is also useful as a maximum value for the
.Fn memset_s
function when clearing passwords filled in by the conversation function.
.Pp .Pp
The The
.Fn printf Ns -style .Fn printf Ns -style

View File

@@ -30,12 +30,6 @@
!defined(HAVE_VSYSLOG) || defined(PREFER_PORTABLE_SNPRINTF) !defined(HAVE_VSYSLOG) || defined(PREFER_PORTABLE_SNPRINTF)
# include <stdarg.h> # include <stdarg.h>
#endif #endif
#if !defined(HAVE_MEMSET_S) && !defined(rsize_t)
# include <stddef.h> /* for rsize_t */
# ifdef HAVE_STRING_H
# include <string.h> /* for rsize_t on AIX */
# endif /* HAVE_STRING_H */
#endif /* HAVE_MEMSET_S && rsize_t */
/* /*
* Macros and functions that may be missing on some operating systems. * Macros and functions that may be missing on some operating systems.
@@ -442,6 +436,11 @@ __dso_public void sudo_closefrom(int);
# undef closefrom # undef closefrom
# define closefrom(_a) sudo_closefrom((_a)) # define closefrom(_a) sudo_closefrom((_a))
#endif /* HAVE_CLOSEFROM */ #endif /* HAVE_CLOSEFROM */
#ifndef HAVE_EXPLICIT_BZERO
__dso_public void sudo_explicit_bzero(void *s, size_t n);
# undef explicit_bzero
# define explicit_bzero(_a, _b) sudo_explicit_bzero((_a), (_b))
#endif /* HAVE_EXPLICIT_BZERO */
#ifdef PREFER_PORTABLE_GETCWD #ifdef PREFER_PORTABLE_GETCWD
__dso_public char *sudo_getcwd(char *, size_t size); __dso_public char *sudo_getcwd(char *, size_t size);
# undef getcwd # undef getcwd
@@ -536,11 +535,6 @@ __dso_public void *sudo_memrchr(const void *s, int c, size_t n);
# undef memrchr # undef memrchr
# define memrchr(_a, _b, _c) sudo_memrchr((_a), (_b), (_c)) # define memrchr(_a, _b, _c) sudo_memrchr((_a), (_b), (_c))
#endif /* HAVE_MEMRCHR */ #endif /* HAVE_MEMRCHR */
#ifndef HAVE_MEMSET_S
__dso_public errno_t sudo_memset_s(void *v, rsize_t smax, int c, rsize_t n);
# undef memset_s
# define memset_s(_a, _b, _c, _d) sudo_memset_s((_a), (_b), (_c), (_d))
#endif /* HAVE_MEMSET_S */
#if !defined(HAVE_MKDTEMP) || !defined(HAVE_MKSTEMPS) #if !defined(HAVE_MKDTEMP) || !defined(HAVE_MKSTEMPS)
__dso_public char *sudo_mkdtemp(char *path); __dso_public char *sudo_mkdtemp(char *path);
# undef mkdtemp # undef mkdtemp

View File

@@ -57,9 +57,7 @@ struct sudo_conv_message {
* conversing with the user. In practical terms, this is the longest * conversing with the user. In practical terms, this is the longest
* password sudo will support. This means that a buffer of size * password sudo will support. This means that a buffer of size
* SUDO_CONV_REPL_MAX+1 is guaranteed to be able to hold any reply * SUDO_CONV_REPL_MAX+1 is guaranteed to be able to hold any reply
* from the conversation function. It is also useful as a max value * from the conversation function.
* for memset_s() when clearing passwords returned by the conversation
* function.
*/ */
#define SUDO_CONV_REPL_MAX 1023 #define SUDO_CONV_REPL_MAX 1023

View File

@@ -559,6 +559,14 @@ event_select.i: $(srcdir)/event_select.c $(incdir)/compat/stdbool.h \
$(CC) -E -o $@ $(CPPFLAGS) $< $(CC) -E -o $@ $(CPPFLAGS) $<
event_select.plog: event_select.i event_select.plog: event_select.i
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/event_select.c --i-file $< --output-file $@ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/event_select.c --i-file $< --output-file $@
explicit_bzero.lo: $(srcdir)/explicit_bzero.c $(incdir)/sudo_compat.h \
$(top_builddir)/config.h
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/explicit_bzero.c
explicit_bzero.i: $(srcdir)/explicit_bzero.c $(incdir)/sudo_compat.h \
$(top_builddir)/config.h
$(CC) -E -o $@ $(CPPFLAGS) $<
explicit_bzero.plog: explicit_bzero.i
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/explicit_bzero.c --i-file $< --output-file $@
fatal.lo: $(srcdir)/fatal.c $(incdir)/compat/getaddrinfo.h \ fatal.lo: $(srcdir)/fatal.c $(incdir)/compat/getaddrinfo.h \
$(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \ $(incdir)/compat/stdbool.h $(incdir)/sudo_compat.h \
$(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \
@@ -847,14 +855,6 @@ memrchr.i: $(srcdir)/memrchr.c $(incdir)/sudo_compat.h $(top_builddir)/config.h
$(CC) -E -o $@ $(CPPFLAGS) $< $(CC) -E -o $@ $(CPPFLAGS) $<
memrchr.plog: memrchr.i memrchr.plog: memrchr.i
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/memrchr.c --i-file $< --output-file $@ rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/memrchr.c --i-file $< --output-file $@
memset_s.lo: $(srcdir)/memset_s.c $(incdir)/sudo_compat.h \
$(top_builddir)/config.h
$(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(ASAN_CFLAGS) $(PIE_CFLAGS) $(SSP_CFLAGS) $(srcdir)/memset_s.c
memset_s.i: $(srcdir)/memset_s.c $(incdir)/sudo_compat.h \
$(top_builddir)/config.h
$(CC) -E -o $@ $(CPPFLAGS) $<
memset_s.plog: memset_s.i
rm -f $@; pvs-studio --cfg $(PVS_CFG) --sourcetree-root $(top_srcdir) --skip-cl-exe yes --source-file $(srcdir)/memset_s.c --i-file $< --output-file $@
mkdir_parents.lo: $(srcdir)/mkdir_parents.c $(incdir)/compat/stdbool.h \ mkdir_parents.lo: $(srcdir)/mkdir_parents.c $(incdir)/compat/stdbool.h \
$(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \ $(incdir)/sudo_compat.h $(incdir)/sudo_debug.h \
$(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \ $(incdir)/sudo_fatal.h $(incdir)/sudo_gettext.h \

View File

@@ -103,7 +103,7 @@ _rs_stir(void)
_rs_init(rnd, sizeof(rnd)); _rs_init(rnd, sizeof(rnd));
} else } else
_rs_rekey(rnd, sizeof(rnd)); _rs_rekey(rnd, sizeof(rnd));
memset_s(rnd, sizeof(rnd), 0, sizeof(rnd)); /* discard source seed */ explicit_bzero(rnd, sizeof(rnd)); /* discard source seed */
/* invalidate rs_buf */ /* invalidate rs_buf */
rs_have = 0; rs_have = 0;

77
lib/util/explicit_bzero.c Normal file
View File

@@ -0,0 +1,77 @@
/*
* SPDX-License-Identifier: ISC
*
* Copyright (c) 2020 Todd C. Miller <Todd.Miller@sudo.ws>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* This is an open source non-commercial project. Dear PVS-Studio, please check it.
* PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
*/
#include <config.h>
#define __STDC_WANT_LIB_EXT1__ 1 /* for memset_s() */
#include <string.h>
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif /* HAVE_STRINGS_H */
#include "sudo_compat.h"
#ifndef HAVE_EXPLICIT_BZERO
# if defined(HAVE_EXPLICIT_MEMSET)
void
sudo_explicit_bzero(void *s, size_t n)
{
explicit_memset(s, 0, n);
}
# elif defined(HAVE_MEMSET_EXPLICIT)
void
sudo_explicit_bzero(void *s, size_t n)
{
memset_explicit(s, 0, n);
}
# elif defined(HAVE_MEMSET_S)
void
sudo_explicit_bzero(void *s, size_t n)
{
(void)memset_s(s, n, 0, n);
}
# elif defined(HAVE_BZERO)
/* Jumping through a volatile function pointer should not be optimized away. */
void (* volatile sudo_explicit_bzero_impl)(void *, size_t) =
(void (*)(void *, size_t))bzero;
void
sudo_explicit_bzero(void *s, size_t n)
{
sudo_explicit_bzero_impl(s, n);
}
# else
void
sudo_explicit_bzero(void *v, size_t n)
{
volatile unsigned char *s = v;
/* Updating through a volatile pointer should not be optimized away. */
while (n--)
*s++ = '\0';
}
# endif /* HAVE_BZERO */
#endif /* HAVE_EXPLICIT_BZERO */

View File

@@ -614,7 +614,7 @@ getentropy_fallback(void *buf, size_t len)
done: done:
sudo_digest_free(ctx); sudo_digest_free(ctx);
if (results != NULL) { if (results != NULL) {
memset_s(results, sizeof(results), 0, sizeof(results)); explicit_bzero(results, sizeof(results));
free(results); free(results);
} }
return (ret); return (ret);

View File

@@ -1,78 +0,0 @@
/*
* SPDX-License-Identifier: ISC
*
* Copyright (c) 2013-2014 Todd C. Miller <Todd.Miller@sudo.ws>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* This is an open source non-commercial project. Dear PVS-Studio, please check it.
* PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
*/
#include <config.h>
#include <stddef.h>
#include <errno.h>
#include <limits.h>
#if defined(HAVE_STDINT_H)
# include <stdint.h>
#elif defined(HAVE_INTTYPES_H)
# include <inttypes.h>
#endif
#include "sudo_compat.h"
#ifndef RSIZE_MAX
# if defined(SIZE_MAX)
# define RSIZE_MAX (SIZE_MAX >> 1)
# elif defined(__LP64__)
# define RSIZE_MAX 0x7fffffffffffffffUL
# else
# define RSIZE_MAX 0x7fffffffU
# endif
#endif
/*
* Simple implementation of C11 memset_s() function.
* We use a volatile pointer when updating the byte string.
* Most compilers will avoid optimizing away access to a
* volatile pointer, even if the pointer appears to be unused
* after the call.
*
* Note that C11 does not specify the return value on error, only
* that it be non-zero. We use EINVAL for all errors.
*/
errno_t
sudo_memset_s(void *v, rsize_t smax, int c, rsize_t n)
{
errno_t ret = 0;
volatile unsigned char *s = v;
/* Fatal runtime-constraint violations. */
if (s == NULL || smax > RSIZE_MAX) {
ret = errno = EINVAL;
goto done;
}
/* Non-fatal runtime-constraint violation, n must not exceed smax. */
if (n > smax) {
n = smax;
ret = errno = EINVAL;
}
/* Updating through a volatile pointer should not be optimized away. */
while (n--)
*s++ = (unsigned char)c;
done:
return ret;
}

View File

@@ -237,8 +237,8 @@ SHA256Transform(uint32_t state[8], const uint8_t data[SHA256_BLOCK_LENGTH])
state[6] += g(0); state[6] += g(0);
state[7] += h(0); state[7] += h(0);
/* Cleanup */ /* Cleanup */
memset_s(T, sizeof(T), 0, sizeof(T)); explicit_bzero(T, sizeof(T));
memset_s(W, sizeof(W), 0, sizeof(W)); explicit_bzero(W, sizeof(W));
} }
#undef S0 #undef S0
@@ -454,8 +454,8 @@ SHA512Transform(uint64_t state[8], const uint8_t data[SHA512_BLOCK_LENGTH])
state[6] += g(0); state[6] += g(0);
state[7] += h(0); state[7] += h(0);
/* Cleanup. */ /* Cleanup. */
memset_s(T, sizeof(T), 0, sizeof(T)); explicit_bzero(T, sizeof(T));
memset_s(W, sizeof(W), 0, sizeof(W)); explicit_bzero(W, sizeof(W));
} }
void void

View File

@@ -243,7 +243,7 @@ sudo_aix_verify(struct passwd *pw, char *prompt, sudo_auth *auth, struct sudo_co
free(message); free(message);
message = NULL; message = NULL;
result = authenticate(pw->pw_name, pass, &reenter, &message); result = authenticate(pw->pw_name, pass, &reenter, &message);
memset_s(pass, SUDO_CONV_REPL_MAX, 0, strlen(pass)); explicit_bzero(pass, strlen(pass));
free(pass); free(pass);
prompt = message; prompt = message;
} while (reenter); } while (reenter);

View File

@@ -151,7 +151,7 @@ bsdauth_verify(struct passwd *pw, char *prompt, sudo_auth *auth, struct sudo_con
if (pass) { if (pass) {
authok = auth_userresponse(as, pass, 1); authok = auth_userresponse(as, pass, 1);
memset_s(pass, SUDO_CONV_REPL_MAX, 0, strlen(pass)); explicit_bzero(pass, strlen(pass));
free(pass); free(pass);
} }

View File

@@ -133,8 +133,8 @@ restart:
sudo_warnx("%s", resp); sudo_warnx("%s", resp);
error = AUTH_FAILURE; error = AUTH_FAILURE;
done: done:
memset_s(buf, sizeof(buf), 0, sizeof(buf)); explicit_bzero(buf, sizeof(buf));
memset_s(pass, SUDO_PASS_MAX, 0, strlen(pass)); explicit_bzero(pass, strlen(pass));
free(pass); free(pass);
debug_return_int(error); debug_return_int(error);
} }

View File

@@ -702,7 +702,7 @@ converse(int num_msg, PAM_CONST struct pam_message **msg,
sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO, sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_LINENO,
"password longer than %d", PAM_MAX_RESP_SIZE); "password longer than %d", PAM_MAX_RESP_SIZE);
ret = PAM_CONV_ERR; ret = PAM_CONV_ERR;
memset_s(pass, SUDO_CONV_REPL_MAX, 0, strlen(pass)); explicit_bzero(pass, strlen(pass));
goto done; goto done;
} }
reply[n].resp = pass; /* auth_getpass() malloc's a copy */ reply[n].resp = pass; /* auth_getpass() malloc's a copy */
@@ -732,7 +732,7 @@ done:
struct pam_response *pr = &reply[n]; struct pam_response *pr = &reply[n];
if (pr->resp != NULL) { if (pr->resp != NULL) {
memset_s(pr->resp, SUDO_CONV_REPL_MAX, 0, strlen(pr->resp)); explicit_bzero(pr->resp, strlen(pr->resp));
free(pr->resp); free(pr->resp);
pr->resp = NULL; pr->resp = NULL;
} }

View File

@@ -101,7 +101,7 @@ sudo_passwd_cleanup(struct passwd *pw, sudo_auth *auth, bool force)
debug_decl(sudo_passwd_cleanup, SUDOERS_DEBUG_AUTH); debug_decl(sudo_passwd_cleanup, SUDOERS_DEBUG_AUTH);
if (pw_epasswd != NULL) { if (pw_epasswd != NULL) {
memset_s(pw_epasswd, SUDO_CONV_REPL_MAX, 0, strlen(pw_epasswd)); explicit_bzero(pw_epasswd, strlen(pw_epasswd));
free(pw_epasswd); free(pw_epasswd);
} }
debug_return_int(AUTH_SUCCESS); debug_return_int(AUTH_SUCCESS);

View File

@@ -102,7 +102,7 @@ sudo_secureware_cleanup(struct passwd *pw, sudo_auth *auth, bool force)
debug_decl(sudo_secureware_cleanup, SUDOERS_DEBUG_AUTH); debug_decl(sudo_secureware_cleanup, SUDOERS_DEBUG_AUTH);
if (pw_epasswd != NULL) { if (pw_epasswd != NULL) {
memset_s(pw_epasswd, SUDO_CONV_REPL_MAX, 0, strlen(pw_epasswd)); explicit_bzero(pw_epasswd, strlen(pw_epasswd));
free(pw_epasswd); free(pw_epasswd);
} }
debug_return_int(AUTH_SUCCESS); debug_return_int(AUTH_SUCCESS);

View File

@@ -177,7 +177,7 @@ sudo_securid_verify(struct passwd *pw, char *pass, sudo_auth *auth, struct sudo_
ACE challenges for the next token displayed ACE challenges for the next token displayed
(entered without the PIN) */ (entered without the PIN) */
if (pass != NULL) { if (pass != NULL) {
memset_s(pass, SUDO_PASS_MAX, 0, strlen(pass)); explicit_bzero(pass, strlen(pass));
free(pass); free(pass);
} }
pass = auth_getpass("\ pass = auth_getpass("\
@@ -218,7 +218,7 @@ then enter the new token code.\n", \
SD_Close(*sd); SD_Close(*sd);
if (pass != NULL) { if (pass != NULL) {
memset_s(pass, SUDO_PASS_MAX, 0, strlen(pass)); explicit_bzero(pass, strlen(pass));
free(pass); free(pass);
} }

View File

@@ -90,7 +90,7 @@ sudo_sia_verify(struct passwd *pw, char *prompt, sudo_auth *auth,
/* Check password and zero out plaintext copy. */ /* Check password and zero out plaintext copy. */
rc = sia_ses_authent(NULL, pass, siah); rc = sia_ses_authent(NULL, pass, siah);
memset_s(pass, SUDO_CONV_REPL_MAX, 0, strlen(pass)); explicit_bzero(pass, strlen(pass));
free(pass); free(pass);
if (rc == SIASUCCESS) if (rc == SIASUCCESS)

View File

@@ -326,7 +326,7 @@ verify_user(struct passwd *pw, char *prompt, int validated,
break; break;
} }
if (pass != NULL) { if (pass != NULL) {
memset_s(pass, SUDO_CONV_REPL_MAX, 0, strlen(pass)); explicit_bzero(pass, strlen(pass));
free(pass); free(pass);
} }

View File

@@ -116,7 +116,7 @@ sub mkdep {
# XXX - fill in AUTH_OBJS from contents of the auth dir instead # XXX - fill in AUTH_OBJS from contents of the auth dir instead
$makefile =~ s:\@AUTH_OBJS\@:afs.lo aix_auth.lo bsdauth.lo dce.lo fwtk.lo getspwuid.lo kerb5.lo pam.lo passwd.lo rfc1938.lo secureware.lo securid5.lo sia.lo:; $makefile =~ s:\@AUTH_OBJS\@:afs.lo aix_auth.lo bsdauth.lo dce.lo fwtk.lo getspwuid.lo kerb5.lo pam.lo passwd.lo rfc1938.lo secureware.lo securid5.lo sia.lo:;
$makefile =~ s:\@DIGEST\@:digest.lo digest_openssl.lo digest_gcrypt.lo:; $makefile =~ s:\@DIGEST\@:digest.lo digest_openssl.lo digest_gcrypt.lo:;
$makefile =~ s:\@LTLIBOBJS\@:arc4random.lo arc4random_uniform.lo closefrom.lo dup3.lo fchmodat.lo fstatat.lo fnmatch.lo getaddrinfo.lo getcwd.lo getentropy.lo getgrouplist.lo getdelim.lo getopt_long.lo getusershell.lo glob.lo inet_ntop_lo inet_pton.lo isblank.lo memrchr.lo memset_s.lo mksiglist.lo mksigname.lo mktemp.lo nanosleep.lo openat.lo pipe2.lo pw_dup.lo reallocarray.lo sha2.lo sig2str.lo siglist.lo signame.lo snprintf.lo str2sig.lo strlcat.lo strlcpy.lo strndup.lo strnlen.lo strsignal.lo unlinkat.lo utimens.lo vsyslog.lo:; $makefile =~ s:\@LTLIBOBJS\@:arc4random.lo arc4random_uniform.lo closefrom.lo dup3.lo explicit_bzero.lo fchmodat.lo fstatat.lo fnmatch.lo getaddrinfo.lo getcwd.lo getentropy.lo getgrouplist.lo getdelim.lo getopt_long.lo getusershell.lo glob.lo inet_ntop_lo inet_pton.lo isblank.lo memrchr.lo mksiglist.lo mksigname.lo mktemp.lo nanosleep.lo openat.lo pipe2.lo pw_dup.lo reallocarray.lo sha2.lo sig2str.lo siglist.lo signame.lo snprintf.lo str2sig.lo strlcat.lo strlcpy.lo strndup.lo strnlen.lo strsignal.lo unlinkat.lo utimens.lo vsyslog.lo:;
# Parse OBJS lines # Parse OBJS lines
my %objs; my %objs;

View File

@@ -80,7 +80,7 @@ sudo_conversation(int num_msgs, const struct sudo_conv_message msgs[],
sudo_fatalx_nodebug(U_("%s: %s"), "sudo_conversation", sudo_fatalx_nodebug(U_("%s: %s"), "sudo_conversation",
U_("unable to allocate memory")); U_("unable to allocate memory"));
} }
memset_s(pass, SUDO_CONV_REPL_MAX, 0, strlen(pass)); explicit_bzero(pass, strlen(pass));
break; break;
case SUDO_CONV_ERROR_MSG: case SUDO_CONV_ERROR_MSG:
fp = stderr; fp = stderr;
@@ -135,7 +135,7 @@ err:
struct sudo_conv_reply *repl = &replies[n]; struct sudo_conv_reply *repl = &replies[n];
if (repl->reply == NULL) if (repl->reply == NULL)
continue; continue;
memset_s(repl->reply, SUDO_CONV_REPL_MAX, 0, strlen(repl->reply)); explicit_bzero(repl->reply, strlen(repl->reply));
free(repl->reply); free(repl->reply);
repl->reply = NULL; repl->reply = NULL;
} while (n--); } while (n--);