We don't necessarily prevent the bugs themselves, though it is true we sometimes have fixes for things that aren't fixed in mainline. I imagine what you mean is that exploitation of the bugs is prevented in grsec kernels. That's been true in many cases at different levels.
Often, we turn vulnerabilities that can be exploited for privilege elevation into DoSes. The reason is that we've detected something that shouldn't have happened that we know can be abused, so it's not safe to allow the system to continue running.
Some vulnerabilities are prevented completely, like those of the form:
buf = kmalloc(attacker_controlled_size * something, GFP_ANYTHING);
instead of overflowing and allowing exploitation, we detect the overflow and cause buf to be set to NULL. We also add additional bounds checking to copy_*_user calls, both against the kernel stack and kernel heap.
Other features of grsecurity prevent exploitation of certain bugs by reducing attack surface. For example, GRKERNSEC_MODHARDEN prevents attackers from auto-loading an unused kernel module just so that it can be exploited. This reduces the risk from numerous obscure driver vulnerabilities (like the recent RDS vulnerability).
Finally, a number of features of grsecurity and PaX work together to make exploitation of the remaining vulnerabilities quite difficult in many cases. Symbol hiding, PAX_KERNEXEC, and PAX_UDEREF all work together to make the kernel a hostile environment to attackers. In general, memory corruption exploits should require an arbitrary read bug in addition to whatever vulnerability is being exploited. Any exploits have to be written considerably different as the ring-0 payload to execute can no longer be located in userland (as it is with every public exploit in existence).
Since we have a couple more people now writing exploits (Kees, Tavis, Dan) I'd actually like to see a memory corruption exploit that works against a grsec kernel with a writeup about the process involved.