-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA512 OpenAFS Security Advisory 2024-003 Topic: Preallocated buffer overflows in XDR responses (CVE-2024-10397) Issued: 12 November, 2024 Affected: OpenAFS clients running versions 1.0 through 1.6.24, 1.8.0 through 1.8.12.2, and 1.9.0 through 1.9.1 A malicious server can crash the OpenAFS cache manager and other client utilities, and possibly execute arbitrary code. SUMMARY ======= Many RPCs used by OpenAFS return dynamically-sized strings, buffers, and arrays in output arguments. Callers of these RPCs may provide preallocated memory to store these results; in these cases, the XDR-marshalling routines do not check if the supplied memory is large enough to store the results. In some cases, callers provide a preallocated buffer that is smaller than the limit defined for the RPC interface; in these cases, if the server responds with more data than the preallocated buffer can hold, the XDR-marshalling code will write to memory beyond the end of the buffer, resulting in errors, crashes, or possible code execution. IMPACT ====== Depending on local configuration, a local unprivileged user may be able to contact a malicious vlserver or fileserver to trigger a buffer overflow in the cache manager. For the Unix cache manager, this means crashing the kernel or possibly executing arbitrary code in kernel mode. If the afsd daemon is running with the options '-afsdb -dynroot' (or '-afsdb - -dynroot-sparse') and the local machine has access to the public Internet, any unprivileged local user can contact a malicious cell they control via /afs/. Using the options '-afsdb -dynroot' is very common, since these are turned on by default in the packaging for OpenAFS on many platforms. If the afsd daemon is running with just '-afsdb', a local user that can create mountpoints can contact a malicious cell by creating a mountpoint to that cell and accessing it. CVSS:4.0/AV:L/AC:H/AT:N/PR:N/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N Score: 7.5 / High If the afsd daemon is not running with '-afsdb', a malicious cell can cause a buffer overflow, but the cache manager can only contact cells configured in the local CellServDB or that were specified by manually running 'fs newcell' (an operation that can only be run successfully by root). A malicious user with the ability to modify network packets can also cause a buffer overflow by modifying the responses from real servers. CVSS:4.0/AV:N/AC:H/AT:P/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N Score: 7.7 / High On Solaris kernel clients, a malicious cell can also trigger a system panic or memory corruption in the same situations, separately from the buffer overflow issues. In addition, on all platforms, a malicious cell can trigger a buffer overflow in utility programs like 'pts' and 'vos'. For example, if 'vos listaddrs' is run against a malicious cell, that server may be able to cause the 'vos' utility to crash or execute arbitrary code. It is also technically possible for servers within a cell to trigger a buffer overflow on other servers. For example, a malicious ptserver could cause a buffer overflow on a fileserver. Such an attack could only be performed by an administrator, and so is not likely to be a significant security concern. AFFECTED SOFTWARE ================= All releases of OpenAFS up to and including 1.6.24. All releases of OpenAFS 1.8.0 to 1.8.12.2. All releases of OpenAFS 1.9.0 to 1.9.1. FIXES ===== The OpenAFS project recommends that administrators upgrade all affected clients and utilities to OpenAFS version 1.6.25 or 1.8.13. For those sites unable or unwilling to upgrade, patches to resolve this issue are available via: https://www.openafs.org/pages/security/openafs-sa-2024-003-stable16.patch https://www.openafs.org/pages/security/openafs-sa-2024-003-stable18.patch https://www.openafs.org/pages/security/openafs-sa-2024-003-master.patch The issue can also be mitigated on the cache manager by limiting users' access to arbitrary remote cells. Running afsd without the -dynroot/-dynroot-sparse options prevents issue from being easily exploited by unprivileged processes, and running afsd without the -afsdb option prevents the issue from being easily exploited by any local process. DETAILS ======= RPCs that define output arguments that are a string, opaque, or array, will use the corresponding functions xdr_string(), xdr_opaque(), xdr_array(), or xdr_arrayN() to decode the server response. All of these can use a preallocated buffer to store the decoded data, but none check if the given preallocated buffer is large enough to store the response. For strings specifically, it is impossible to check if the provided buffer is large enough, because callers do not pass the size of the buffer. If the caller provides a preallocated buffer that is larger than or equal to the maximum size in the interface definition, then there is no possibility of an overflow. Otherwise, the relevant XDR routine can store more data than the given buffer has space for, overflowing the buffer. One such RPC is RXAFS_GetVolumeStatus(), which is called by the Unix and WINNT cache managers with stack-preallocated strings of size 32, 256, and 256, but the arguments have interface-defined limits of 256, 1024, and 1024, respectively. If the server responds with strings longer than 32 or 256 bytes, a buffer overflow in the stack will occur. Many other RPCs that are called in retry/fallback loops effectively use preallocated output arguments, even if they didn't intend to. For example, the Unix and WINNT cache managers also contain calls to VL_GetAddrsU() that look like this: memset(addrs, 0, sizeof(&addrs)); do { code = VL_GetAddrsU(rxconn, &attrs, &uuid, &unique, &nentries, &addrs); } while (afs_Analyze(code, args)); If the first call to VL_GetAddrsU() populates the 'addrs' argument and then aborts, we may try to call VL_GetAddrsU() again, passing the allocated 'addrs' array from the first call. This allows for a buffer overflow in the heap if the next call returns an 'addrs' array larger than the 'addrs' array allocated from the first call. All RPCs called through ubik_ wrappers (e.g. ubik_VL_GetAddrsU()) that _don't_ pass preallocated output arguments are subject to this same problem, since the underlying RPC may be called more than once by the ubik_ wrapper. This mostly happens in userspace utility programs that are contacting known servers (vos, pts, aklog), and so tends to be less of a security concern. A related problem can happen specifically for strings, specifically on Solaris in kernel code: Strings are encoded in XDR by providing a length first, followed by the string contents. But when xdr_string() frees a string, it calculates the size of the buffer by calling strlen() on the string. If a server responds with a string of length N whose contents contains a NUL byte, xdr_string() will allocate N+1 bytes of memory, but then try to free the allocated buffer by calling osi_free() with a size that is N or smaller. Most platforms ignore the size argument to osi_free(), but Solaris passes this to kmem_free(). If the size given to kmem_free() is wrong, this can cause the kernel to panic, or cause memory corruption. ACKNOWLEDGMENTS =============== Issue reported by and fix provided by Andrew Deason. Significant review provided by Mark Vitale. -----BEGIN PGP SIGNATURE----- iQG3BAEBCgAdFiEE2WGV4E2ARf9BYP0XKNmm82TrdRIFAmczuFkACgkQKNmm82Tr dRKzSQwgkKmhS1KRCQTNBTQ0OJNOJov4fiSEtGFsr3ck0GnYSUfXFMN6Y6eHftdH OWGo4e0zDpvd7xTVJPv+CB0BQI/4qtkw9bZ0pvEsU2pGEs3CXFPBLZSsuO//VYIk sv78n+vhfYSmGTYLWVoANAz2jneCH0F6bXJhXJJs8kRZ8JBDvSGTJLPYsijWzURx cWrj06497PaBwLtIoZtZpBtH5j6NCQVlur5DprmlKLCZrxmWDSR2pWRD3UbI2dSV 4ERj/zXRYLVg1KU95UBeKfgDgiHhPeUodpYygdi6neA4XH9pvGYqUuNYC5Gck5X2 R3NIF1I2TZBCFdvOuQ2MFfjOBCoxXCV7cgR0NIFWpXPwczB4Ols3oKsjZA3HuIUe k5IzGcwAm9zqiIwJnzxX5cGBXlrQ/hw9cNZ5kF7howvQ5NlCf1wLAThasvxKE3AA RfmpYkX9ZWMjrJMr1axq1JqSsPw8BqedlqnwYF3qwRHMYXd1EnaZTHhkbBkZNlwj ViSd3WgsxKoUfA== =kWaj -----END PGP SIGNATURE-----