Qualification-wise, it's fine. With each expression split into a statement:
int *p = 0; // ok int **addrp = &p; // ok int const *const *caddrq = addrp; // ok, qualification conv. according to §4.4/4 int const *q = *caddrq; // ok
Note that the rules of const_cast (§5.2.11/3) are identical to those of qualification conversion, but without the requirement of being monotonically increasing in qualification. In your case, because you're only ever adding qualifications the const_cast is unnecessary.
Concerning aliasing, I don't think it's an issue, here, or at least it's not intended to be.
Like you mentioned, there's a new bullet in the C++0x list of allowed access methods (§3.10) that allows similar types ("similar" being types arising from qualification conversions). In C++03 that bullet is missing, but I suspect that the bullet about allowing more cv-qualified access was meant to cover that, but it technically isn't so (that is, the commitee overlooked this).
double*to a function taking adouble const*would cause UB? I'd be amazed if this were truedouble **into a function taking adouble const**is UB (when that function uses it), but the example you give is not a consequence of this being UB. If this even is UB, I mean.