@@ -12,21 +12,18 @@
#include <linux/uaccess.h>
typedef struct {
- union {
- void *kernel;
- void __user *user;
- };
- bool is_kernel : 1;
+ void *kernel;
+ void __user *user;
} sockptr_t;
static inline bool sockptr_is_kernel(sockptr_t sockptr)
{
- return sockptr.is_kernel;
+ return !!sockptr.kernel;
}
static inline sockptr_t KERNEL_SOCKPTR(void *p)
{
- return (sockptr_t) { .kernel = p, .is_kernel = true };
+ return (sockptr_t) { .kernel = p };
}
static inline sockptr_t USER_SOCKPTR(void __user *p)
@@ -36,9 +33,7 @@ static inline sockptr_t USER_SOCKPTR(void __user *p)
static inline bool sockptr_is_null(sockptr_t sockptr)
{
- if (sockptr_is_kernel(sockptr))
- return !sockptr.kernel;
- return !sockptr.user;
+ return !sockptr.user && !sockptr.kernel;
}
static inline int copy_from_sockptr_offset(void *dst, sockptr_t src,
The original commit for sockptr_t tried to use the pointer value to determine whether a pointer was user or kernel. This can't work on some architecures and was buffy on x86. So the is_kernel descriminator was added after the union of pointers. However this is still open to misuse and accidents. Replace the union with a struct and remove the is_kernel member. The user and kernel values are now in different places. The size doesn't change - it was always padded out to 'two pointers'. The only functional difference is that NULL pointers are always 'user'. So dereferncing will (usually) fault in copy_from_user() rather than panic if supplied as a kernel address. Simple driver code that uses kernel sockets still works. I've not tested bpf - but that should work unless it is breaking the rules. Signed-off-by: David Laight <david.laight@aculab.com> --- include/linux/sockptr.h | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-)