Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F144473327
D50653.id156670.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
16 KB
Referenced Files
None
Subscribers
None
D50653.id156670.diff
View Options
diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c
--- a/sys/kern/kern_prot.c
+++ b/sys/kern/kern_prot.c
@@ -2150,6 +2150,44 @@
CTLFLAG_MPSAFE, 0, 0, sysctl_unprivileged_proc_debug, "I",
"Unprivileged processes may use process debugging facilities");
+/*
+ * Return true if the object owner/group ids are subset of the active
+ * credentials.
+ */
+bool
+cr_xids_subset(struct ucred *active_cred, struct ucred *obj_cred)
+{
+ int i;
+ bool grpsubset, uidsubset;
+
+ /*
+ * Is p's group set a subset of td's effective group set? This
+ * includes p's egid, group access list, rgid, and svgid.
+ */
+ grpsubset = true;
+ for (i = 0; i < obj_cred->cr_ngroups; i++) {
+ if (!groupmember(obj_cred->cr_groups[i], active_cred)) {
+ grpsubset = false;
+ break;
+ }
+ }
+ grpsubset = grpsubset &&
+ groupmember(obj_cred->cr_rgid, active_cred) &&
+ groupmember(obj_cred->cr_svgid, active_cred);
+
+ /*
+ * Are the uids present in obj_cred's credential equal to
+ * active_cred's effective uid? This includes obj_cred's
+ * euid, svuid, and ruid.
+ */
+ uidsubset = (active_cred->cr_uid == obj_cred->cr_uid &&
+ active_cred->cr_uid == obj_cred->cr_svuid &&
+ active_cred->cr_uid == obj_cred->cr_ruid);
+
+ return (uidsubset && grpsubset);
+
+}
+
/*-
* Determine whether td may debug p.
* Returns: 0 for permitted, an errno value otherwise
@@ -2161,7 +2199,7 @@
int
p_candebug(struct thread *td, struct proc *p)
{
- int error, grpsubset, i, uidsubset;
+ int error;
KASSERT(td == curthread, ("%s: td not curthread", __func__));
PROC_LOCK_ASSERT(p, MA_OWNED);
@@ -2178,35 +2216,12 @@
if ((error = cr_bsd_visible(td->td_ucred, p->p_ucred)))
return (error);
- /*
- * Is p's group set a subset of td's effective group set? This
- * includes p's egid, group access list, rgid, and svgid.
- */
- grpsubset = 1;
- for (i = 0; i < p->p_ucred->cr_ngroups; i++) {
- if (!groupmember(p->p_ucred->cr_groups[i], td->td_ucred)) {
- grpsubset = 0;
- break;
- }
- }
- grpsubset = grpsubset &&
- groupmember(p->p_ucred->cr_rgid, td->td_ucred) &&
- groupmember(p->p_ucred->cr_svgid, td->td_ucred);
-
- /*
- * Are the uids present in p's credential equal to td's
- * effective uid? This includes p's euid, svuid, and ruid.
- */
- uidsubset = (td->td_ucred->cr_uid == p->p_ucred->cr_uid &&
- td->td_ucred->cr_uid == p->p_ucred->cr_svuid &&
- td->td_ucred->cr_uid == p->p_ucred->cr_ruid);
-
/*
* If p's gids aren't a subset, or the uids aren't a subset,
* or the credential has changed, require appropriate privilege
* for td to debug p.
*/
- if (!grpsubset || !uidsubset) {
+ if (!cr_xids_subset(td->td_ucred, p->p_ucred)) {
error = priv_check(td, PRIV_DEBUG_DIFFCRED);
if (error)
return (error);
diff --git a/sys/kern/uipc_ktls.c b/sys/kern/uipc_ktls.c
--- a/sys/kern/uipc_ktls.c
+++ b/sys/kern/uipc_ktls.c
@@ -595,6 +595,8 @@
return (error);
}
+uint64_t ktls_glob_gen = 1;
+
static int
ktls_create_session(struct socket *so, struct tls_enable *en,
struct ktls_session **tlsp, int direction)
@@ -819,6 +821,8 @@
arc4rand(tls->params.iv + 8, sizeof(uint64_t), 0);
}
+ atomic_thread_fence_rel();
+ tls->gen = atomic_fetchadd_64(&ktls_glob_gen, 1);
*tlsp = tls;
return (0);
}
@@ -861,6 +865,8 @@
memcpy(tls_new->params.cipher_key, tls->params.cipher_key,
tls->params.cipher_key_len);
+ atomic_thread_fence_rel();
+ tls_new->gen = atomic_fetchadd_64(&ktls_glob_gen, 1);
return (tls_new);
}
@@ -1940,6 +1946,8 @@
MPASS(tls->refcount == 0);
+ atomic_add_acq_64(&ktls_glob_gen, 1);
+
inp = tls->inp;
if (tls->tx) {
wlocked = INP_WLOCKED(inp);
@@ -3439,3 +3447,51 @@
TASK_INIT(&tls->disable_ifnet_task, 0, ktls_disable_ifnet_help, tls);
(void)taskqueue_enqueue(taskqueue_thread, &tls->disable_ifnet_task);
}
+
+void
+ktls_session_to_xktls_onedir(const struct ktls_session *ktls,
+ struct xktls_session_onedir *xk)
+{
+ if_t ifp;
+ struct m_snd_tag *st;
+
+ memcpy(&xk->iv, &ktls->params.iv, TLS_CBC_IMPLICIT_IV_LEN);
+ xk->gen = ktls->gen;
+#define A(m) xk->m = ktls->params.m
+ A(cipher_algorithm);
+ A(auth_algorithm);
+ A(cipher_key_len);
+ A(iv_len);
+ A(auth_key_len);
+ A(max_frame_len);
+ A(tls_vmajor);
+ A(tls_vminor);
+ A(tls_hlen);
+ A(tls_tlen);
+ A(tls_bs);
+ A(flags);
+#undef A
+ if ((st = ktls->snd_tag) != NULL &&
+ (ifp = ktls->snd_tag->ifp) != NULL)
+ strncpy(xk->ifnet, if_name(ifp), sizeof(xk->ifnet));
+}
+
+void
+ktls_session_copy_keys(const struct ktls_session *ktls,
+ uint8_t *data, size_t *sz)
+{
+ size_t t, ta, tc;
+
+ if (ktls == NULL) {
+ *sz = 0;
+ return;
+ }
+ t = *sz;
+ tc = MIN(t, ktls->params.cipher_key_len);
+ if (data != NULL)
+ memcpy(data, ktls->params.cipher_key, tc);
+ ta = MIN(t - tc, ktls->params.auth_key_len);
+ if (data != NULL)
+ memcpy(data + tc, ktls->params.auth_key, ta);
+ *sz = ta + tc;
+}
diff --git a/sys/net/if_var.h b/sys/net/if_var.h
--- a/sys/net/if_var.h
+++ b/sys/net/if_var.h
@@ -297,12 +297,14 @@
typedef int (if_snd_tag_query_t)(struct m_snd_tag *, union if_snd_tag_query_params *);
typedef void (if_snd_tag_free_t)(struct m_snd_tag *);
typedef struct m_snd_tag *(if_next_send_tag_t)(struct m_snd_tag *);
+typedef int (if_snd_tag_status_str_t)(struct m_snd_tag *, char *buf, size_t *sz);
struct if_snd_tag_sw {
if_snd_tag_modify_t *snd_tag_modify;
if_snd_tag_query_t *snd_tag_query;
if_snd_tag_free_t *snd_tag_free;
if_next_send_tag_t *next_snd_tag;
+ if_snd_tag_status_str_t *snd_tag_status_str;
u_int type; /* One of IF_SND_TAG_TYPE_*. */
};
diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h
--- a/sys/netinet/in_pcb.h
+++ b/sys/netinet/in_pcb.h
@@ -303,6 +303,30 @@
char sop_optval[];
};
+#ifdef _SYS_KTLS_H_
+struct xktls_session {
+ uint32_t tsz; /* total sz of elm, next elm is at this+tsz */
+ uint32_t fsz; /* size of the struct up to keys */
+ uint64_t inp_gencnt;
+ kvaddr_t so_pcb;
+ struct in_conninfo coninf;
+ u_short rx_vlan_id;
+ struct xktls_session_onedir rcv;
+ struct xktls_session_onedir snd;
+/*
+ * Next are
+ * - keydata for rcv, first cipher of length rcv.cipher_key_len, then
+ * authentication of length rcv.auth_key_len;
+ * - driver data (string) of length rcv.drv_st_len, if the rcv session is
+ * offloaded to ifnet rcv.ifnet;
+ * - keydata for snd, first cipher of length snd.cipher_key_len, then
+ * authentication of length snd.auth_key_len;
+ * - driver data (string) of length snd.drv_st_len, if the snd session is
+ * offloaded to ifnet snd.ifnet;
+ */
+};
+#endif /* _SYS_KTLS_H_ */
+
#ifdef _KERNEL
int sysctl_setsockopt(SYSCTL_HANDLER_ARGS, struct inpcbinfo *pcbinfo,
int (*ctloutput_set)(struct inpcb *, struct sockopt *));
diff --git a/sys/netinet/in_prot.c b/sys/netinet/in_prot.c
--- a/sys/netinet/in_prot.c
+++ b/sys/netinet/in_prot.c
@@ -26,21 +26,17 @@
*/
/*
- * System calls related to processes and protection
+ * Helpers related to visibility and protection of sockets and inpcb.
*/
-#include <sys/cdefs.h>
-#include "opt_inet.h"
-#include "opt_inet6.h"
-
-#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/jail.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/mutex.h>
+#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/socket.h>
-#include <sys/jail.h>
#include <netinet/in.h>
#include <netinet/in_pcb.h>
@@ -72,3 +68,16 @@
return (0);
}
+
+bool
+cr_canexport_ktlskeys(struct thread *td, struct inpcb *inp)
+{
+ int error;
+
+ if (cr_canseeinpcb(td->td_ucred, inp) == 0 &&
+ cr_xids_subset(td->td_ucred, inp->inp_cred))
+ return (true);
+ error = priv_check(td, PRIV_NETINET_KTLSKEYS);
+ return (error == 0);
+
+}
diff --git a/sys/netinet/in_systm.h b/sys/netinet/in_systm.h
--- a/sys/netinet/in_systm.h
+++ b/sys/netinet/in_systm.h
@@ -58,8 +58,10 @@
#ifdef _KERNEL
struct inpcb;
struct ucred;
+struct thread;
int cr_canseeinpcb(struct ucred *cred, struct inpcb *inp);
+bool cr_canexport_ktlskeys(struct thread *td, struct inpcb *inp);
uint32_t iptime(void);
#endif
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -2664,6 +2664,219 @@
NULL, 0, tcp_pcblist, "S,xtcpcb",
"List of active TCP connections");
+#define SND_TAG_STATUS_MAXLEN 128
+
+#ifdef KERN_TLS
+static int
+tcp_ktlslist(SYSCTL_HANDLER_ARGS, bool export_keys)
+{
+ struct xinpgen xig;
+ struct inpcb *inp;
+ struct socket *so;
+ struct ktls_session *ksr, *kss;
+ char *buf;
+ struct xktls_session *xktls;
+ uint64_t ipi_gencnt;
+ size_t buflen, len, sz;
+ u_int cnt;
+ int error;
+ bool p;
+
+ if (req->newptr != NULL)
+ return (EPERM);
+
+ len = 0;
+ cnt = 0;
+ ipi_gencnt = V_tcbinfo.ipi_gencnt;
+ bzero(&xig, sizeof(xig));
+ xig.xig_len = sizeof(xig);
+ xig.xig_gen = atomic_load_acq_64(&ktls_glob_gen);
+ xig.xig_sogen = so_gencnt;
+
+ struct inpcb_iterator inpi = INP_ALL_ITERATOR(&V_tcbinfo,
+ INPLOOKUP_RLOCKPCB);
+ while ((inp = inp_next(&inpi)) != NULL) {
+ if (inp->inp_gencnt > ipi_gencnt ||
+ cr_canseeinpcb(req->td->td_ucred, inp) != 0)
+ continue;
+
+ so = inp->inp_socket;
+ if (so != NULL && so->so_gencnt <= xig.xig_sogen) {
+ p = false;
+ ksr = so->so_rcv.sb_tls_info;
+ if (ktls_session_genvis(ksr, xig.xig_gen)) {
+ p = true;
+ if (export_keys && cr_canexport_ktlskeys(
+ req->td, inp)) {
+ sz = SIZE_T_MAX;
+ ktls_session_copy_keys(ksr,
+ NULL, &sz);
+ len += sz;
+ }
+ if (ksr->snd_tag != NULL &&
+ ksr->snd_tag->sw->snd_tag_status_str !=
+ NULL) {
+ sz = SND_TAG_STATUS_MAXLEN;
+ ksr->snd_tag->sw->snd_tag_status_str(
+ ksr->snd_tag, NULL, &sz);
+ len += sz;
+ }
+ }
+ kss = so->so_snd.sb_tls_info;
+ if (ktls_session_genvis(kss, xig.xig_gen)) {
+ p = true;
+ if (export_keys && cr_canexport_ktlskeys(
+ req->td, inp)) {
+ sz = SIZE_T_MAX;
+ ktls_session_copy_keys(kss,
+ NULL, &sz);
+ len += sz;
+ }
+ if (kss->snd_tag != NULL &&
+ kss->snd_tag->sw->snd_tag_status_str !=
+ NULL) {
+ sz = SND_TAG_STATUS_MAXLEN;
+ kss->snd_tag->sw->snd_tag_status_str(
+ kss->snd_tag, NULL, &sz);
+ len += sz;
+ }
+ }
+ if (p) {
+ len += sizeof(*xktls);
+ len = roundup2(len, __alignof(struct
+ xktls_session));
+ }
+ }
+ }
+ if (req->oldptr == NULL) {
+ len += 2 * sizeof(xig);
+ len += 3 * len / 4;
+ req->oldidx = len;
+ return (0);
+ }
+
+ if ((error = sysctl_wire_old_buffer(req, 0)) != 0)
+ return (error);
+
+ error = SYSCTL_OUT(req, &xig, sizeof xig);
+ if (error != 0)
+ return (error);
+
+ buflen = roundup2(sizeof(*xktls) + 2 * TLS_MAX_PARAM_SIZE +
+ 2 * SND_TAG_STATUS_MAXLEN, __alignof(struct xktls_session));
+ buf = malloc(buflen, M_TEMP, M_WAITOK | M_ZERO);
+ struct inpcb_iterator inpi1 = INP_ALL_ITERATOR(&V_tcbinfo,
+ INPLOOKUP_RLOCKPCB);
+ while ((inp = inp_next(&inpi1)) != NULL) {
+ if (inp->inp_gencnt > ipi_gencnt ||
+ cr_canseeinpcb(req->td->td_ucred, inp) != 0)
+ continue;
+
+ so = inp->inp_socket;
+ if (so == NULL)
+ continue;
+
+ p = false;
+ ksr = so->so_rcv.sb_tls_info;
+ kss = so->so_snd.sb_tls_info;
+ xktls = (struct xktls_session *)buf;
+ if (ktls_session_genvis(ksr, xig.xig_gen)) {
+ p = true;
+ ktls_session_to_xktls_onedir(ksr, &xktls->rcv);
+ }
+ if (ktls_session_genvis(kss, xig.xig_gen)) {
+ p = true;
+ ktls_session_to_xktls_onedir(kss, &xktls->snd);
+ }
+ if (!p)
+ continue;
+
+ xktls->inp_gencnt = inp->inp_gencnt;
+ xktls->so_pcb = (kvaddr_t)inp;
+ memcpy(&xktls->coninf, &inp->inp_inc, sizeof(xktls->coninf));
+ len = sizeof(*xktls);
+ if (ktls_session_genvis(ksr, xig.xig_gen)) {
+ if (export_keys && cr_canexport_ktlskeys(req->td,
+ inp)) {
+ sz = buflen - len;
+ ktls_session_copy_keys(ksr, buf + len, &sz);
+ len += sz;
+ } else {
+ xktls->rcv.cipher_key_len = 0;
+ xktls->rcv.auth_key_len = 0;
+ }
+ if (ksr->snd_tag != NULL &&
+ ksr->snd_tag->sw->snd_tag_status_str != NULL) {
+ sz = SND_TAG_STATUS_MAXLEN;
+ ksr->snd_tag->sw->snd_tag_status_str(
+ ksr->snd_tag, buf + len, &sz);
+ len += sz;
+ }
+ }
+ if (ktls_session_genvis(kss, xig.xig_gen)) {
+ if (export_keys && cr_canexport_ktlskeys(req->td,
+ inp)) {
+ sz = buflen - len;
+ ktls_session_copy_keys(kss, buf + len, &sz);
+ len += sz;
+ } else {
+ xktls->snd.cipher_key_len = 0;
+ xktls->snd.auth_key_len = 0;
+ }
+ if (kss->snd_tag != NULL &&
+ kss->snd_tag->sw->snd_tag_status_str != NULL) {
+ sz = SND_TAG_STATUS_MAXLEN;
+ kss->snd_tag->sw->snd_tag_status_str(
+ kss->snd_tag, buf + len, &sz);
+ len += sz;
+ }
+ }
+ len = roundup2(len, __alignof(*xktls));
+ xktls->tsz = len;
+ xktls->fsz = sizeof(*xktls);
+
+ error = SYSCTL_OUT(req, xktls, len);
+ if (error != 0) {
+ INP_RUNLOCK(inp);
+ break;
+ }
+ cnt++;
+ }
+
+ if (error == 0) {
+ atomic_thread_fence_rel();
+ xig.xig_gen = atomic_load_64(&ktls_glob_gen);
+ xig.xig_sogen = so_gencnt;
+ xig.xig_count = cnt;
+ error = SYSCTL_OUT(req, &xig, sizeof(xig));
+ }
+
+ free(buf, M_TEMP);
+ return (error);
+}
+
+static int
+tcp_ktlslist_nokeys(SYSCTL_HANDLER_ARGS)
+{
+ return (tcp_ktlslist(oidp, arg1, arg2, req, false));
+}
+
+static int
+tcp_ktlslist_wkeys(SYSCTL_HANDLER_ARGS)
+{
+ return (tcp_ktlslist(oidp, arg1, arg2, req, true));
+}
+
+SYSCTL_PROC(_net_inet_tcp, TCPCTL_KTLSLIST, ktlslist,
+ CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE,
+ NULL, 0, tcp_ktlslist_nokeys, "S,xktls_session",
+ "List of active kTLS sessions for TCP connections");
+SYSCTL_PROC(_net_inet_tcp, TCPCTL_KTLSLIST_WKEYS, ktlslist_wkeys,
+ CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE,
+ NULL, 0, tcp_ktlslist_wkeys, "S,xktls_session",
+ "List of active kTLS sessions for TCP connections with keys");
+#endif /* KERN_TLS */
+
#ifdef INET
static int
tcp_getcred(SYSCTL_HANDLER_ARGS)
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -1234,6 +1234,8 @@
#define TCPCTL_SACK 14 /* Selective Acknowledgement,rfc 2018 */
#define TCPCTL_DROP 15 /* drop tcp connection */
#define TCPCTL_STATES 16 /* connection counts by TCP state */
+#define TCPCTL_KTLSLIST 17
+#define TCPCTL_KTLSLIST_WKEYS 18
#ifdef _KERNEL
#ifdef SYSCTL_DECL
diff --git a/sys/sys/ktls.h b/sys/sys/ktls.h
--- a/sys/sys/ktls.h
+++ b/sys/sys/ktls.h
@@ -145,6 +145,27 @@
uint16_t tls_length;
};
+struct xktls_session_onedir {
+ uint64_t gen;
+ uint64_t rsrv1[8];
+ uint32_t rsrv2[8];
+ uint8_t iv[TLS_CBC_IMPLICIT_IV_LEN];
+ int cipher_algorithm;
+ int auth_algorithm;
+ uint16_t cipher_key_len;
+ uint16_t iv_len;
+ uint16_t auth_key_len;
+ uint16_t max_frame_len;
+ uint8_t tls_vmajor;
+ uint8_t tls_vminor;
+ uint8_t tls_hlen;
+ uint8_t tls_tlen;
+ uint8_t tls_bs;
+ uint8_t flags;
+ uint16_t drv_st_len;
+ char ifnet[16]; /* IFNAMSIZ */
+};
+
#ifdef _KERNEL
struct tls_session_params {
@@ -206,9 +227,12 @@
/* Used to destroy any kTLS session */
struct task destroy_task;
+
+ uint64_t gen;
} __aligned(CACHE_LINE_SIZE);
extern unsigned int ktls_ifnet_max_rexmit_pct;
+extern uint64_t ktls_glob_gen;
typedef enum {
KTLS_MBUF_CRYPTO_ST_MIXED = 0,
@@ -258,5 +282,16 @@
ktls_destroy(tls);
}
+static inline bool
+ktls_session_genvis(const struct ktls_session *ks, uint64_t gen)
+{
+ return (ks != NULL && ks->gen <= gen);
+}
+
+void ktls_session_to_xktls_onedir(const struct ktls_session *ks,
+ struct xktls_session_onedir *xktls_od);
+void ktls_session_copy_keys(const struct ktls_session *ktls,
+ uint8_t *data, size_t *sz);
+
#endif /* !_KERNEL */
#endif /* !_SYS_KTLS_H_ */
diff --git a/sys/sys/priv.h b/sys/sys/priv.h
--- a/sys/sys/priv.h
+++ b/sys/sys/priv.h
@@ -406,6 +406,7 @@
#define PRIV_NETINET_SETHDROPTS 505 /* Set certain IPv4/6 header options. */
#define PRIV_NETINET_BINDANY 506 /* Allow bind to any address. */
#define PRIV_NETINET_HASHKEY 507 /* Get and set hash keys for IPv4/6. */
+#define PRIV_NETINET_KTLSKEYS 508 /* Read ktls session keys. */
/*
* Placeholders for IPX/SPX privileges, not supported any more.
diff --git a/sys/sys/ucred.h b/sys/sys/ucred.h
--- a/sys/sys/ucred.h
+++ b/sys/sys/ucred.h
@@ -237,6 +237,7 @@
void crsetgroups(struct ucred *cr, int ngrp, const gid_t *groups);
void crsetgroups_fallback(struct ucred *cr, int ngrp, const gid_t *groups,
const gid_t fallback);
+bool cr_xids_subset(struct ucred *active_cred, struct ucred *obj_cred);
/*
* Returns whether gid designates a primary group in cred.
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Feb 9, 3:20 PM (11 m, 54 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28593280
Default Alt Text
D50653.id156670.diff (16 KB)
Attached To
Mode
D50653: Add sysctl net.inet.tcp.ktlslist
Attached
Detach File
Event Timeline
Log In to Comment