Consider enabling cf-protection
nirs opened this issue · 7 comments
rpmdiff complains about missing cf-protection:
Detecting usr/lib64/python3.6/site-packages/ovirt_imageio/_internal/ioutil.cpython-36m-x86_64-linux-gnu.so with not-hardened warnings '
Hardened: ioutil.cpython-36m-x86_64-linux-gnu.so: WARN: The annobin plugin was built to run on a newer version of the compiler
Hardened: ioutil.cpython-36m-x86_64-linux-gnu.so: FAIL: cf-protection test because no protection enabled
Hardened: Rerun annocheck with --verbose to see more information on the tests.
' on x86_64
Check what is this cf-protection and how to enable it for next build.
@sandrobonazzola do you have more info about this issue?
Seems like you're missing -fcf-protection=full
(x86 and x86_64 only) flag in GCC compiler options.
As of RHEL 8, all programs compiled by gcc and llvm should include the following options on the command line:
-D_FORTIFY_SOURCE=2
-D_GLIBCXX_ASSERTIONS
-fstack-protector-strong
-fexceptions
-O2
(or higher)-fcf-protection=full
(x86 and x86_64 only)-mstackrealign
(x86 only)-fPIC
(for libraries) or-fPIE
(for executables)-fstack-clash-protection
-Wl,-z,now
redhat-rpm-config
packages the required flags up into RPM_OPT_FLAGS and RPM_LD_FLAGS.
So perhaps you're missing redhat-rpm-config
in imageio dependency tree?
I see that @oliel handled the same issue by adding extra compiler arg:
https://github.com/oVirt/python-ovirt-engine-sdk4/pull/62/files
@sandrobonazzola do you mean to add "BuildRequires: redhat-rpm-config"?
We use %py3_build - I think this should be handled by the macro, and not
required all package maintainers to do extra work, which is error prone.
Yes, the buildrequires should solve. I can only guess that the %py3_build macro has been kept generic allowing to differentiate flag sets between different distributions.
I looked at the build logs in brew:
Brew root log:
http://{host}/brewroot/work/tasks/5592/43785592/root.log
DEBUG util.py:636: redhat-rpm-config noarch 125-1.el8 build 85 k
Brew build log:
http://{host}/brewroot/work/tasks/5592/43785592/build.log
gcc -pthread -DDYNAMIC_ANNOTATIONS_ENABLED=1 -DNDEBUG -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -D_GNU_SOURCE -fPIC -fwrapv -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -fPIC -I/usr/include/python3.6m -c ovirt_imageio/_internal/ioutil.c -o build/temp.linux-x86_64-3.6/ovirt_imageio/_internal/ioutil.o
gcc -pthread -shared -Wl,-z,relro -Wl,-z,now -g -Wl,-z,relro -Wl,-z,now -g -Wl,-z,relro -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection build/temp.linux-x86_64-3.6/ovirt_imageio/_internal/ioutil.o -L/usr/lib64 -lpython3.6m -o build/lib.linux-x86_64-3.6/ovirt_imageio/_internal/ioutil.cpython-36m-x86_64-linux-gnu.so
And -fcf-protection is used.
We should have:
If available, the -fcf-protection=full option was used.
Looking in redhat-rpm-config files in Fedora 35, we have:
$ grep -rn -- '-fcf-protection' /usr/lib/rpm/
/usr/lib/rpm/redhat/rpmrc:6:optflags: i686 %{__global_compiler_flags} -m32 -march=i686 -mtune=generic -msse2 -mfpmath=sse -mstackrealign -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection
/usr/lib/rpm/redhat/rpmrc:9:optflags: x86_64 %{__global_compiler_flags} -m64 %{__cflags_arch_x86_64} -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection
$ dnf whatprovides /usr/lib/rpm/redhat/rpmrc
Last metadata expiration check: 0:35:32 ago on Tue 15 Mar 2022 04:05:11 AM IST.
redhat-rpm-config-197-1.fc35.noarch : Red Hat specific rpm configuration files
Repo : fedora
Matched from:
Filename : /usr/lib/rpm/redhat/rpmrc
So this looks like an issue with redhat-rpm-config, using -fcf-protection instead of -fcf-proection=full.
gcc(1) (on Fedora 35) document several settings (full, branch, return, none, check)
but does not specify what is the default if no value is used.
-fcf-protection=[full|branch|return|none|check]
Enable code instrumentation of control-flow transfers to increase
program security by checking that target addresses of control-flow
transfer instructions (such as indirect function call, function
return, indirect jump) are valid. This prevents diverting the flow
of control to an unexpected target. This is intended to protect
against such threats as Return-oriented Programming (ROP), and
similarly call/jmp-oriented programming (COP/JOP).
The value "branch" tells the compiler to implement checking of
validity of control-flow transfer at the point of indirect branch
instructions, i.e. call/jmp instructions. The value "return"
implements checking of validity at the point of returning from a
function. The value "full" is an alias for specifying both
"branch" and "return". The value "none" turns off instrumentation.
The value "check" is used for the final link with link-time
optimization (LTO). An error is issued if LTO object files are
compiled with different -fcf-protection values. The value "check"
is ignored at the compile time.
The macro "__CET__" is defined when -fcf-protection is used. The
first bit of "__CET__" is set to 1 for the value "branch" and the
second bit of "__CET__" is set to 1 for the "return".
You can also use the "nocf_check" attribute to identify which
functions and calls should be skipped from instrumentation.
Currently the x86 GNU/Linux target provides an implementation based
on Intel Control-flow Enforcement Technology (CET) which works for
i686 processor or newer.
Testing on Fedora show:
$ make
...
gcc -Wno-unused-result -Wsign-compare -DDYNAMIC_ANNOTATIONS_ENABLED=1 -DNDEBUG -O2 -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fstack-protector-strong -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -D_GNU_SOURCE -fPIC -fwrapv -O2 -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fstack-protector-strong -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -D_GNU_SOURCE -fPIC -fwrapv -O2 -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fstack-protector-strong -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -D_GNU_SOURCE -fPIC -fwrapv -fPIC -I/usr/include/python3.10 -c ovirt_imageio/_internal/ioutil.c -o build/temp.linux-x86_64-3.10/ovirt_imageio/_internal/ioutil.o
gcc -shared -Wl,-z,relro -Wl,--as-needed -Wl,-z,now -g -Wl,-z,relro -Wl,--as-needed -Wl,-z,now -g build/temp.linux-x86_64-3.10/ovirt_imageio/_internal/ioutil.o -L/usr/lib64 -o /home/nsoffer/src/ovirt-imageio/ovirt_imageio/_internal/ioutil.cpython-310-x86_64-linux-gnu.so
Checking the built executable show:
$ annocheck -v ovirt_imageio/_internal/ioutil.cpython-310-x86_64-linux-gnu.so | grep cf-protection
Hardened: ovirt_imageio/_internal/ioutil.cpython-310-x86_64-linux-gnu.so: PASS: cf-protection test
Testing make rpm:
$ make rpm
...
gcc -Wno-unused-result -Wsign-compare -DDYNAMIC_ANNOTATIONS_ENABLED=1 -DNDEBUG -O2 -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fstack-protector-strong -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -D_GNU_SOURCE -fPIC -fwrapv -O2 -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fstack-protector-strong -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -D_GNU_SOURCE -fPIC -fwrapv -O2 -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fstack-protector-strong -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -D_GNU_SOURCE -fPIC -fwrapv -O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -fPIC -I/usr/include/python3.10 -c ovirt_imageio/_internal/ioutil.c -o build/temp.linux-x86_64-3.10/ovirt_imageio/_internal/ioutil.o
gcc -shared -Wl,-z,relro -Wl,--as-needed -Wl,-z,now -g -Wl,-z,relro -Wl,--as-needed -Wl,-z,now -g -Wl,-z,relro -Wl,--as-needed -Wl,-z,now -specs=/usr/lib/rpm/redhat/redhat-hardened-ld -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection build/temp.linux-x86_64-3.10/ovirt_imageio/_internal/ioutil.o -L/usr/lib64 -o build/lib.linux-x86_64-3.10/ovirt_imageio/_internal/ioutil.cpython-310-x86_64-linux-gnu.so
Testing the built rpm show:
$ annocheck -v dist/ovirt-imageio-common-2.4.2-0.202203151143.git089d54b.fc35.x86_64.rpm | grep cf-protection
Hardened: ./usr/lib64/python3.10/site-packages/ovirt_imageio/_internal/ioutil.cpython-310-x86_64-linux-gnu.so: PASS: cf-protection test
Looks correct.
So I think we have several issues:
- gcc: need to document the semantics of bare -fcf-protection
- redhat-rpm-config: maybe should use -fcf-protection=full
- rpmdiff: maybe need to handle better different versions of gcc/annobin
But I don't see any issue with imageio spec.
@nirs can you please report a BZ for:
So this looks like an issue with redhat-rpm-config, using -fcf-protection instead of -fcf-proection=full.
redhat-rpm-config bug: https://bugzilla.redhat.com/2065867
So turns out that redhat-rpm-config is correct when using
-fcf-protection
since it is an alias for
-fcf-protection=full
The real issue is mismatch between gcc and annobin plugin, causing a bogus failure in annocheck.
Closing since there is nothing to do on our side.