Author: bz
Date: Fri Oct 17 16:26:16 2008
New Revision: 183982
URL: http://svn.freebsd.org/changeset/base/183982

Log:
  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)

Modified:
  head/sys/kern/kern_prot.c
  head/sys/netinet/ip_divert.c
  head/sys/netinet/raw_ip.c
  head/sys/netinet/tcp_subr.c
  head/sys/netinet/udp_usrreq.c
  head/sys/sys/systm.h

Modified: head/sys/kern/kern_prot.c
==============================================================================
--- head/sys/kern/kern_prot.c   Fri Oct 17 16:03:37 2008        (r183981)
+++ head/sys/kern/kern_prot.c   Fri Oct 17 16:26:16 2008        (r183982)
@@ -45,6 +45,8 @@
 __FBSDID("$FreeBSD$");
 
 #include "opt_compat.h"
+#include "opt_inet.h"
+#include "opt_inet6.h"
 #include "opt_mac.h"
 
 #include <sys/param.h>
@@ -68,6 +70,11 @@ __FBSDID("$FreeBSD$");
 #include <sys/syscallsubr.h>
 #include <sys/sysctl.h>
 
+#if defined(INET) || defined(INET6)
+#include <netinet/in.h>
+#include <netinet/in_pcb.h>
+#endif
+
 #include <security/audit/audit.h>
 #include <security/mac/mac_framework.h>
 
@@ -1704,6 +1711,34 @@ cr_canseesocket(struct ucred *cred, stru
        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

Modified: head/sys/netinet/ip_divert.c
==============================================================================
--- head/sys/netinet/ip_divert.c        Fri Oct 17 16:03:37 2008        
(r183981)
+++ head/sys/netinet/ip_divert.c        Fri Oct 17 16:26:16 2008        
(r183982)
@@ -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);
        }

Modified: head/sys/netinet/raw_ip.c
==============================================================================
--- head/sys/netinet/raw_ip.c   Fri Oct 17 16:03:37 2008        (r183981)
+++ head/sys/netinet/raw_ip.c   Fri Oct 17 16:26:16 2008        (r183982)
@@ -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;
                }

Modified: head/sys/netinet/tcp_subr.c
==============================================================================
--- head/sys/netinet/tcp_subr.c Fri Oct 17 16:03:37 2008        (r183981)
+++ head/sys/netinet/tcp_subr.c Fri Oct 17 16:26:16 2008        (r183982)
@@ -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);

Modified: head/sys/netinet/udp_usrreq.c
==============================================================================
--- head/sys/netinet/udp_usrreq.c       Fri Oct 17 16:03:37 2008        
(r183981)
+++ head/sys/netinet/udp_usrreq.c       Fri Oct 17 16:26:16 2008        
(r183982)
@@ -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);

Modified: head/sys/sys/systm.h
==============================================================================
--- head/sys/sys/systm.h        Fri Oct 17 16:03:37 2008        (r183981)
+++ head/sys/sys/systm.h        Fri Oct 17 16:26:16 2008        (r183982)
@@ -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);
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[EMAIL PROTECTED]"

Reply via email to