If any Ubuntu maintainers are listening: PLEASE STOP DOING THIS
github.com
github.com
Ubuntu should not enable the flag when -ffreestanding is set.
#include <setjmp.h>
void __attribute__((noinline)) test(jmp_buf buf)
{
__builtin_longjmp(buf, 1);
}
int main()
{
jmp_buf buf;
if (__builtin_setjmp(buf) == 0)
test(buf);
return 0;
}
and ran it on a non-CET machine. It works fine. It does contain a CET fixup, but that CET fixup is smart enough to work regardless of whether CET is enabled.However, gcc does generate non-working code if the setjmp and the longjmp are in different files and only one is compiled with -fcf-protection=full. Ouch. I'll file a bug.
The issue is expecting it to work in a freestanding environment.
Can you call into the BIOS, EFI drivers, and have interrupt handlers and not worry about any of this at all? It really should be OK freestanding without any additional CET-specific initialization code support and mixed with non-CET code?
If so, I stand corrected.
(But then, what's all this machinery for marking code that doesn't use endbranch in glibc, ld.so, the kernel, etc, and the legacy code page bitmap for?)
The actual semantics of when the combination of gcc, ld, and glibc will try to turn CET on are not documented, as far as I can tell.
And, to be fair, as my bug report shows, there can also be issues if something has a different ABI when compiled with and without CET enabled. This shouldn't happen, but apparently it did.
Yes. And a complicating thing is here there's no loader or normal initialization code, because PXE is freestanding and invoked directly by the BIOS/EFI. CET is -probably- off...
And yes, are there any dependencies between the init code changes and GCC enabling CET and GCC builtins?
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).
That is, it doesn't make sense with -ffreestanding, but Ubuntu enables it in that case.
IBT is a rather weak indirect-branch-and-call protection scheme. IMO it's weak enough that it has dubious value, and software-only schemes can be a lot stronger. The main benefits of IBT are that it can guarantee that a program won't, even when attacked, jump to the middle of an instruction and that, since IBT is a hardware mitigation, it can provide a degree of protection against Spectre-like attacks. Specifically, the CPU won't speculatively branch to an address that isn't an indirect branch target.
SHSTK is a very strong return address protection. With SHSTK on, it's really quite difficult to convince the CPU to let RET branch to anywhere other than were the original CALL came from. This even integrates with the page tables -- the memory it uses cannot be written by normal stores. The latter part is a large part of why this isn't upstream yet: the x86 pagetable format is already a technically-indebted mess, and SHSTK makes it worse in ways that are quite nasty. It'll get sorted out eventually.
You can find SHSTK in Zen 3 (yes, AMD brought Intel's feature to market before Intel -- go AMD!) and, apparently, in one Tiger Lake part. The latter also supports IBT.
You can play with the GCC support by compiling a trivial program like this:
void test(void (*fn)())
{
fn();
}
(no Godbolt link because I didn't figure out how to extract the right output from Godbolt.) If you compile with -S -fcf-protection=branch, the indirect jump is unchanged but the function itself gets an endbr64 (or endbr32) instruction at the beginning. That's a new special NOP that means "this is a valid indirect branch target". The CPU will only allow indirect branches that land on an endbr64 instruction, so the actual indirect jump in this function is unchanged. I think GCC is clever enough to omit the endbr64 if it can prove that the address of the function is not taken.The other interesting thing that GCC does is to emit this:
.section .note.gnu.property,"a"
.align 8
.long 1f - 0f
.long 4f - 1f
.long 5
0:
.string "GNU"
1:
.align 8
.long 0xc0000002
.long 3f - 2f
2:
.long 0x3
3:
.align 8
The 0x3 changes depending on the -fcf-protection option. This is a magic incantation for the benefit of the linker and kernel declaring whether this object supports IBT and/or SHSTK. This way you don't crash if you link a non-endbr-instrumented file into a IBT-using program.Note that SHSTK support doesn't affect the code at all. The CALL and RET magic is handled by the CPU, and library functions like setjmp use special new instructions in order to keep working.
There is also CPU support for CET and IBT in the kernel. SHSTK in the kernel is a huge mess. Specifically, the x86 architecture is starting to fall apart -- there are various ill-conceived features like SYSCALL, NMI, the machine check architecture, and some fancy virtualization features that, collectively, conspire to make it extremely complicated to correctly handle all types of interrupts and interrupt-like events. SHSTK-in-kernel makes it worse, and I don't think anyone wants to try to deal with this yet. I and others have been badgering Intel and AMD for quite some time to do something about the mess that x86 kernel entries have become, and so far there are no results.
You'd be lucky, in my experience. They Know Better
I've seen plenty of things were they couldn't meet the demand, but were they were simply taking the high ground?
When they introduced Unity (? Their version of Gnome Shell, I think that is what it was called). I found unity after I did a `full-upgrade`. Suddenly my user interface was something that I could not understand, had no idea of how to use, and did not work very well. There was no path back to the user interface I knew well. I had to stop everything I was doing with the computer, way beyond what I had allocated for the upgrade.
I grizzled on our local Linux users email group (I vented I think) which was interesting because two people who worked for Canonical (Ubuntu's maker) and took it personally that I would call their employer a whole lot of bad things, for giving me "free software". I was furious.
Turns out I found later that Unity was not even ready for release and had been rushed out (I think I remember the reasons, but not sure enough to relate them).
All they needed to do was do a parallel release then I could have learnt it, evaluated it, they could have debugged it.
I went back to Ubuntu when they adopted the Gnome Shell - it is a good interface, I am convinced now.
But wind on several years and software I needed to have, but not use often, had to be installed in snaps was the final straw. Not just the waste (I want my laptop to be a integrated system, not a mess of different walled off packages) but the fact that I would no longer be in control of the updates. After the debacle of having a very buggy user interface foisted on me I am not ready to give them such control.
I understand what snaps are good for, but I am headed in a different direction.
So basically you were going to get an entirely unfamiliar interface anyway. You could get unpolished Red Hat contraption of Gnome Shell, or unpolished Canonical contraption of Unity.
If anything, Unity had more resemblance to the interface of old (eg you had static virtual desktops, which you only kinda have even today with Gnome), and if you ever used a spatial grid of workspaces (to leverage your human spatial memory: I used 3x3 grid with Emacs in the centre one and task-based workspaces around it), you were out of luck with Gnome 3.
I think Gnome 3 has become significantly more robust even before Unity's demise, but UX design-wise, Unity is much better even today after being unmaintained for years (though buggy as hell).
I thought I decided I wanted the comfort of the familiar. Over time it won me over. Which was my point.
Canonical at the time were so arrogant that they did not try to win me over, they dumped me in it
However, Gnome 2 was all but abandoned at the time, and it did not make sense for Canonical to commit to supporting it for the next 5 years with their LTS release without the help of the upstream.
All the big distributions were "forced" to switch to an unfamiliar interface. Fedora did too with Gnome Shell. Ubuntu at least had derivatives like Mate or Kubuntu that you could easily move to with an apt-get install.
They did not.
Users == Lusers thinking.
But you seem to have been already decided that they did it because they are mean, so I don't think it makes sense to continue the discussion.
https://salsa.debian.org/toolchain-team/gcc/-/commit/2f9aefe...
We did, it was called CentOS.
I think GPUs might be a different story but we have not needed those beyond the trivial usage, and those were not discrete.
Macs and Windows don't break when you install NVIDIA official drivers. Ubuntu breaks because nvidia cuda-10.0 installs nvidia-450 which fights with Ubuntu which wants to install nvidia-460 with the latest kernel, which also breaks virtualbox's official repo IN the Ubuntu repo. So either the kernel breaks or cuda and virtualbox breaks.
In any case, I as a user shouldn't have to worry about stupid things like this.
You might also like Fedora as a pretty mainstream, up to date desktop distro, but under the hood you'll find more differences like rpm instead of apt.
edit: I'd add that Linux distros are complicated: the issue in this article is hardly a reason to leave Ubuntu if it's otherwise working well for you.
EDIT: By default, non-free drivers are placed in a separate repository, and receive less support. In my case the biggest pain has been Nvidia drivers. I needed a cheap card to drive an HDMI display and all they had at the store was a GT710. That meant installing the proprietary drivers, since the free alternative had poor performance last time I checked. Every few updates it breaks, and I need to reinstall it and sign the kernel module each time. That is something to watch out for if you switch over.
One big advantage I see with other distributions is that the release support cycles are longer (5y+).
But it will greatly depend on your usage, we are pretty happy with Debian running on somewhat 300+ machines.
I keep hearing high praise about Manjaro too, that it's solid, fast, and newbie-friendly; but I haven't tried it out myself yet.
There is a mess of things wrong with the linux ecosystem and a lot of it comes down to packaging systems and package management. Once you get over a little learning curve, working with FreeBSD is a breath of fresh air.
For sure there are some narrow cases where it is, but Linux just supports sooo much more
I wouldn't call it a universal drop-in replacement, you can indeed do a whole lot with FreeBSD that you can do with a linux box.
But for the lazy package manager, this route is easier.