From 31c88a3043053e6caa5cd4d9f686be6e10db1630 Mon Sep 17 00:00:00 2001 From: "Christian S.J. Peron" Date: Thu, 12 Aug 2004 22:06:55 +0000 Subject: [PATCH] Add the ability to associate ipfw rules with a specific prison ID. Since the only thing truly unique about a prison is it's ID, I figured this would be the most granular way of handling this. This commit makes the following changes: - Adds tokenizing and parsing for the ``jail'' command line option to the ipfw(8) userspace utility. - Append the ipfw opcode list with O_JAIL. - While Iam here, add a comment informing others that if they want to add additional opcodes, they should append them to the end of the list to avoid ABI breakage. - Add ``fw_prid'' to the ipfw ucred cache structure. - When initializing ucred cache, if the process is jailed, set fw_prid to the prison ID, otherwise set it to -1. - Update man page to reflect these changes. This change was a strong motivator behind the ucred caching mechanism in ipfw. A sample usage of this new functionality could be: ipfw add count ip from any to any jail 2 It should be noted that because ucred based constraints are only implemented for TCP and UDP packets, the same applies for jail associations. Conceptual head nod by: pjd Reviewed by: rwatson Approved by: bmilekic (mentor) --- sbin/ipfw/ipfw.8 | 4 ++++ sbin/ipfw/ipfw2.c | 22 ++++++++++++++++++++++ sys/netinet/ip_fw.h | 6 +++++- sys/netinet/ip_fw2.c | 10 +++++++++- 4 files changed, 40 insertions(+), 2 deletions(-) diff --git a/sbin/ipfw/ipfw.8 b/sbin/ipfw/ipfw.8 index e01ac72b1bfc..eb9e92b17cac 100644 --- a/sbin/ipfw/ipfw.8 +++ b/sbin/ipfw/ipfw.8 @@ -929,6 +929,10 @@ Matches all TCP or UDP packets sent by or received for a A .Ar group may be specified by name or number. +.It Cm jail Ar prisonID +Matches all TCP or UDP packets sent by or received for the +jail whos prison ID is +.Ar prisoniD . .It Cm icmptypes Ar types Matches ICMP packets whose ICMP type is in the list .Ar types . diff --git a/sbin/ipfw/ipfw2.c b/sbin/ipfw/ipfw2.c index 1030e39aaec7..bac35529c2a8 100644 --- a/sbin/ipfw/ipfw2.c +++ b/sbin/ipfw/ipfw2.c @@ -204,6 +204,7 @@ enum tokens { TOK_UID, TOK_GID, + TOK_JAIL, TOK_IN, TOK_LIMIT, TOK_KEEPSTATE, @@ -304,6 +305,7 @@ struct _s_x rule_actions[] = { struct _s_x rule_options[] = { { "uid", TOK_UID }, { "gid", TOK_GID }, + { "jail", TOK_JAIL }, { "in", TOK_IN }, { "limit", TOK_LIMIT }, { "keep-state", TOK_KEEPSTATE }, @@ -1284,6 +1286,10 @@ show_ipfw(struct ip_fw *rule, int pcwidth, int bcwidth) } break; + case O_JAIL: + printf(" jail %d", cmd32->d[0]); + break; + case O_VERREVPATH: printf(" verrevpath"); break; @@ -3298,6 +3304,22 @@ add(int ac, char *av[]) } break; + case TOK_JAIL: + NEED1("jail requires argument"); + { + char *end; + int jid; + + cmd->opcode = O_JAIL; + jid = (int)strtol(*av, &end, 0); + if (jid < 0 || *end != '\0') + errx(EX_DATAERR, "jail requires prison ID"); + cmd32->d[0] = (unsigned int)jid; + cmd->len = F_INSN_SIZE(ipfw_insn_u32); + ac--; av++; + } + break; + case TOK_ESTAB: fill_cmd(cmd, O_ESTAB, 0, 0); break; diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h index 62e743d7da49..32d9e4c5e23b 100644 --- a/sys/netinet/ip_fw.h +++ b/sys/netinet/ip_fw.h @@ -44,7 +44,10 @@ * 64-bit architectures, so the must be handled with care. * * "enum ipfw_opcodes" are the opcodes supported. We can have up - * to 256 different opcodes. + * to 256 different opcodes. When adding new opcodes, they should + * be appended to the end of the opcode list before O_LAST_OPCODE, + * this will prevent the ABI from being broken, otherwise users + * will have to recompile ipfw(8) when they update the kernel. */ enum ipfw_opcodes { /* arguments (4 byte each) */ @@ -129,6 +132,7 @@ enum ipfw_opcodes { /* arguments (4 byte each) */ O_IPSEC, /* has ipsec history */ O_IP_SRC_LOOKUP, /* arg1=table number, u32=value */ O_IP_DST_LOOKUP, /* arg1=table number, u32=value */ + O_JAIL, /* u32 = id */ O_LAST_OPCODE /* not an opcode! */ }; diff --git a/sys/netinet/ip_fw2.c b/sys/netinet/ip_fw2.c index 7333f685b3a8..7559db7a5e1d 100644 --- a/sys/netinet/ip_fw2.c +++ b/sys/netinet/ip_fw2.c @@ -50,6 +50,7 @@ #include #include #include +#include #include #include #include @@ -111,6 +112,7 @@ struct ip_fw_ugid { gid_t fw_groups[NGROUPS]; int fw_ngroups; uid_t fw_uid; + int fw_prid; }; struct ip_fw_chain { @@ -1579,6 +1581,8 @@ check_uidgid(ipfw_insn_u32 *insn, INP_LOCK(pcb); if (pcb->inp_socket != NULL) { cr = pcb->inp_socket->so_cred; + ugp->fw_prid = jailed(cr) ? + cr->cr_prison->pr_id : -1; ugp->fw_uid = cr->cr_uid; ugp->fw_ngroups = cr->cr_ngroups; bcopy(cr->cr_groups, ugp->fw_groups, @@ -1601,13 +1605,15 @@ check_uidgid(ipfw_insn_u32 *insn, } if (insn->o.opcode == O_UID) match = (ugp->fw_uid == (uid_t)insn->d[0]); - else if (insn->o.opcode == O_GID) + 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]); return match; } @@ -1921,6 +1927,7 @@ ipfw_chk(struct ip_fw_args *args) case O_GID: case O_UID: + case O_JAIL: /* * We only check offset == 0 && proto != 0, * as this ensures that we have an IPv4 @@ -2862,6 +2869,7 @@ check_ipfw_struct(struct ip_fw *rule, int size) case O_UID: case O_GID: + case O_JAIL: case O_IP_SRC: case O_IP_DST: case O_TCPSEQ: