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)
This commit is contained in:
csjp 2004-08-12 22:06:55 +00:00
parent 00b723c98e
commit 6661aed38d
4 changed files with 40 additions and 2 deletions

View File

@ -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 .

View File

@ -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;

View File

@ -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! */
};

View File

@ -50,6 +50,7 @@
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
#include <sys/jail.h>
#include <sys/module.h>
#include <sys/proc.h>
#include <sys/socket.h>
@ -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: