]>
git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blob - include/linux/sockptr.h
1 /* SPDX-License-Identifier: GPL-2.0-only */
3 * Copyright (c) 2020 Christoph Hellwig.
5 * Support for "universal" pointers that can point to either kernel or userspace
8 #ifndef _LINUX_SOCKPTR_H
9 #define _LINUX_SOCKPTR_H
11 #include <linux/slab.h>
12 #include <linux/uaccess.h>
22 static inline bool sockptr_is_kernel(sockptr_t sockptr
)
24 return sockptr
.is_kernel
;
27 static inline sockptr_t
KERNEL_SOCKPTR(void *p
)
29 return (sockptr_t
) { .kernel
= p
, .is_kernel
= true };
32 static inline sockptr_t
USER_SOCKPTR(void __user
*p
)
34 return (sockptr_t
) { .user
= p
};
37 static inline bool sockptr_is_null(sockptr_t sockptr
)
39 if (sockptr_is_kernel(sockptr
))
40 return !sockptr
.kernel
;
44 static inline int copy_from_sockptr_offset(void *dst
, sockptr_t src
,
45 size_t offset
, size_t size
)
47 if (!sockptr_is_kernel(src
))
48 return copy_from_user(dst
, src
.user
+ offset
, size
);
49 memcpy(dst
, src
.kernel
+ offset
, size
);
53 static inline int copy_from_sockptr(void *dst
, sockptr_t src
, size_t size
)
55 return copy_from_sockptr_offset(dst
, src
, 0, size
);
58 static inline int copy_to_sockptr_offset(sockptr_t dst
, size_t offset
,
59 const void *src
, size_t size
)
61 if (!sockptr_is_kernel(dst
))
62 return copy_to_user(dst
.user
+ offset
, src
, size
);
63 memcpy(dst
.kernel
+ offset
, src
, size
);
67 static inline void *memdup_sockptr(sockptr_t src
, size_t len
)
69 void *p
= kmalloc_track_caller(len
, GFP_USER
| __GFP_NOWARN
);
72 return ERR_PTR(-ENOMEM
);
73 if (copy_from_sockptr(p
, src
, len
)) {
75 return ERR_PTR(-EFAULT
);
80 static inline void *memdup_sockptr_nul(sockptr_t src
, size_t len
)
82 char *p
= kmalloc_track_caller(len
+ 1, GFP_KERNEL
);
85 return ERR_PTR(-ENOMEM
);
86 if (copy_from_sockptr(p
, src
, len
)) {
88 return ERR_PTR(-EFAULT
);
94 static inline long strncpy_from_sockptr(char *dst
, sockptr_t src
, size_t count
)
96 if (sockptr_is_kernel(src
)) {
97 size_t len
= min(strnlen(src
.kernel
, count
- 1) + 1, count
);
99 memcpy(dst
, src
.kernel
, len
);
102 return strncpy_from_user(dst
, src
.user
, count
);
105 #endif /* _LINUX_SOCKPTR_H */