Ignore:
Timestamp:
Apr 19, 2010, 10:51:58 PM (12 years ago)
Author:
Sam Hocevar
Message:

New operating mode "copy". It uses temporary files instead of preloading
libzzuf into the process.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • zzuf/trunk/src/zzuf.c

    r4308 r4393  
    154154#endif
    155155#define OPTSTR "+" OPTSTR_REGEX OPTSTR_RLIMIT_MEM OPTSTR_RLIMIT_CPU \
    156                 "a:Ab:B:C:dD:e:f:F:ij:l:mnp:P:qr:R:s:St:U:vxhV"
     156                "a:Ab:B:C:dD:e:f:F:ij:l:mnO:p:P:qr:R:s:St:U:vxhV"
    157157#define MOREINFO "Try `%s --help' for more information.\n"
    158158        int option_index = 0;
     
    183183            { "max-memory",   1, NULL, 'M' },
    184184            { "network",      0, NULL, 'n' },
     185            { "opmode",       1, NULL, 'O' },
    185186            { "ports",        1, NULL, 'p' },
    186187            { "protect",      1, NULL, 'P' },
     
    257258        case 'F':
    258259            fprintf(stderr, "%s: `-F' is deprecated, use `-j'\n", argv[0]);
     260            _zz_opts_fini(opts);
    259261            return EXIT_FAILURE;
    260262        case 'i': /* --stdin */
     
    294296            setenv("ZZUF_NETWORK", "1", 1);
    295297            network = 1;
     298            break;
     299        case 'O': /* --opmode */
     300            if(myoptarg[0] == '=')
     301                myoptarg++;
     302            if (!strcmp(myoptarg, "preload"))
     303                opts->opmode = OPMODE_PRELOAD;
     304            else if (!strcmp(myoptarg, "copy"))
     305                opts->opmode = OPMODE_COPY;
     306            else
     307            {
     308                fprintf(stderr, "%s: invalid operating mode -- `%s'\n",
     309                        argv[0], myoptarg);
     310                _zz_opts_fini(opts);
     311                return EXIT_FAILURE;
     312            }
    296313            break;
    297314        case 'p': /* --ports */
     
    386403    _zz_setseed(opts->seed);
    387404
    388     /* If asked to read from the standard input */
    389     if(myoptind >= argc)
    390     {
    391         if(opts->verbose)
    392         {
    393             finfo(stderr, opts, opts->seed);
    394             fprintf(stderr, "reading from stdin\n");
    395         }
    396 
    397         if(opts->endseed != opts->seed + 1)
    398         {
    399             fprintf(stderr, "%s: seed ranges are incompatible with "
    400                             "stdin fuzzing\n", argv[0]);
    401             printf(MOREINFO, argv[0]);
    402             _zz_opts_fini(opts);
    403             return EXIT_FAILURE;
    404         }
    405 
    406         loop_stdin(opts);
    407 
    408         _zz_opts_fini(opts);
    409         return EXIT_SUCCESS;
    410     }
    411 
    412     /* If asked to launch programs */
    413 #if defined HAVE_REGEX_H
    414     if(cmdline)
    415     {
    416         int dashdash = 0;
    417 
    418         for(i = myoptind + 1; i < argc; i++)
    419         {
    420             if(dashdash)
    421                 include = merge_file(include, argv[i]);
    422             else if(!strcmp("--", argv[i]))
    423                 dashdash = 1;
    424             else if(argv[i][0] != '-')
    425                 include = merge_file(include, argv[i]);
    426         }
    427     }
    428 
    429     if(include)
    430         setenv("ZZUF_INCLUDE", include, 1);
    431     if(exclude)
    432         setenv("ZZUF_EXCLUDE", exclude, 1);
    433 #endif
    434 
    435     setenv("ZZUF_DEBUG", debug ? debug > 1 ? "2" : "1" : "0", 1);
    436     setenv("ZZUF_DEBUGFD", DEBUG_FILENO_STR, 1);
    437 
    438     if(opts->fuzzing)
    439         setenv("ZZUF_FUZZING", opts->fuzzing, 1);
    440     if(opts->bytes)
    441         setenv("ZZUF_BYTES", opts->bytes, 1);
    442     if(opts->list)
    443         setenv("ZZUF_LIST", opts->list, 1);
    444     if(opts->ports)
    445         setenv("ZZUF_PORTS", opts->ports, 1);
    446     if(opts->allow && opts->allow[0] == '!')
    447         setenv("ZZUF_DENY", opts->allow, 1);
    448     else if(opts->allow)
    449         setenv("ZZUF_ALLOW", opts->allow, 1);
    450     if(opts->protect)
    451         setenv("ZZUF_PROTECT", opts->protect, 1);
    452     if(opts->refuse)
    453         setenv("ZZUF_REFUSE", opts->refuse, 1);
    454 #if defined HAVE_SETRLIMIT && defined ZZUF_RLIMIT_MEM
    455     if(opts->maxmem >= 0)
    456     {
    457         char buf[32];
    458         snprintf(buf, 32, "%i", opts->maxmem);
    459         setenv("ZZUF_MEMORY", buf, 1);
    460     }
    461 #endif
    462 
    463     /* Allocate memory for children handling */
    464     opts->child = malloc(opts->maxchild * sizeof(struct child));
    465     for(i = 0; i < opts->maxchild; i++)
    466         opts->child[i].status = STATUS_FREE;
    467     opts->nchild = 0;
    468 
    469     /* Create new argv */
    470     opts->oldargv = argv;
    471     opts->newargv = malloc((argc - myoptind + 1) * sizeof(char *));
    472     memcpy(opts->newargv, argv + myoptind, (argc - myoptind) * sizeof(char *));
    473     opts->newargv[argc - myoptind] = (char *)NULL;
    474 
    475     /* Main loop */
    476     while(opts->nchild || opts->seed < opts->endseed)
    477     {
    478         /* Spawn new children, if necessary */
    479         spawn_children(opts);
    480 
    481         /* Cleanup dead or dying children */
    482         clean_children(opts);
    483 
    484         /* Read data from children */
    485         read_children(opts);
    486 
    487         if(opts->maxcrashes && opts->crashes >= opts->maxcrashes
    488             && opts->nchild == 0)
    489         {
    490             if(opts->verbose)
    491                 fprintf(stderr,
    492                         "zzuf: maximum crash count reached, exiting\n");
    493             break;
    494         }
    495 
    496         if(opts->maxtime && _zz_time() - opts->starttime >= opts->maxtime
    497             && opts->nchild == 0)
    498         {
    499             if(opts->verbose)
    500                 fprintf(stderr,
    501                         "zzuf: maximum running time reached, exiting\n");
    502             break;
    503         }
    504     }
    505 
    506     /* Clean up */
    507     _zz_opts_fini(opts);
    508 
    509     return opts->crashes ? EXIT_FAILURE : EXIT_SUCCESS;
    510 }
    511 
    512 static void loop_stdin(struct opts *opts)
    513 {
    514     uint8_t md5sum[16];
    515     struct md5 *ctx = NULL;
    516     int total = 0;
    517 
    518     if(opts->md5)
    519         ctx = _zz_md5_init();
    520 
    521405    if(opts->fuzzing)
    522406        _zz_fuzzing(opts->fuzzing);
     
    530414        _zz_refuse(opts->refuse);
    531415
     416    /* Needed for stdin mode and for copy opmode. */
    532417    _zz_fd_init();
     418
     419    /*
     420     * Mode 1: asked to read from the standard input
     421     */
     422    if(myoptind >= argc)
     423    {
     424        if(opts->verbose)
     425        {
     426            finfo(stderr, opts, opts->seed);
     427            fprintf(stderr, "reading from stdin\n");
     428        }
     429
     430        if(opts->endseed != opts->seed + 1)
     431        {
     432            fprintf(stderr, "%s: seed ranges are incompatible with "
     433                            "stdin fuzzing\n", argv[0]);
     434            printf(MOREINFO, argv[0]);
     435            _zz_opts_fini(opts);
     436            return EXIT_FAILURE;
     437        }
     438
     439        loop_stdin(opts);
     440    }
     441    /*
     442     * Mode 2: asked to launch programs
     443     */
     444    else
     445    {
     446#if defined HAVE_REGEX_H
     447        if(cmdline)
     448        {
     449            int dashdash = 0;
     450
     451            for(i = myoptind + 1; i < argc; i++)
     452            {
     453                if(dashdash)
     454                    include = merge_file(include, argv[i]);
     455                else if(!strcmp("--", argv[i]))
     456                    dashdash = 1;
     457                else if(argv[i][0] != '-')
     458                    include = merge_file(include, argv[i]);
     459            }
     460        }
     461
     462        if(include)
     463            setenv("ZZUF_INCLUDE", include, 1);
     464        if(exclude)
     465            setenv("ZZUF_EXCLUDE", exclude, 1);
     466#endif
     467
     468        setenv("ZZUF_DEBUG", debug ? debug > 1 ? "2" : "1" : "0", 1);
     469        setenv("ZZUF_DEBUGFD", DEBUG_FILENO_STR, 1);
     470
     471        if(opts->fuzzing)
     472            setenv("ZZUF_FUZZING", opts->fuzzing, 1);
     473        if(opts->bytes)
     474            setenv("ZZUF_BYTES", opts->bytes, 1);
     475        if(opts->list)
     476            setenv("ZZUF_LIST", opts->list, 1);
     477        if(opts->ports)
     478            setenv("ZZUF_PORTS", opts->ports, 1);
     479        if(opts->allow && opts->allow[0] == '!')
     480            setenv("ZZUF_DENY", opts->allow, 1);
     481        else if(opts->allow)
     482            setenv("ZZUF_ALLOW", opts->allow, 1);
     483        if(opts->protect)
     484            setenv("ZZUF_PROTECT", opts->protect, 1);
     485        if(opts->refuse)
     486            setenv("ZZUF_REFUSE", opts->refuse, 1);
     487#if defined HAVE_SETRLIMIT && defined ZZUF_RLIMIT_MEM
     488        if(opts->maxmem >= 0)
     489        {
     490            char buf[32];
     491            snprintf(buf, 32, "%i", opts->maxmem);
     492            setenv("ZZUF_MEMORY", buf, 1);
     493        }
     494#endif
     495
     496        /* Allocate memory for children handling */
     497        opts->child = malloc(opts->maxchild * sizeof(struct child));
     498        for(i = 0; i < opts->maxchild; i++)
     499            opts->child[i].status = STATUS_FREE;
     500        opts->nchild = 0;
     501
     502        /* Create new argv */
     503        opts->oldargc = argc;
     504        opts->oldargv = argv;
     505        for(i = 0; i < opts->maxchild; i++)
     506        {
     507            int len = argc - myoptind;
     508            opts->child[i].newargv = malloc((len + 1) * sizeof(char *));
     509            memcpy(opts->child[i].newargv, argv + myoptind,
     510                   len * sizeof(char *));
     511            opts->child[i].newargv[len] = (char *)NULL;
     512        }
     513
     514        /* Main loop */
     515        while(opts->nchild || opts->seed < opts->endseed)
     516        {
     517            /* Spawn new children, if necessary */
     518            spawn_children(opts);
     519
     520            /* Cleanup dead or dying children */
     521            clean_children(opts);
     522
     523            /* Read data from children */
     524            read_children(opts);
     525
     526            if(opts->maxcrashes && opts->crashes >= opts->maxcrashes
     527                && opts->nchild == 0)
     528            {
     529                if(opts->verbose)
     530                    fprintf(stderr,
     531                            "zzuf: maximum crash count reached, exiting\n");
     532                break;
     533            }
     534
     535            if(opts->maxtime && _zz_time() - opts->starttime >= opts->maxtime
     536                && opts->nchild == 0)
     537            {
     538                if(opts->verbose)
     539                    fprintf(stderr,
     540                            "zzuf: maximum running time reached, exiting\n");
     541                break;
     542            }
     543        }
     544    }
     545
     546    /* Clean up */
     547    _zz_fd_fini();
     548    _zz_opts_fini(opts);
     549
     550    return opts->crashes ? EXIT_FAILURE : EXIT_SUCCESS;
     551}
     552
     553static void loop_stdin(struct opts *opts)
     554{
     555    uint8_t md5sum[16];
     556    struct md5 *ctx = NULL;
     557    int total = 0;
     558
     559    if(opts->md5)
     560        ctx = _zz_md5_init();
     561
    533562    _zz_register(0);
    534563
     
    579608
    580609    _zz_unregister(0);
    581     _zz_fd_fini();
    582610}
    583611
     
    666694            break;
    667695
     696    /* Prepare required files, if necessary */
     697    if (opts->opmode == OPMODE_COPY)
     698    {
     699        char tmpname[4096];
     700        char *tmpdir;
     701        FILE *fpin;
     702        int j, k = 0, fdout;
     703
     704        tmpdir = getenv("TEMP");
     705        if (!tmpdir || !*tmpdir)
     706            tmpdir = "/tmp";
     707
     708        for (j = optind + 1; j < opts->oldargc; j++)
     709        {
     710            fpin = fopen(opts->oldargv[j], "r");
     711            if (!fpin)
     712                continue;
     713
     714            sprintf(tmpname, "%s/zzuf.%i.XXXXXX", tmpdir, (int)getpid());
     715            fdout = mkstemp(tmpname);
     716            if (fdout < 0)
     717            {
     718                fclose(fpin);
     719                continue;
     720            }
     721
     722            opts->child[i].newargv[j - optind] = strdup(tmpname);
     723
     724            _zz_register(k);
     725            while(!feof(fpin))
     726            {
     727                uint8_t buf[BUFSIZ];
     728                size_t n = fread(buf, 1, BUFSIZ, fpin);
     729                if (n <= 0)
     730                    break;
     731                _zz_fuzz(k, buf, n);
     732                _zz_addpos(k, n);
     733                write(fdout, buf, n);
     734            }
     735            _zz_unregister(k);
     736
     737            fclose(fpin);
     738            close(fdout);
     739
     740            k++;
     741        }
     742    }
     743
     744    /* Launch process */
    668745    if (myfork(&opts->child[i], opts) < 0)
    669746    {
    670         fprintf(stderr, "error launching `%s'\n", opts->newargv[0]);
     747        fprintf(stderr, "error launching `%s'\n", opts->child[i].newargv[0]);
    671748        opts->seed++;
     749        /* FIXME: clean up OPMODE_COPY files here */
    672750        return;
    673751    }
     
    685763    {
    686764        finfo(stderr, opts, opts->child[i].seed);
    687         fprintf(stderr, "launched `%s'\n", opts->newargv[0]);
     765        fprintf(stderr, "launched `%s'\n", opts->child[i].newargv[0]);
    688766    }
    689767
     
    814892            if(opts->child[i].fd[j] >= 0)
    815893                close(opts->child[i].fd[j]);
     894
     895        if (opts->opmode == OPMODE_COPY)
     896        {
     897            for (j = optind + 1; j < opts->oldargc; j++)
     898            {
     899                if (opts->child[i].newargv[j - optind] != opts->oldargv[j])
     900                {
     901                    unlink(opts->child[i].newargv[j - optind]);
     902                    free(opts->child[i].newargv[j - optind]);
     903                    opts->child[i].newargv[j - optind] = opts->oldargv[j];
     904                }
     905            }
     906        }
    816907
    817908        if(opts->md5)
     
    9761067    printf(                                                " [-I include] [-E exclude]");
    9771068#endif
     1069    printf("              [-O mode]\n");
    9781070    printf("\n");
    9791071    printf("              [PROGRAM [--] [ARGS]...]\n");
     
    10091101#endif
    10101102    printf("  -n, --network             fuzz network input\n");
     1103    printf("  -O, --opmode <mode>       use operating mode <mode> ([preload] copy)\n");
    10111104    printf("  -p, --ports <list>        only fuzz network destination ports in <list>\n");
    10121105    printf("  -P, --protect <list>      protect bytes and characters in <list>\n");
Note: See TracChangeset for help on using the changeset viewer.