#include two headers with an identical path, but you can install one outside of the normal paths and have it supersede those when you compile by using the appropriate switch (for gcc,
-I). I think you understand that stuff already, so it should not take too much thinking to recognize that you if you place more than one
asm/fcntl.h in normal include directories, only one of them will apply anyway.
I don't think you have much to worry about, however. Starting with some of your comments:
Those features in the userspace program that use newer kernel mechanisms can be disabled.
This is good. If you need
#define NEWVALUE 666 in order to compile, and that involves a feature that will only work on a newer kernel and you can catch or disable the use of such otherwise, then the sections that actually apply
NEWVALUE will never get called. Remember, it's not that there's no header defining this available when the old kernel is running -- even if there was, it wouldn't matter, since the real problem at runtime is that you've effectively invoked a non-existent part of the kernel ABI. You don't need any headers at all present just to run an executable, so going back to the old kernel won't matter for that.
Perhaps I'm being paranoid but...
Yes and no. If this is a system where various people arbitrary swap in different kernel headers in order to exploit new features when compiling stuff that's going to be left around and run later using an older kernel, then paranoia is an appropriate response, lol. However, there's probably not much that really falls into this category.
Distros replace the kernel headers at every upgrade, but the list of user land things they have to replace at the same time usually seems not so long (if it exists at all). I suppose that's in part because maintaining backward compatibility in this context is pretty easy, but I think it's also because things in this context don't change drastically over time.
I suppose I could save off the old headers and reinstall them.
You could do that, or you could replace them from the appropriate source when needed (
make headers_install); if it's a distro kernel and you are worried they may be patched, the distro should have a source package for it.