forked from pool/xorg-x11-server
Stefan Dirsch
0c00d6fdc4
- Update to version 1.19.4: A collection of stability fixes from the development branch, including two minor CVEs (CVE-2017-13721, CVE-2017-13723). - Remove upstream patches: + U_Xi-Do-not-try-to-swap-GenericEvent.patch + U_Xi-Verify-all-events-in-ProcXSendExtensionEvent.patch + U_Xi-Zero-target-buffer-in-SProcXSendExtensionEvent.patch + U_dix-Disallow-GenericEvent-in-SendEvent-request.patch - Adapt patches to work with the new release: + u_Use-better-fallbacks-to-generate-cookies-if-arc4rand.patch OBS-URL: https://build.opensuse.org/request/show/531711 OBS-URL: https://build.opensuse.org/package/show/X11:XOrg/xorg-x11-server?expand=0&rev=676
236 lines
6.5 KiB
Diff
236 lines
6.5 KiB
Diff
From 44a643812ce3c07cd38972abfa9dbd163529c192 Mon Sep 17 00:00:00 2001
|
|
From: Matthias Gerstner <mgerstner@suse.de>
|
|
Date: Thu, 13 Jul 2017 14:58:04 +0200
|
|
Subject: [PATCH] Use better fallbacks to generate cookies if arc4random_buf(3)
|
|
is unavailable
|
|
References: bsc#1025084
|
|
|
|
If arc4random_buf() is not available for generating cookies:
|
|
|
|
- use getentropy(), if available (which was only recently added to
|
|
glibc)
|
|
- use getrandom() via syscall(), if available (there was no glibc
|
|
wrapper for this syscall for a long time)
|
|
- if all else fails, directly read from /dev/urandom as before, but
|
|
employ O_CLOEXEC, do an OsAbort() in case the random data couldn't be
|
|
read to avoid unsecure situations. Don't know if that's too hard a
|
|
measure but it shouldn't actually occur except on maximum number of
|
|
FDs reached
|
|
|
|
Reviewed-by: Stefan Dirsch <sndirsch@suse.de>
|
|
---
|
|
configure.ac | 4 +-
|
|
include/dix-config.h.in | 6 +++
|
|
os/auth.c | 138 ++++++++++++++++++++++++++++++++++++++++++++++--
|
|
3 files changed, 141 insertions(+), 7 deletions(-)
|
|
|
|
Index: xorg-server-1.19.3/configure.ac
|
|
===================================================================
|
|
--- xorg-server-1.19.3.orig/configure.ac
|
|
+++ xorg-server-1.19.3/configure.ac
|
|
@@ -134,7 +134,7 @@ AM_CONDITIONAL(SPECIAL_DTRACE_OBJECTS, [
|
|
AC_HEADER_DIRENT
|
|
AC_HEADER_STDC
|
|
AC_CHECK_HEADERS([fcntl.h stdlib.h string.h unistd.h dlfcn.h stropts.h \
|
|
- fnmatch.h sys/mkdev.h sys/sysmacros.h sys/utsname.h])
|
|
+ fnmatch.h sys/mkdev.h sys/sysmacros.h sys/utsname.h sys/syscall.h])
|
|
|
|
dnl Checks for typedefs, structures, and compiler characteristics.
|
|
AC_C_CONST
|
|
@@ -226,7 +226,7 @@ AC_REPLACE_FUNCS([reallocarray strcasecm
|
|
AM_CONDITIONAL(POLL, [test "x$ac_cv_func_poll" = "xyes"])
|
|
|
|
AC_CHECK_LIB([bsd], [arc4random_buf])
|
|
-AC_CHECK_FUNCS([arc4random_buf])
|
|
+AC_CHECK_FUNCS([arc4random_buf getentropy])
|
|
|
|
AC_CHECK_DECLS([program_invocation_short_name], [], [], [[#include <errno.h>]])
|
|
|
|
Index: xorg-server-1.19.3/include/dix-config.h.in
|
|
===================================================================
|
|
--- xorg-server-1.19.3.orig/include/dix-config.h.in
|
|
+++ xorg-server-1.19.3/include/dix-config.h.in
|
|
@@ -167,6 +167,9 @@
|
|
/* Define to 1 if you have the `arc4random_buf' function. */
|
|
#undef HAVE_ARC4RANDOM_BUF
|
|
|
|
+/* Define to 1 if you have the `getentropy' function. */
|
|
+#undef HAVE_GETENTROPY
|
|
+
|
|
/* Define to use libc SHA1 functions */
|
|
#undef HAVE_SHA1_IN_LIBC
|
|
|
|
@@ -244,6 +247,9 @@
|
|
/* Define to 1 if you have the <sys/utsname.h> header file. */
|
|
#undef HAVE_SYS_UTSNAME_H
|
|
|
|
+/* Define to 1 if you have the <sys/syscall.h> header file. */
|
|
+#undef HAVE_SYS_SYSCALL_H
|
|
+
|
|
/* Define to 1 if you have the `timingsafe_memcmp' function. */
|
|
#undef HAVE_TIMINGSAFE_MEMCMP
|
|
|
|
Index: xorg-server-1.19.3/os/auth.c
|
|
===================================================================
|
|
--- xorg-server-1.19.3.orig/os/auth.c
|
|
+++ xorg-server-1.19.3/os/auth.c
|
|
@@ -48,6 +48,10 @@ from The Open Group.
|
|
#ifdef HAVE_LIBBSD
|
|
#include <bsd/stdlib.h> /* for arc4random_buf() */
|
|
#endif
|
|
+#include <errno.h>
|
|
+#ifdef HAVE_SYS_SYSCALL_H
|
|
+#include <syscall.h>
|
|
+#endif
|
|
|
|
struct protocol {
|
|
unsigned short name_length;
|
|
@@ -302,18 +306,142 @@ GenerateAuthorization(unsigned name_leng
|
|
return -1;
|
|
}
|
|
|
|
+#if ! defined(HAVE_ARC4RANDOM_BUF)
|
|
+
|
|
+// fallback function to get random data directly from /dev/urandom
|
|
+
|
|
+static int
|
|
+GetUrandom ( char *buffer, size_t length )
|
|
+{
|
|
+ int random_fd = -1;
|
|
+ int res = -1;
|
|
+ size_t filled = 0;
|
|
+
|
|
+ // larger requests are typically rejected by getentropy() / getrandom()
|
|
+ // because they could block or return partially filled buffers
|
|
+ if( length > 256 ) {
|
|
+ errno = EIO;
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ random_fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC);
|
|
+
|
|
+ if( random_fd == -1 ) {
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ while( filled < length ) {
|
|
+ res = read(random_fd, (char*)buffer + filled, length - filled);
|
|
+
|
|
+ if( res == -1 ) {
|
|
+ // shouldn't actually happen acc. to man(4) random,
|
|
+ // but you never know
|
|
+ if( errno == EINTR ) {
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ res = errno;
|
|
+ close(random_fd);
|
|
+ errno = res;
|
|
+ return -1;
|
|
+ }
|
|
+ else if( res == 0 ) {
|
|
+ close(random_fd);
|
|
+ // no more bytes available? should not happen
|
|
+ errno = EIO;
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ filled += res;
|
|
+ }
|
|
+
|
|
+ close(random_fd);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+#endif // ! defined(HAVE_ARC4RANDOM_BUF)
|
|
+
|
|
+#if !defined(HAVE_GETENTROPY) && defined(HAVE_SYS_SYSCALL_H) && defined(SYS_getrandom)
|
|
+# define TRY_GETRANDOM
|
|
+#endif
|
|
+
|
|
+#ifdef TRY_GETRANDOM
|
|
+
|
|
+/*
|
|
+ * wrapper for the getrandom() syscall which was for a long time implemented
|
|
+ * in the Linux kernel, but not wrapped in glibc
|
|
+ */
|
|
+static int
|
|
+GetRandom ( char *buffer, size_t length )
|
|
+{
|
|
+ int res;
|
|
+ size_t filled = 0;
|
|
+
|
|
+ // larger requests are typically rejected by getentropy() / getrandom()
|
|
+ // because they could block or return partially filled buffers
|
|
+ if( length > 256 )
|
|
+ {
|
|
+ errno = EIO;
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ while( filled < length )
|
|
+ {
|
|
+ /*
|
|
+ * glibc does not contain a syscall wrapper for this in older
|
|
+ * versions
|
|
+ */
|
|
+ res = syscall(SYS_getrandom, (char*)buffer + filled, length - filled, 0);
|
|
+
|
|
+ if( res == -1 )
|
|
+ {
|
|
+ if( errno == EINTR ) {
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ return -1;
|
|
+ }
|
|
+ else if( res == 0 )
|
|
+ {
|
|
+ // no more bytes available? should not happen
|
|
+ errno = EIO;
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ filled += res;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+#endif /* TRY_GETRANDOM */
|
|
+
|
|
void
|
|
GenerateRandomData(int len, char *buf)
|
|
{
|
|
#ifdef HAVE_ARC4RANDOM_BUF
|
|
arc4random_buf(buf, len);
|
|
#else
|
|
- int fd;
|
|
+ int ret = -1;
|
|
+# ifdef HAVE_GETENTROPY
|
|
+ /* use getentropy instead */
|
|
+ ret = getentropy (buf, len);
|
|
+# elif defined(TRY_GETRANDOM)
|
|
+ /* try getrandom() wrapper */
|
|
+ ret = GetRandom(buf, len);
|
|
+# endif
|
|
+
|
|
+ if( ret == -1 ) {
|
|
+ // fallback to manual reading of /dev/urandom
|
|
+ ret = GetUrandom(buf, len);
|
|
+ }
|
|
|
|
- fd = open("/dev/urandom", O_RDONLY);
|
|
- read(fd, buf, len);
|
|
- close(fd);
|
|
-#endif
|
|
+ if( ret == -1 ) {
|
|
+ // no error return possible, rather abort than have security problems
|
|
+ OsAbort();
|
|
+ }
|
|
+#endif // HAVE_ARC4RANDOM_BUF
|
|
}
|
|
|
|
#endif /* XCSECURITY */
|