git: f14bdfefa41c - main - CHERI: add sooptcopyinptr to preserve pointer provenance
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 01 Jul 2026 11:49:35 UTC
The branch main has been updated by brooks:
URL: https://cgit.FreeBSD.org/src/commit/?id=f14bdfefa41c7d81dd1317e61b98de22dc03016c
commit f14bdfefa41c7d81dd1317e61b98de22dc03016c
Author: Brooks Davis <brooks@FreeBSD.org>
AuthorDate: 2026-07-01 11:46:39 +0000
Commit: Brooks Davis <brooks@FreeBSD.org>
CommitDate: 2026-07-01 11:48:10 +0000
CHERI: add sooptcopyinptr to preserve pointer provenance
Most socket options don't involve pointers so make the default
sooptcopyin discard provenance and add a sooptcopyinptr that preserves.
Reviewed by: markj, emaste
Effort: CHERI upstreaming
Sponsored by: DARPA, AFRL, Innovate UK
Differential Revision: https://reviews.freebsd.org/D57665
---
share/man/man9/socket.9 | 13 ++++++++++++-
sys/kern/uipc_socket.c | 34 ++++++++++++++++++++++++++++------
sys/sys/sockopt.h | 6 ++++++
3 files changed, 46 insertions(+), 7 deletions(-)
diff --git a/share/man/man9/socket.9 b/share/man/man9/socket.9
index fb0ead0e20e1..c54716d8e155 100644
--- a/share/man/man9/socket.9
+++ b/share/man/man9/socket.9
@@ -24,7 +24,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd September 6, 2022
+.Dd July 1, 2026
.Dt SOCKET 9
.Os
.Sh NAME
@@ -146,6 +146,8 @@
.Ft int
.Fn sooptcopyin "struct sockopt *sopt" "void *buf" "size_t len" "size_t minlen"
.Ft int
+.Fn sooptcopyinptr "struct sockopt *sopt" "void *buf" "size_t len" "size_t minlen"
+.Ft int
.Fn sooptcopyout "struct sockopt *sopt" "const void *buf" "size_t len"
.Sh DESCRIPTION
The kernel
@@ -577,6 +579,15 @@ and
are useful for transferring
.Vt struct sockopt
data between user and kernel code.
+They do not preserve the provenance of pointers in copied objects
+.Pq see Xr memory_model 7 for further information .
+If the object to be copied contains pointers, the
+.Fn sooptcopyinptr
+function must be used to preserve the provenance of those pointers.
+There is no corresponding
+.Fn sooptcopyoutptr
+as the kernel does not typically return pointers to userspace objects
+and instead would update objects previously passed via sooptcopyinptr.
.Sh SEE ALSO
.Xr bind 2 ,
.Xr close 2 ,
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
index 47de87c1887c..dc4db57c07e2 100644
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -3808,8 +3808,9 @@ hhook_run_socket(struct socket *so, void *hctx, int32_t h_id)
* here, these functions are also called by the protocol-level pr_ctloutput()
* routines.
*/
-int
-sooptcopyin(struct sockopt *sopt, void *buf, size_t len, size_t minlen)
+static int
+_sooptcopyin(struct sockopt *sopt, void *buf, size_t len, size_t minlen,
+ bool copycaps)
{
size_t valsize;
@@ -3824,13 +3825,34 @@ sooptcopyin(struct sockopt *sopt, void *buf, size_t len, size_t minlen)
if (valsize > len)
sopt->sopt_valsize = valsize = len;
- if (sopt->sopt_td != NULL)
- return (copyin(sopt->sopt_val, buf, valsize));
+ if (sopt->sopt_td != NULL) {
+ if (copycaps)
+ return (copyinptr(sopt->sopt_val, buf, valsize));
+ else
+ return (copyin(sopt->sopt_val, buf, valsize));
+ }
- memcpy(buf, sopt->sopt_val, valsize);
+ if (copycaps)
+ memcpy(buf, sopt->sopt_val, valsize);
+ else
+ memcpy_data(buf, sopt->sopt_val, valsize);
return (0);
}
+int
+sooptcopyin(struct sockopt *sopt, void *buf, size_t len, size_t minlen)
+{
+ return (_sooptcopyin(sopt, buf, len, minlen, false));
+}
+
+#ifdef __CHERI__
+int
+sooptcopyinptr(struct sockopt *sopt, void *buf, size_t len, size_t minlen)
+{
+ return (_sooptcopyin(sopt, buf, len, minlen, true));
+}
+#endif
+
/*
* Kernel version of setsockopt(2).
*
@@ -4118,7 +4140,7 @@ sooptcopyout(struct sockopt *sopt, const void *buf, size_t len)
if (sopt->sopt_td != NULL)
error = copyout(buf, sopt->sopt_val, valsize);
else
- memcpy(sopt->sopt_val, buf, valsize);
+ memcpy_data(sopt->sopt_val, buf, valsize);
}
return (error);
}
diff --git a/sys/sys/sockopt.h b/sys/sys/sockopt.h
index d2b0ff5ed2c8..54d0afe673d5 100644
--- a/sys/sys/sockopt.h
+++ b/sys/sys/sockopt.h
@@ -59,6 +59,12 @@ int sosetopt(struct socket *so, struct sockopt *sopt);
int sogetopt(struct socket *so, struct sockopt *sopt);
int __result_use_check sooptcopyin(struct sockopt *sopt, void *buf, size_t len,
size_t minlen);
+#ifdef __CHERI__
+int __result_use_check sooptcopyinptr(struct sockopt *sopt, void *buf,
+ size_t len, size_t minlen);
+#else
+#define sooptcopyinptr sooptcopyin
+#endif
int __result_use_check sooptcopyout(struct sockopt *sopt, const void *buf,
size_t len);
int soopt_getm(struct sockopt *sopt, struct mbuf **mp);