svn commit: r194309 - projects/ngroups/sys/netinet/ipfw

Brooks Davis brooks at FreeBSD.org
Tue Jun 16 22:39:58 UTC 2009


Author: brooks
Date: Tue Jun 16 22:39:57 2009
New Revision: 194309
URL: http://svn.freebsd.org/changeset/base/194309

Log:
  Instead of caching an incomplete copy of the interesting bits of struct
  ucred, just grab a reference and cache a pointer to the real deal.

Modified:
  projects/ngroups/sys/netinet/ipfw/ip_fw2.c

Modified: projects/ngroups/sys/netinet/ipfw/ip_fw2.c
==============================================================================
--- projects/ngroups/sys/netinet/ipfw/ip_fw2.c	Tue Jun 16 22:35:16 2009	(r194308)
+++ projects/ngroups/sys/netinet/ipfw/ip_fw2.c	Tue Jun 16 22:39:57 2009	(r194309)
@@ -135,20 +135,6 @@ static uma_zone_t ipfw_dyn_rule_zone;
 struct ip_fw *ip_fw_default_rule;
 
 /*
- * Data structure to cache our ucred related
- * information. This structure only gets used if
- * the user specified UID/GID based constraints in
- * a firewall rule.
- */
-#define	FW_NGROUPS	16
-struct ip_fw_ugid {
-	gid_t		fw_groups[FW_NGROUPS];	/* XXX: should be dynamic */
-	int		fw_ngroups;
-	uid_t		fw_uid;
-	int		fw_prid;
-};
-
-/*
  * list of rules for layer 3
  */
 #ifdef VIMAGE_GLOBALS
@@ -2010,22 +1996,10 @@ dump_table(struct ip_fw_chain *ch, ipfw_
 	return (0);
 }
 
-static void
-fill_ugid_cache(struct inpcb *inp, struct ip_fw_ugid *ugp)
-{
-	struct ucred *cr;
-
-	cr = inp->inp_cred;
-	ugp->fw_prid = jailed(cr) ? cr->cr_prison->pr_id : -1;
-	ugp->fw_uid = cr->cr_uid;
-	ugp->fw_ngroups = MIN(cr->cr_ngroups, FW_NGROUPS);
-	bcopy(cr->cr_groups, ugp->fw_groups, sizeof(gid_t) * ugp->fw_ngroups);
-}
-
 static int
 check_uidgid(ipfw_insn_u32 *insn, int proto, struct ifnet *oif,
     struct in_addr dst_ip, u_int16_t dst_port, struct in_addr src_ip,
-    u_int16_t src_port, struct ip_fw_ugid *ugp, int *ugid_lookupp,
+    u_int16_t src_port, struct ucred **uc, int *ugid_lookupp,
     struct inpcb *inp)
 {
 	INIT_VNET_INET(curvnet);
@@ -2033,7 +2007,6 @@ check_uidgid(ipfw_insn_u32 *insn, int pr
 	int wildcard;
 	struct inpcb *pcb;
 	int match;
-	gid_t *gp;
 
 	/*
 	 * Check to see if the UDP or TCP stack supplied us with
@@ -2043,7 +2016,7 @@ check_uidgid(ipfw_insn_u32 *insn, int pr
 	if (inp && *ugid_lookupp == 0) {
 		INP_LOCK_ASSERT(inp);
 		if (inp->inp_socket != NULL) {
-			fill_ugid_cache(inp, ugp);
+			*uc=crhold(inp->inp_cred);
 			*ugid_lookupp = 1;
 		} else
 			*ugid_lookupp = -1;
@@ -2076,7 +2049,7 @@ check_uidgid(ipfw_insn_u32 *insn, int pr
 				dst_ip, htons(dst_port),
 				wildcard, NULL);
 		if (pcb != NULL) {
-			fill_ugid_cache(pcb, ugp);
+			*uc=crhold(inp->inp_cred);
 			*ugid_lookupp = 1;
 		}
 		INP_INFO_RUNLOCK(pi);
@@ -2092,16 +2065,11 @@ check_uidgid(ipfw_insn_u32 *insn, int pr
 		}
 	} 
 	if (insn->o.opcode == O_UID)
-		match = (ugp->fw_uid == (uid_t)insn->d[0]);
-	else if (insn->o.opcode == O_GID) {
-		for (gp = ugp->fw_groups;
-			gp < &ugp->fw_groups[ugp->fw_ngroups]; gp++)
-			if (*gp == (gid_t)insn->d[0]) {
-				match = 1;
-				break;
-			}
-	} else if (insn->o.opcode == O_JAIL)
-		match = (ugp->fw_prid == (int)insn->d[0]);
+		match = ((*uc)->cr_uid == (uid_t)insn->d[0]);
+	else if (insn->o.opcode == O_GID)
+		match = groupmember((gid_t)insn->d[0], *uc);
+	else if (insn->o.opcode == O_JAIL)
+		match = ((*uc)->cr_prison->pr_id == (int)insn->d[0]);
 	return match;
 }
 
@@ -2179,8 +2147,8 @@ ipfw_chk(struct ip_fw_args *args)
 	 * these types of constraints, as well as decrease contention
 	 * on pcb related locks.
 	 */
-	struct ip_fw_ugid fw_ugid_cache;
-	int ugid_lookup = 0;
+	struct ucred *ucred_cache = NULL;
+	int ucred_lookup = 0;
 
 	/*
 	 * divinput_flags	If non-zero, set to the IP_FW_DIVERT_*_FLAG
@@ -2642,8 +2610,8 @@ check_body:
 						    (ipfw_insn_u32 *)cmd,
 						    proto, oif,
 						    dst_ip, dst_port,
-						    src_ip, src_port, &fw_ugid_cache,
-						    &ugid_lookup, args->inp);
+						    src_ip, src_port, &ucred_cache,
+						    &ucred_lookup, args->inp);
 				break;
 
 			case O_RECV:
@@ -3271,6 +3239,8 @@ check_body:
 					/* XXX statistic */
 					/* drop packet */
 					IPFW_RUNLOCK(chain);
+					if (ucred_cache != NULL)
+						crfree(ucred_cache);
 					return (IP_FW_DENY);
 				}
 				dt = (struct divert_tag *)(mtag+1);
@@ -3476,6 +3446,8 @@ next_rule:;		/* try next rule		*/
 	}		/* end of outer for, scan rules */
 	printf("ipfw: ouch!, skip past end of rules, denying packet\n");
 	IPFW_RUNLOCK(chain);
+	if (ucred_cache != NULL)
+		crfree(ucred_cache);
 	return (IP_FW_DENY);
 
 done:
@@ -3484,6 +3456,8 @@ done:
 	f->bcnt += pktlen;
 	f->timestamp = time_uptime;
 	IPFW_RUNLOCK(chain);
+	if (ucred_cache != NULL)
+		crfree(ucred_cache);
 	return (retval);
 
 pullup_failed:


More information about the svn-src-projects mailing list