They provide knobs which actually reflect backing resources rather than limiting something arbitrary like the number of open files. Not to mention that you can limit the amount of kernel memory used by a process (not possible with rlimits).
Also, rlimits have interesting interactions once a process starts changing its user ID or session ID. cgroups are actually linked directly to the set of processes in the cgroup, and it's completely transparent what's going on. rlimits are not transparent and have odd semantics that aren't described in the man page.
Not to mention that rlimits use signals for communicating when you've started to hit some of the limits. This is not a good idea (Unix signals are just bad in so many ways it's not funny). So you can't be sure that your process will ever figure out that its hitting a limit.
> do you think they make any specific attack vector impossible, or harder
Kernel memory exhaustion is harder because you can be sure that your limits are actually limiting the backing resource you're trying to protect. The rlimits for open files and similar things are just not useful for things like that.
Also, there are things like the blkio cgroup which don't have an rlimit analogue. And then there's the fact that RLIMIT_CPU is completely useless (you shouldn't care about how much real time a process runs for, you should be limiting what fraction of the total cpu power it can take up from the system).
In general, POSIX rlimits are just underpowered as a resource control mechanism IMO. Especially since many are more historical artifacts than anything else.