The "enable the kernel to be programmable" piece is absolutely the most insightful part about BPF/eBPF effort IMHO. Anyone who ever designed/implemented an OS/studied OS design knows that there is a lot of stuff that
has to be done in the user space for security reasons (in the "don't let a user program accidentally blow up the whole system" sense) and there is just no way around it —
or is there?
For example, consider CreateProcess vs fork/exec: at the first glance, the first one is the most obvious and sensible, you want a program launched, you point the OS at the executable and say "execute this". The second API instead makes you to make a perfect copy of the currently executing process, then you tell the OS to completely scrape and discard its state and launch another executable file inside it. Literally no other object in the system works this way (i.e. to create a new X, you must copy an already existing X first, then modify with the copy).
But then consider that you would also like to configure the environment of the newly launched program before it actually launches, and that's when CreateProcess API starts to lose its simplicity: you have to pass all imaginable (and some unimaginable) kinds of configuration, and the API has to be extensible and future-proof, too! Just look at what kind of silliness goes into thread-attribute lists [0]. But with fork/exec, you simply run the normal, user-space code that configures the current process whatever way it pleases, then swaps the executable, done — and you can't do that with CreateProcess, you can't just ask the kernel to run some arbitrary user-provided code in the kernel context... unless it's not entirely arbitrary: enter eBPF.
[0] https://learn.microsoft.com/en-us/windows/win32/api/processt...