From 9a008232c0575e15cbb0f8b46dd7886e41eb15da Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Fri, 14 Jun 2024 11:19:08 -0700 Subject: [PATCH] sys: Replace SOPT_SET/GETCAP with sooptcopyincap This requires smaller changes in socket option consumers avoiding the need to store the original direction after calling sooptcopyin. While here, change the in-kernel copies for sooptcopyin and sooptcopyout to clear tags via bcopynocap() instead of bcopy(). --- sys/kern/uipc_socket.c | 74 ++++++++++++++++------------------------ sys/netinet/tcp_usrreq.c | 18 ++-------- sys/sys/sockopt.h | 10 +++--- 3 files changed, 38 insertions(+), 64 deletions(-) diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index b8f96217d6ec..51173e97fdd5 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -3017,19 +3017,32 @@ 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) { + if (sopt->sopt_td != NULL) + return (copyin(sopt->sopt_val, buf, valsize)); + + bcopynocap((__cheri_fromcap void *)sopt->sopt_val, buf, valsize); + return (0); +} + #if __has_feature(capabilities) - if (sopt->sopt_dir == SOPT_SETCAP || - sopt->sopt_dir == SOPT_GETCAP) - return (copyincap(sopt->sopt_val, buf, valsize)); - else -#endif - return (copyin(sopt->sopt_val, buf, valsize)); - } +/* Version of sooptcopyin that preserves tags. */ +int +sooptcopyincap(struct sockopt *sopt, void *buf, size_t len, size_t minlen) +{ + size_t valsize; + + if ((valsize = sopt->sopt_valsize) < minlen) + return EINVAL; + if (valsize > len) + sopt->sopt_valsize = valsize = len; + + if (sopt->sopt_td != NULL) + return (copyincap(sopt->sopt_val, buf, valsize)); bcopy((__cheri_fromcap void *)sopt->sopt_val, buf, valsize); return (0); } +#endif /* * Kernel version of setsockopt(2). @@ -3211,16 +3224,8 @@ sosetopt(struct socket *so, struct sockopt *sopt) tmpmac.m_buflen); } else #endif - { -#if __has_feature(capabilities) - sopt->sopt_dir = SOPT_SETCAP; -#endif - error = sooptcopyin(sopt, &extmac, + error = sooptcopyincap(sopt, &extmac, sizeof extmac, sizeof extmac); -#if __has_feature(capabilities) - sopt->sopt_dir = SOPT_SET; -#endif - } if (error) goto bad; error = mac_setsockopt_label(sopt->sopt_td->td_ucred, @@ -3288,15 +3293,10 @@ sooptcopyout(struct sockopt *sopt, const void *buf, size_t len) valsize = min(len, sopt->sopt_valsize); sopt->sopt_valsize = valsize; if (sopt->sopt_val != NULL) { - if (sopt->sopt_td != NULL) { -#if __has_feature(capabilities) - KASSERT(sopt->sopt_dir != SOPT_GETCAP && - sopt->sopt_dir != SOPT_SETCAP, - ("exporting capabilities not supproted")); -#endif + if (sopt->sopt_td != NULL) error = copyout(buf, sopt->sopt_val, valsize); - } else - bcopy(buf, (__cheri_fromcap void *)sopt->sopt_val, + else + bcopynocap(buf, (__cheri_fromcap void *)sopt->sopt_val, valsize); } return (error); @@ -3438,16 +3438,8 @@ sogetopt(struct socket *so, struct sockopt *sopt) tmpmac.m_buflen); } else #endif - { -#if __has_feature(capabilities) - sopt->sopt_dir = SOPT_GETCAP; -#endif - error = sooptcopyin(sopt, &extmac, - sizeof extmac, sizeof extmac); -#if __has_feature(capabilities) - sopt->sopt_dir = SOPT_GET; -#endif - } + error = sooptcopyincap(sopt, &extmac, + sizeof(extmac), sizeof(extmac)); if (error) goto bad; error = mac_getsockopt_label(sopt->sopt_td->td_ucred, @@ -3477,16 +3469,8 @@ sogetopt(struct socket *so, struct sockopt *sopt) tmpmac.m_buflen); } else #endif - { -#if __has_feature(capabilities) - sopt->sopt_dir = SOPT_GETCAP; -#endif - error = sooptcopyin(sopt, &extmac, - sizeof extmac, sizeof extmac); -#if __has_feature(capabilities) - sopt->sopt_dir = SOPT_GET; -#endif - } + error = sooptcopyincap(sopt, &extmac, + sizeof(extmac), sizeof(extmac)); if (error) goto bad; error = mac_getsockopt_peerlabel( diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c index 932d5edd231b..0121b03f7834 100644 --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -1918,7 +1918,7 @@ copyin_tls_enable(struct sockopt *sopt, struct tls_enable *tls) int error; if (sopt->sopt_valsize == sizeof(tls_v0)) { - error = sooptcopyin(sopt, &tls_v0, sizeof(tls_v0), + error = sooptcopyincap(sopt, &tls_v0, sizeof(tls_v0), sizeof(tls_v0)); if (error) return (error); @@ -1937,7 +1937,7 @@ copyin_tls_enable(struct sockopt *sopt, struct tls_enable *tls) return (0); } - return (sooptcopyin(sopt, tls, sizeof(*tls), sizeof(*tls))); + return (sooptcopyincap(sopt, tls, sizeof(*tls), sizeof(*tls))); } #endif @@ -2288,13 +2288,7 @@ tcp_default_ctloutput(struct tcpcb *tp, struct sockopt *sopt) #ifdef KERN_TLS case TCP_TXTLS_ENABLE: INP_WUNLOCK(inp); -#if __has_feature(capabilities) - sopt->sopt_dir = SOPT_SETCAP; -#endif error = copyin_tls_enable(sopt, &tls); -#if __has_feature(capabilities) - sopt->sopt_dir = SOPT_SET; -#endif if (error) break; error = ktls_enable_tx(so, &tls); @@ -2311,14 +2305,8 @@ tcp_default_ctloutput(struct tcpcb *tp, struct sockopt *sopt) break; case TCP_RXTLS_ENABLE: INP_WUNLOCK(inp); -#if __has_feature(capabilities) - sopt->sopt_dir = SOPT_SETCAP; -#endif - error = sooptcopyin(sopt, &tls, sizeof(tls), + error = sooptcopyincap(sopt, &tls, sizeof(tls), sizeof(tls)); -#if __has_feature(capabilities) - sopt->sopt_dir = SOPT_SET; -#endif if (error) break; error = ktls_enable_rx(so, &tls); diff --git a/sys/sys/sockopt.h b/sys/sys/sockopt.h index 04914139e827..ae8dd602117e 100644 --- a/sys/sys/sockopt.h +++ b/sys/sys/sockopt.h @@ -45,10 +45,6 @@ struct socket; enum sopt_dir { SOPT_GET, SOPT_SET, -#if __has_feature(capabilities) - SOPT_GETCAP, - SOPT_SETCAP, -#endif }; struct sockopt { @@ -63,6 +59,12 @@ struct sockopt { int sosetopt(struct socket *so, struct sockopt *sopt); int sogetopt(struct socket *so, struct sockopt *sopt); int sooptcopyin(struct sockopt *sopt, void *buf, size_t len, size_t minlen); +#if __has_feature(capabilities) +int sooptcopyincap(struct sockopt *sopt, void *buf, size_t len, + size_t minlen); +#else +#define sooptcopyincap sooptcopyin +#endif int sooptcopyout(struct sockopt *sopt, const void *buf, size_t len); int soopt_getm(struct sockopt *sopt, struct mbuf **mp); int soopt_mcopyin(struct sockopt *sopt, struct mbuf *m);