From nobody Wed Jan 22 18:39:22 2025 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4YdXt26dpKz5krwd; Wed, 22 Jan 2025 18:39:22 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R11" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4YdXt25vVQz42bg; Wed, 22 Jan 2025 18:39:22 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1737571162; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=8H+GfHAYT+zWBTypsxba60HSD746WdFAXLrwYNUrRew=; b=f7ZtcjtgQpmWhx46b7K4r7nd1DFzHhMvDRGEUbUO3w72eo4izMXJgsMnkrHB1eMeUVNhof zbi2kv93eW1JORaKQdDCTqE7i7Vso+p6b2PZVzUCFcWDH8Zdw9QpALhE+m7SZueMnvdevc KWx5EL8t2SgLRakkh5mcfi5WnPILO8jTFucjNUsvDX4OCYGebh6YAZWsabWaka34Nln67X YYdh6NNCc5YAk9fKhhrmlMwP+SNdWp0/ywCKjnpjVIlQLmdylM5Bad4KdVxci00M2NELQk rswaMuZCKemsm7MRZu5Ylc7kW9l+94QHqFv7ifDieurzpyDW25CQ5CM+qQQA+w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1737571162; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=8H+GfHAYT+zWBTypsxba60HSD746WdFAXLrwYNUrRew=; b=CR1rZVQeOuidC6LzUx0xN05lXRO11S9MZ2vHwwkl91w7Q6wNvgqNP+EihPtRP5Y50+wPQz 9gKXeSVMrcyMJZndjsO2tE4i8PywgQ7PriHswYQTOqCuuSXeBNBIFnw+wVsXedKN21Hne9 4pBh6fJLEOAI1k6UgsF8GqAsQU6IuSNyyI+NpoOs9nc9KhKyMXPQ2/P48fL8ZEQ/z1pk4D REJX1wsKWYingS/XRhWcNTTxYgpyZDlhgZt5a0/kKVTA517Z71AVpRW3l4wsPnaSxxgzAW 0KkDnOCTIOyfOIDc+hp47p2HqKz54Be0n8qfvoNkq57JDdl8ucGqXPyakbwnaA== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1737571162; a=rsa-sha256; cv=none; b=Bwm9WwULrXK/nl4p4e95ZGQL29+GxuMZXAvme2VNZaJ/1t1ij/89AdHQTjIFb1NQx426QF CEQvPWm94Y23JCqy2OKqrjFqNLL9Xk3yuQA8k/laFwjMVl5DAax04FLMjn7ZCQqIT7YzAn fYsA/kMNjT7xOtKGDH5qH5MQyW9exVlxCk1RDoC/igsOkSjRPx6HPoDJrFigXf3323o3fQ O8NJVvZpYxbuH2Q2udCfc1PnOOoARnTzzqRb1aGTjrC7vtY24ZhP7OjJ5RYqqMT0N19t96 WvcrOcj/rK8PUTsSN5dUdDFlPaUri7t1IQwK3qAhxYNIIoWLPUEu39WLMfa4Xw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4YdXt24zLKz14Cx; Wed, 22 Jan 2025 18:39:22 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 50MIdMeK053065; Wed, 22 Jan 2025 18:39:22 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 50MIdMIx053062; Wed, 22 Jan 2025 18:39:22 GMT (envelope-from git) Date: Wed, 22 Jan 2025 18:39:22 GMT Message-Id: <202501221839.50MIdMIx053062@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Alexander Leidinger Subject: git: 2a44cccd404d - main - Add option to clear caller-used registers on function return. List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-main@freebsd.org Sender: owner-dev-commits-src-main@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: netchild X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 2a44cccd404d94c273c78e279df3fdc5531d25a2 Auto-Submitted: auto-generated The branch main has been updated by netchild: URL: https://cgit.FreeBSD.org/src/commit/?id=2a44cccd404d94c273c78e279df3fdc5531d25a2 commit 2a44cccd404d94c273c78e279df3fdc5531d25a2 Author: Alexander Leidinger AuthorDate: 2025-01-11 12:48:50 +0000 Commit: Alexander Leidinger CommitDate: 2025-01-22 18:33:23 +0000 Add option to clear caller-used registers on function return. The WITH_ZEROREGS option for src.conf will zero caller-used register contents just before returning from a function, ensuring that temporary values are not leaked beyond the function boundary. This means that register contents are less likely to be available for side channel attacks and information exposures. It reduces all except 1 of the simple "write-what-where" ROP gadgets in /lib: grep "Gadget found" /tmp/before_lib* | wc -l 197 grep "Gadget found" /tmp/after_lib* | wc -l 1 grep "Gadget found" /tmp/after_lib* /tmp/after_libbsdxml.so.4.txt: [+] Gadget found: 0x1b3f1 mov qword ptr [rdi], rcx ; pop rbp ; ret To reproduce: for lib in *.so.*; do echo $lib: ROPgadget --ropchain --binary /tmp/be_mount.Sx87/lib/$lib | sed -n '/Step 1/,/Step 2/p' >! /tmp/before_$lib.txt ROPgadget --ropchain --binary $lib | sed -n '/Step 1/,/Step 2/p' >! /tmp/after_$lib.txt done Additionally, in some cases this reduces the number of all ROP gadgets (quick check with /libs only): libalias.so.7: reduction 10.000% libavl.so.2: reduction 13.900% libbsdxml.so.4: reduction 37.500% libc.so.7: reduction 10.000% libc++.so.1: reduction 14.800% libcam.so.7: reduction 50.700% libcap_netdb.so.1: reduction 5.800% libcasper.so.1: reduction 14.600% libcrypto.so.30: reduction 7.500% libdtrace.so.2: reduction 3.900% libelf.so.2: reduction 15.800% libgcc_s.so.1: reduction 32.700% libibverbs.so.1: reduction 5.300% libicp.so.3: reduction 2.100% libipt.so.0: reduction 28.200% libirdma.so.1: reduction 1.600% libkiconv.so.4: reduction 0% libm.so.5: reduction 21.900% libmd.so.6: reduction 0% libmd.so.7: reduction 3.100% libncursesw.so.9: reduction 11.200% libnvpair.so.2: reduction 40.200% libpcap.so.8: reduction 11.400% libpjdlog.so.0: reduction 27.400% libsbuf.so.6: reduction 2.900% libspl.so.2: reduction 42.300% libsys.so.7: reduction 2.700% libthr.so.3: reduction 21.000% libuutil.so.2: reduction 13.100% libz.so.6: reduction 5.600% libzpool.so.2: reduction 15.100% In some cases it adds some ROP gadgets despite removing the simple ROP gadgets: lib80211.so.1: reduction -32.700% libbe.so.1: reduction -22.300% libbegemot.so.4: reduction -20.500% libcap_dns.so.2: reduction -58.000% libcap_fileargs.so.1: reduction -28.200% libcap_grp.so.1: reduction -54.000% libcap_net.so.1: reduction -28.800% libcap_pwd.so.1: reduction -38.800% libcap_sysctl.so.2: reduction -71.100% libcap_syslog.so.1: reduction -15.000% libcrypt.so.5: reduction -14.600% libctf.so.2: reduction -.300% libcxxrt.so.1: reduction -14.000% libdevstat.so.7: reduction -1.600% libedit.so.8: reduction -4.200% libgeom.so.5: reduction -16.500% libicp_rescue.so.3: reduction -2.300% libipsec.so.4: reduction -31.800% libjail.so.1: reduction -21.700% libkvm.so.7: reduction -5.300% libmlx5.so.1: reduction -6.300% libmt.so.5: reduction -23.000% libnv.so.1: reduction -.400% librss.so.1: reduction -3.800% librt.so.1: reduction -24.000% libssp.so.0: reduction -21.100% libstats.so.0: reduction -9.000% libtinfow.so.9: reduction -3.500% libtpool.so.2: reduction -36.500% libufs.so.8: reduction -11.900% libulog.so.0: reduction -67.400% libumem.so.2: reduction -2.000% libutil.so.9: reduction -7.200% libxo.so.0: reduction -9.000% libzdb.so.2: reduction -11.700% libzfs_core.so.2: reduction -17.700% libzfs.so.4: reduction -.300% libzfsbootenv.so.1: reduction -26.900% libzutil.so.2: reduction -5.600% To reproduce: for lib in *.so.*; do echo -n $lib: before="$(ROPgadget --nosys --nojop --binary /tmp/be_mount.Sx87/lib/$lib | tail -n1 | cut -d : -f 2)" after="$(ROPgadget --nosys --nojop --binary $lib | tail -n1 | cut -d : -f 2)" echo " reduction" $(bc -S 3 -e "(1-${after}/${before})*100")% done >/tmp/reduction.txt Most of the time the size difference is very small (<1% for >50% of the files and >10% for only 2 files): lib80211.so.1: size change .100% libalias.so.7: size change 0% libavl.so.2: size change 0% libbe.so.1: size change .100% libbegemot.so.4: size change .100% libbsdxml.so.4: size change 0% libc.so.7: size change 1.200% libc++.so.1: size change 1.600% libcam.so.7: size change 1.900% libcap_dns.so.2: size change .100% libcap_fileargs.so.1: size change .100% libcap_grp.so.1: size change .100% libcap_net.so.1: size change .100% libcap_netdb.so.1: size change .100% libcap_pwd.so.1: size change .100% libcap_sysctl.so.2: size change .100% libcap_syslog.so.1: size change .100% libcasper.so.1: size change 0% libcrypt.so.5: size change 3.900% libcrypto.so.30: size change 1.400% libctf.so.2: size change .100% libcxxrt.so.1: size change .100% libdevstat.so.7: size change 15.400% exceptional libdtrace.so.2: size change .600% libedit.so.8: size change 1.800% libelf.so.2: size change .100% libgcc_s.so.1: size change 3.000% libgeom.so.5: size change 0% libibverbs.so.1: size change .100% libicp_rescue.so.3: size change .100% libicp.so.3: size change 1.500% libipsec.so.4: size change .100% libipt.so.0: size change 3.100% libirdma.so.1: size change .100% libjail.so.1: size change .100% libkiconv.so.4: size change .100% libkvm.so.7: size change .100% libm.so.5: size change 1.700% libmd.so.6: size change 0% libmd.so.7: size change .100% libmlx5.so.1: size change 0% libmt.so.5: size change .100% libncursesw.so.9: size change 1.900% libnv.so.1: size change 4.300% libnvpair.so.2: size change 4.300% libpcap.so.8: size change 1.200% libpjdlog.so.0: size change .100% librss.so.1: size change .200% librt.so.1: size change .100% libsbuf.so.6: size change .100% libspl.so.2: size change 0% libssp.so.0: size change .100% libstats.so.0: size change .100% libsys.so.7: size change .100% libthr.so.3: size change 2.400% libtinfow.so.9: size change 1.600% libtpool.so.2: size change .100% libufs.so.8: size change .100% libulog.so.0: size change .100% libumem.so.2: size change 54.300% exceptional libutil.so.9: size change .100% libuutil.so.2: size change .100% libxo.so.0: size change .100% libz.so.6: size change .100% libzdb.so.2: size change .300% libzfs_core.so.2: size change .100% libzfs.so.4: size change 2.000% libzfsbootenv.so.1: size change .100% libzpool.so.2: size change 1.200% libzutil.so.2: size change 0% --- share/man/man5/src.conf.5 | 7 ++++++- share/mk/bsd.compiler.mk | 6 ++++++ share/mk/bsd.lib.mk | 9 +++++++++ share/mk/bsd.opts.mk | 3 ++- share/mk/bsd.prog.mk | 9 +++++++++ stand/defs.mk | 1 + tools/build/options/WITHOUT_ZEROREGS | 2 ++ tools/build/options/WITH_ZEROREGS | 4 ++++ 8 files changed, 39 insertions(+), 2 deletions(-) diff --git a/share/man/man5/src.conf.5 b/share/man/man5/src.conf.5 index 88df18b3142e..4d48edff3c80 100644 --- a/share/man/man5/src.conf.5 +++ b/share/man/man5/src.conf.5 @@ -1,5 +1,5 @@ .\" DO NOT EDIT-- this file is @generated by tools/build/options/makeman. -.Dd November 22, 2024 +.Dd January 22, 2025 .Dt SRC.CONF 5 .Os .Sh NAME @@ -1856,6 +1856,11 @@ Build without support for the IEEE 802.1X protocol and without support for EAP-PEAP, EAP-TLS, EAP-LEAP, and EAP-TTLS protocols (usable only via 802.1X). +.It Va WITH_ZEROREGS +Build the basesystem with code to zero caller-used register contents +on function return. +This prevents leaking temporary values for side channel attacks. +Additionally this reduces the number of usable ROP gadgets for attackers. .It Va WITHOUT_ZFS Do not build the ZFS file system kernel module, libraries such as .Xr libbe 3 , diff --git a/share/mk/bsd.compiler.mk b/share/mk/bsd.compiler.mk index fd236b2e6b8f..bf6ef3956d7d 100644 --- a/share/mk/bsd.compiler.mk +++ b/share/mk/bsd.compiler.mk @@ -24,6 +24,7 @@ # - retpoline: supports the retpoline speculative execution vulnerability # mitigation. # - init-all: supports stack variable initialization. +# - zeroregs: supports zeroing used registers on return # - aarch64-sha512: supports the AArch64 sha512 intrinsic functions. # # When bootstrapping on macOS, 'apple-clang' will be set in COMPILER_FEATURES @@ -263,6 +264,11 @@ ${X_}COMPILER_FEATURES+= compressed-debug ${X_}COMPILER_FEATURES+= fileprefixmap .endif +.if (${${X_}COMPILER_TYPE} == "clang" && ${${X_}COMPILER_VERSION} >= 150000) || \ + (${${X_}COMPILER_TYPE} == "gcc" && ${${X_}COMPILER_VERSION} >= 110000) +${X_}COMPILER_FEATURES+= zeroregs +.endif + .if (${${X_}COMPILER_TYPE} == "clang" && ${${X_}COMPILER_VERSION} >= 130000) || \ (${${X_}COMPILER_TYPE} == "gcc" && ${${X_}COMPILER_VERSION} >= 90000) # AArch64 sha512 intrinsics are supported (and have been tested) in diff --git a/share/mk/bsd.lib.mk b/share/mk/bsd.lib.mk index d669dccdc268..cf4140d0b3e6 100644 --- a/share/mk/bsd.lib.mk +++ b/share/mk/bsd.lib.mk @@ -118,6 +118,15 @@ CXXFLAGS+= -enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-cl .endif .endif +# Zero used registers on return (mitigate some ROP) +.if ${MK_ZEROREGS} != "no" +.if ${COMPILER_FEATURES:Mzeroregs} +ZEROREG_TYPE?= used +CFLAGS+= -fzero-call-used-regs=${ZEROREG_TYPE} +CXXFLAGS+= -fzero-call-used-regs=${ZEROREG_TYPE} +.endif +.endif + # bsd.sanitizer.mk is not installed, so don't require it (e.g. for ports). .sinclude "bsd.sanitizer.mk" diff --git a/share/mk/bsd.opts.mk b/share/mk/bsd.opts.mk index c05de9b079ce..f79c5bc61a20 100644 --- a/share/mk/bsd.opts.mk +++ b/share/mk/bsd.opts.mk @@ -81,7 +81,8 @@ __DEFAULT_NO_OPTIONS = \ RETPOLINE \ STALE_STAGED \ UBSAN \ - UNDEFINED_VERSION + UNDEFINED_VERSION \ + ZEROREGS __DEFAULT_DEPENDENT_OPTIONS = \ MAKE_CHECK_USE_SANDBOX/TESTS \ diff --git a/share/mk/bsd.prog.mk b/share/mk/bsd.prog.mk index 89534b21d0e7..1894a8b938d0 100644 --- a/share/mk/bsd.prog.mk +++ b/share/mk/bsd.prog.mk @@ -90,6 +90,15 @@ CXXFLAGS+= -enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-cl .endif .endif +# Zero used registers on return (mitigate some ROP) +.if ${MK_ZEROREGS} != "no" +.if ${COMPILER_FEATURES:Mzeroregs} +ZEROREG_TYPE?= used +CFLAGS+= -fzero-call-used-regs=${ZEROREG_TYPE} +CXXFLAGS+= -fzero-call-used-regs=${ZEROREG_TYPE} +.endif +.endif + # bsd.sanitizer.mk is not installed, so don't require it (e.g. for ports). .sinclude "bsd.sanitizer.mk" diff --git a/stand/defs.mk b/stand/defs.mk index fa3c89a4c3cc..f39966f2ca8e 100644 --- a/stand/defs.mk +++ b/stand/defs.mk @@ -11,6 +11,7 @@ FORTIFY_SOURCE= 0 MK_CTF= no MK_SSP= no MK_PIE= no +MK_ZEROREGS= no MAN= .if !defined(PIC) NO_PIC= diff --git a/tools/build/options/WITHOUT_ZEROREGS b/tools/build/options/WITHOUT_ZEROREGS new file mode 100644 index 000000000000..edaf5fd8d6c9 --- /dev/null +++ b/tools/build/options/WITHOUT_ZEROREGS @@ -0,0 +1,2 @@ +Do not build build the basesystem with code to zero caller-used register +contents on function return. diff --git a/tools/build/options/WITH_ZEROREGS b/tools/build/options/WITH_ZEROREGS new file mode 100644 index 000000000000..1fc4b856bd50 --- /dev/null +++ b/tools/build/options/WITH_ZEROREGS @@ -0,0 +1,4 @@ +Build the basesystem with code to zero caller-used register contents +on function return. +This prevents leaking temporary values for side channel attacks. +Additionally this reduces the number of usable ROP gadgets for attackers.