From: Mathieu Desnoyers <mathieu.desnoy...@efficios.com> > Sent: 13 April 2021 15:22 ... > > David > > > >> So I suppose that if we're going to #ifdef this, we might as well do the > >> whole thing. > >> > >> Mathieu; did I forget a reason why this cannot work? > > The only difference it brings on 32-bit is that the truncation of high bits > will be done before the following validation: > > if (!ptr) { > memset(rseq_cs, 0, sizeof(*rseq_cs)); > return 0; > } > if (ptr >= TASK_SIZE) > return -EINVAL; > > The question is whether we really want to issue a segmentation fault if 32-bit > user-space has set non-zero high bits, or if silently ignoring those high > bits is acceptable.
Well, 32bit programs running on 64bit kernels better zero the 'padding'. It is a shame that the 32bit compilers don't have an attribute(64bit) for pointers. > ... > I am always reluctant to use long/unsigned long type as type for the > get/put_user > (x) argument, because it hides the cast deep within architecture-specific > macros. > I understand that in this specific case it happens that on 64-bit archs we > end up > casting a u64 to unsigned long (same size), and on 32-bit archs we end up > casting a > u32 to unsigned long (also same size), so there is no practical concern about > type > promotion and sign-extension, but I think it would be better to have something > explicit, e.g.: If the ABI passes small structures in registers (most modern ones) then user pointers probably ought to be encapsulated in a structure. Possibly as a pointer to an unknown structure. That would force all the required type checking. Unfortunately the fallout/churn would be massive. > #ifdef CONFIG_64BIT > static int rseq_get_cs_ptr(struct rseq_cs __user **uptrp, struct rseq_cs > *rseq_cs) > { > u64 ptr; > > if (get_user(ptr, &rseq_cs->ptr64)) > return -EFAULT; > *ptrp = (struct rseq_cs __user *)ptr; > return 0; > } > #else > static int rseq_get_cs_ptr(struct rseq_cs __user **uptrp, struct rseq_cs > *rseq_cs) > { > u32 ptr; > > if (get_user(ptr, &rseq_cs->ptr.ptr32)) > return -EFAULT; > *ptrp = (struct rseq_cs __user *)ptr; > return 0; > } > #endif Hmmm... too much replication. You could do: #ifdef CONFIG_64BIT #define PTR_TYPE u64 #define PTR_FLD ptr64 #else #define PTR_TYPE u32 #define PTR_FLD ptr32 #endif Then have one copy of the code and the #undefs. ... David - Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK Registration No: 1397386 (Wales)