Check ipfw table numbers in both user and kernel space before rule addition.

Found by:	Saychik Pavel <umka@localka.net>
MFC after:	2 weeks
Sponsored by:	Yandex LLC
This commit is contained in:
Alexander V. Chernikov 2013-11-28 10:28:28 +00:00
parent 34ee1e4d3f
commit 1058f17749
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=258708
3 changed files with 38 additions and 11 deletions

View File

@ -60,6 +60,8 @@ int resvd_set_number = RESVD_SET;
int ipfw_socket = -1;
uint32_t ipfw_tables_max = 0; /* Number of tables supported by kernel */
#ifndef s6_addr32
#define s6_addr32 __u6_addr.__u6_addr32
#endif
@ -2203,6 +2205,7 @@ fill_ip(ipfw_insn_ip *cmd, char *av, int cblen)
{
int len = 0;
uint32_t *d = ((ipfw_insn_u32 *)cmd)->d;
uint32_t tables_max;
cmd->o.len &= ~F_LEN_MASK; /* zero len */
@ -2221,6 +2224,10 @@ fill_ip(ipfw_insn_ip *cmd, char *av, int cblen)
*p++ = '\0';
cmd->o.opcode = O_IP_DST_LOOKUP;
cmd->o.arg1 = strtoul(av + 6, NULL, 0);
tables_max = ipfw_get_tables_max();
if (cmd->o.arg1 > tables_max)
errx(EX_USAGE, "The table number exceeds the maximum "
"allowed value (%u)", tables_max - 1);
if (p) {
cmd->o.len |= F_INSN_SIZE(ipfw_insn_u32);
d[0] = strtoul(p, NULL, 0);
@ -4118,6 +4125,33 @@ ipfw_flush(int force)
static void table_list(uint16_t num, int need_header);
static void table_fill_xentry(char *arg, ipfw_table_xentry *xent);
/*
* Retrieve maximum number of tables supported by ipfw(4) module.
*/
uint32_t
ipfw_get_tables_max()
{
size_t len;
uint32_t tables_max;
if (ipfw_tables_max != 0)
return (ipfw_tables_max);
len = sizeof(tables_max);
if (sysctlbyname("net.inet.ip.fw.tables_max", &tables_max, &len,
NULL, 0) == -1) {
if (co.test_only)
tables_max = 128; /* Old conservative default */
else
errx(1, "Can't determine maximum number of ipfw tables."
" Perhaps you forgot to load ipfw module?");
}
ipfw_tables_max = tables_max;
return (ipfw_tables_max);
}
/*
* This one handles all table-related commands
* ipfw table N add addr[/masklen] [value]
@ -4131,19 +4165,10 @@ ipfw_table_handler(int ac, char *av[])
ipfw_table_xentry xent;
int do_add;
int is_all;
size_t len;
uint32_t a;
uint32_t tables_max;
len = sizeof(tables_max);
if (sysctlbyname("net.inet.ip.fw.tables_max", &tables_max, &len,
NULL, 0) == -1) {
if (co.test_only)
tables_max = 128; /* Old conservative default */
else
errx(1, "Can't determine maximum number of ipfw tables."
" Perhaps you forgot to load ipfw module?");
}
tables_max = ipfw_get_tables_max();
memset(&xent, 0, sizeof(xent));

View File

@ -228,6 +228,8 @@ char const *match_value(struct _s_x *p, int value);
int do_cmd(int optname, void *optval, uintptr_t optlen);
uint32_t ipfw_get_tables_max(void);
struct in6_addr;
void n2mask(struct in6_addr *mask, int n);
int contigmask(uint8_t *p, int len);

View File

@ -653,7 +653,7 @@ check_ipfw_struct(struct ip_fw *rule, int size)
case O_IP_SRC_LOOKUP:
case O_IP_DST_LOOKUP:
if (cmd->arg1 >= IPFW_TABLES_MAX) {
if (cmd->arg1 >= V_fw_tables_max) {
printf("ipfw: invalid table number %d\n",
cmd->arg1);
return (EINVAL);