From 4d4d2d367d9471f9de363f0ca2ed82871e0030d0 Mon Sep 17 00:00:00 2001 From: bz Date: Fri, 17 Oct 2008 16:26:16 +0000 Subject: [PATCH] Add cr_canseeinpcb() doing checks using the cached socket credentials from inp_cred which is also available after the socket is gone. Switch cr_canseesocket consumers to cr_canseeinpcb. This removes an extra acquisition of the socket lock. Reviewed by: rwatson MFC after: 3 months (set timer; decide then) --- sys/kern/kern_prot.c | 35 +++++++++++++++++++++++++++++++++++ sys/netinet/ip_divert.c | 2 +- sys/netinet/raw_ip.c | 2 +- sys/netinet/tcp_subr.c | 9 +++------ sys/netinet/udp_usrreq.c | 5 ++--- sys/sys/systm.h | 2 ++ 6 files changed, 44 insertions(+), 11 deletions(-) diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c index cd0fb170a20f..bbd4fd5bf243 100644 --- a/sys/kern/kern_prot.c +++ b/sys/kern/kern_prot.c @@ -45,6 +45,8 @@ __FBSDID("$FreeBSD$"); #include "opt_compat.h" +#include "opt_inet.h" +#include "opt_inet6.h" #include "opt_mac.h" #include @@ -68,6 +70,11 @@ __FBSDID("$FreeBSD$"); #include #include +#if defined(INET) || defined(INET6) +#include +#include +#endif + #include #include @@ -1704,6 +1711,34 @@ cr_canseesocket(struct ucred *cred, struct socket *so) return (0); } +#if defined(INET) || defined(INET6) +/*- + * Determine whether the subject represented by cred can "see" a socket. + * Returns: 0 for permitted, ENOENT otherwise. + */ +int +cr_canseeinpcb(struct ucred *cred, struct inpcb *inp) +{ + int error; + + error = prison_check(cred, inp->inp_cred); + if (error) + return (ENOENT); +#ifdef MAC + INP_LOCK_ASSERT(inp); + error = mac_inpcb_check_visible(cred, inp); + if (error) + return (error); +#endif + if (cr_seeotheruids(cred, inp->inp_cred)) + return (ENOENT); + if (cr_seeothergids(cred, inp->inp_cred)) + return (ENOENT); + + return (0); +} +#endif + /*- * Determine whether td can wait for the exit of p. * Returns: 0 for permitted, an errno value otherwise diff --git a/sys/netinet/ip_divert.c b/sys/netinet/ip_divert.c index aea0d613e596..bac453437824 100644 --- a/sys/netinet/ip_divert.c +++ b/sys/netinet/ip_divert.c @@ -627,7 +627,7 @@ div_pcblist(SYSCTL_HANDLER_ARGS) inp = LIST_NEXT(inp, inp_list)) { INP_RLOCK(inp); if (inp->inp_gencnt <= gencnt && - cr_canseesocket(req->td->td_ucred, inp->inp_socket) == 0) + cr_canseeinpcb(req->td->td_ucred, inp) == 0) inp_list[i++] = inp; INP_RUNLOCK(inp); } diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c index 19c744eca72c..8eca00a8704c 100644 --- a/sys/netinet/raw_ip.c +++ b/sys/netinet/raw_ip.c @@ -942,7 +942,7 @@ rip_pcblist(SYSCTL_HANDLER_ARGS) inp = LIST_NEXT(inp, inp_list)) { INP_RLOCK(inp); if (inp->inp_gencnt <= gencnt && - cr_canseesocket(req->td->td_ucred, inp->inp_socket) == 0) { + cr_canseeinpcb(req->td->td_ucred, inp) == 0) { /* XXX held references? */ inp_list[i++] = inp; } diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index be9daae9db2c..91560f1b0806 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -1015,8 +1015,7 @@ tcp_pcblist(SYSCTL_HANDLER_ARGS) else error = EINVAL; /* Skip this inp. */ } else - error = cr_canseesocket(req->td->td_ucred, - inp->inp_socket); + error = cr_canseeinpcb(req->td->td_ucred, inp); if (error == 0) inp_list[i++] = inp; } @@ -1104,8 +1103,7 @@ tcp_getcred(SYSCTL_HANDLER_ARGS) if (inp->inp_socket == NULL) error = ENOENT; if (error == 0) - error = cr_canseesocket(req->td->td_ucred, - inp->inp_socket); + error = cr_canseeinpcb(req->td->td_ucred, inp); if (error == 0) cru2x(inp->inp_cred, &xuc); INP_RUNLOCK(inp); @@ -1168,8 +1166,7 @@ tcp6_getcred(SYSCTL_HANDLER_ARGS) if (inp->inp_socket == NULL) error = ENOENT; if (error == 0) - error = cr_canseesocket(req->td->td_ucred, - inp->inp_socket); + error = cr_canseeinpcb(req->td->td_ucred, inp); if (error == 0) cru2x(inp->inp_cred, &xuc); INP_RUNLOCK(inp); diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c index b5b9c553c281..cbfdb6bbe6a5 100644 --- a/sys/netinet/udp_usrreq.c +++ b/sys/netinet/udp_usrreq.c @@ -688,7 +688,7 @@ udp_pcblist(SYSCTL_HANDLER_ARGS) inp = LIST_NEXT(inp, inp_list)) { INP_RLOCK(inp); if (inp->inp_gencnt <= gencnt && - cr_canseesocket(req->td->td_ucred, inp->inp_socket) == 0) + cr_canseeinpcb(req->td->td_ucred, inp) == 0) inp_list[i++] = inp; INP_RUNLOCK(inp); } @@ -758,8 +758,7 @@ udp_getcred(SYSCTL_HANDLER_ARGS) if (inp->inp_socket == NULL) error = ENOENT; if (error == 0) - error = cr_canseesocket(req->td->td_ucred, - inp->inp_socket); + error = cr_canseeinpcb(req->td->td_ucred, inp); if (error == 0) cru2x(inp->inp_cred, &xuc); INP_RUNLOCK(inp); diff --git a/sys/sys/systm.h b/sys/sys/systm.h index f780311c1064..eb60a341cbf7 100644 --- a/sys/sys/systm.h +++ b/sys/sys/systm.h @@ -112,6 +112,7 @@ extern char **kenvp; * General function declarations. */ +struct inpcb; struct lock_object; struct malloc_type; struct mtx; @@ -227,6 +228,7 @@ void cpu_stopprofclock(void); int cr_cansee(struct ucred *u1, struct ucred *u2); int cr_canseesocket(struct ucred *cred, struct socket *so); +int cr_canseeinpcb(struct ucred *cred, struct inpcb *inp); char *getenv(const char *name); void freeenv(char *env);