The null page is only really *needed* for vm86() -- for 16-bit protected mode code an LDT with a constant non-zero base offset for all segments can be used and a pure 16-bit protected mode program (I think many use vm86() though!) that runs in Wine does not even know it.
But for vm86() there is no easy and fast solution: every program that uses it (Wine, DOSEMU, X when it's been changed to run without root privs, a few others) will have to use CPU emulation. Now mapping the zero page needs CAP_SYS_RAWIO but that by itself is a much higher capability. That is, CAP_SYS_RAWIO allows direct I/O to hardware, surely giving root-like capabilities, even if the kernel is watertight. That way, one could argue for CAP_MAY_MAP_ZERO or something like that.
A technical solution would be Brad's UDEREF, or the Linux 2.0 kernel method of using segment limits, where user space needs to be accessed via FS and there is no direct kernel address space via CS/DS/ES below 3GB (keep in mind, vm86() is i386 only) but those segment limits aren't so popular anymore and I'm not sure how they interact with modern virtualization environments.
Another way would be to sandbox vm86() completely so it has the zero page,
which can be alias-mapped elsewhere, accessible -- after all inside vm86() 16-bit code you can't do system calls. But that would mean to change the page protections on every vm86() call, exit, and also on every interrupt (unmap 0 as soon as possible as an IRQ happens to be effective). Too complex, I think.