Index: src/sbin/ipfw/ipfw2.c =================================================================== RCS file: /home/ncvs/src/sbin/ipfw/ipfw2.c,v retrieving revision 1.4.2.12 diff -u -r1.4.2.12 ipfw2.c --- src/sbin/ipfw/ipfw2.c 14 Apr 2003 12:41:37 -0000 1.4.2.12 +++ src/sbin/ipfw/ipfw2.c 16 May 2003 13:40:25 -0000 @@ -2481,6 +2481,14 @@ return NULL; } +static void +check_length(ipfw_insn *cmd, size_t add, void *ptr, size_t size) +{ + + if ((uintptr_t)(cmd + add) > (uintptr_t)((char *)ptr + size)) + errx(EX_DATAERR, "Rule too long!"); +} + /* * Parse arguments and assemble the microinstructions which make up a rule. * Rules are added into the 'rulebuf' and then copied in the correct order @@ -2562,6 +2570,7 @@ NEED1("missing action"); i = match_token(rule_actions, *av); ac--; av++; + check_length(action, 1, actbuf, sizeof(actbuf)); /* superfluous.. */ action->len = 1; /* default */ switch(i) { case TOK_CHECKSTATE: @@ -2602,6 +2611,7 @@ case TOK_QUEUE: case TOK_PIPE: action->len = F_INSN_SIZE(ipfw_insn_pipe); + check_length(action, action->len, actbuf, sizeof(actbuf)); case TOK_SKIPTO: if (i == TOK_QUEUE) action->opcode = O_QUEUE; @@ -2639,6 +2649,7 @@ action->opcode = O_FORWARD_IP; action->len = F_INSN_SIZE(ipfw_insn_sa); + check_length(action, action->len, actbuf, sizeof(actbuf)); p->sa.sin_len = sizeof(struct sockaddr_in); p->sa.sin_family = AF_INET; @@ -2665,6 +2676,7 @@ default: errx(EX_DATAERR, "invalid action %s\n", av[-1]); } + check_length(action, F_LEN(action), actbuf, sizeof(actbuf)); action = next_cmd(action); /* @@ -2687,6 +2699,7 @@ errx(EX_DATAERR, "logamount must be positive"); ac--; av++; } + check_length(cmd, F_LEN(cmd), cmdbuf, sizeof(cmdbuf)); cmd = next_cmd(cmd); } @@ -2751,12 +2764,16 @@ !strncmp(*av, "mac", strlen(*av))) { ac--; av++; /* the "MAC" keyword */ add_mac(cmd, ac, av); /* exits in case of errors */ + check_length(cmd, F_LEN(cmd), cmdbuf, sizeof(cmdbuf)); cmd = next_cmd(cmd); ac -= 2; av += 2; /* dst-mac and src-mac */ NOT_BLOCK; NEED1("missing mac type"); if (add_mactype(cmd, ac, av[0])) + { + check_length(cmd, F_LEN(cmd), cmdbuf, sizeof(cmdbuf)); cmd = next_cmd(cmd); + } ac--; av++; /* any or mac-type */ goto read_options; } @@ -2775,6 +2792,7 @@ else { proto = cmd->arg1; prev = cmd; + check_length(cmd, F_LEN(cmd), cmdbuf, sizeof(cmdbuf)); cmd = next_cmd(cmd); } } else if (first_cmd != cmd) { @@ -2800,6 +2818,7 @@ ac--; av++; if (F_LEN(cmd) != 0) { /* ! any */ prev = cmd; + check_length(cmd, F_LEN(cmd), cmdbuf, sizeof(cmdbuf)); cmd = next_cmd(cmd); } } @@ -2814,7 +2833,10 @@ add_ports(cmd, *av, proto, O_IP_SRCPORT)) { ac--; av++; if (F_LEN(cmd) != 0) + { + check_length(cmd, F_LEN(cmd), cmdbuf, sizeof(cmdbuf)); cmd = next_cmd(cmd); + } } } @@ -2835,6 +2857,7 @@ ac--; av++; if (F_LEN(cmd) != 0) { /* ! any */ prev = cmd; + check_length(cmd, F_LEN(cmd), cmdbuf, sizeof(cmdbuf)); cmd = next_cmd(cmd); } } @@ -2849,7 +2872,10 @@ add_ports(cmd, *av, proto, O_IP_DSTPORT)) { ac--; av++; if (F_LEN(cmd) != 0) + { + check_length(cmd, F_LEN(cmd), cmdbuf, sizeof(cmdbuf)); cmd = next_cmd(cmd); + } } } @@ -3167,6 +3193,7 @@ } if (F_LEN(cmd) > 0) { /* prepare to advance */ prev = cmd; + check_length(cmd, F_LEN(cmd), cmdbuf, sizeof(cmdbuf)); cmd = next_cmd(cmd); } } @@ -3187,6 +3214,7 @@ if (match_prob != 1) { /* 1 means always match */ dst->opcode = O_PROB; dst->len = 2; + check_length(dst, 2, rulebuf, sizeof(rulebuf)); *((int32_t *)(dst+1)) = (int32_t)(match_prob * 0x7fffffff); dst += dst->len; } @@ -3196,6 +3224,7 @@ */ if (have_state && have_state->opcode != O_CHECK_STATE) { fill_cmd(dst, O_PROBE_STATE, 0, 0); + check_length(dst, F_LEN(dst), rulebuf, sizeof(rulebuf)); dst = next_cmd(dst); } /* @@ -3210,6 +3239,7 @@ case O_LIMIT: break; default: + check_length(dst, i, rulebuf, sizeof(rulebuf)); bcopy(src, dst, i * sizeof(u_int32_t)); dst += i; } @@ -3220,6 +3250,7 @@ */ if (have_state && have_state->opcode != O_CHECK_STATE) { i = F_LEN(have_state); + check_length(dst, i, rulebuf, sizeof(rulebuf)); bcopy(have_state, dst, i * sizeof(u_int32_t)); dst += i; } @@ -3234,6 +3265,7 @@ src = (ipfw_insn *)cmdbuf; if ( src->opcode == O_LOG ) { i = F_LEN(src); + check_length(dst, i, rulebuf, sizeof(rulebuf)); bcopy(src, dst, i * sizeof(u_int32_t)); dst += i; } @@ -3242,6 +3274,7 @@ */ for (src = (ipfw_insn *)actbuf; src != action; src += i) { i = F_LEN(src); + check_length(dst, i, rulebuf, sizeof(rulebuf)); bcopy(src, dst, i * sizeof(u_int32_t)); dst += i; }