Пример #1
0
    def test_get_or_create_latest(self):
        # First game
        r0, status = Round.get_or_create_latest(num=0)
        assert_equals(status, Round.FIRST_GAME)
        assert_equals(r0.num, 0)
        assert_equals(r0, Round.current_round())

        # New round
        r1, status = Round.get_or_create_latest(num=1)
        assert_equals(status, Round.NEW_ROUND)
        assert_equals(r1.num, 1)
        assert_equals(r1, Round.current_round())
        assert_equals(r0, Round.prev_round())

        # Same round
        r1b, status = Round.get_or_create_latest(num=1)
        assert_equals(status, Round.SAME_ROUND)
        assert_equals(r1b.num, 1)
        assert_equals(r1b, Round.current_round())
        assert_equals(r0, Round.prev_round())
        assert_equals(r1, r1b)

        # New game
        r0b, status = Round.get_or_create_latest(num=0)
        assert_equals(status, Round.NEW_GAME)
        assert_equals(r0b.num, 0)
        assert_equals(r0b, Round.current_round())
        assert_is_none(Round.prev_round())
Пример #2
0
 def test_prev_round_on_new_game(self):
     Round.create(num=99)
     assert_equals(Round.prev_round(), None)
     r0 = Round.create(num=0)
     assert_equals(Round.prev_round(), None)
     Round.create(num=1)
     assert_equals(Round.prev_round(), r0)
Пример #3
0
 def test_prev_round(self):
     assert_equals(Round.prev_round(), None)
     Round.create(num=0)
     assert_equals(Round.prev_round(), None)
     r1 = Round.create(num=1)
     Round.create(num=2)
     assert_equals(Round.prev_round(), r1)
Пример #4
0
    def should_submit(target_cs):
        # FIXME: this should be generalized per challenge set introduction
        # don't submit on the first round
        if Round.current_round().num == 0:
            LOG.info("Not submitting on round 0.")
            return False

        # don't submit if we haven't submitted an exploit before this round
        if ExploitSubmissionCable.select().join(
                Exploit).where((ExploitSubmissionCable.cs == target_cs)
                               & (ExploitSubmissionCable.processed_at != None)
                               & (ExploitSubmissionCable.processed_at <=
                                  Round.current_round().created_at)
                               & (Exploit.method != "backdoor")).exists():
            LOG.info("There's an exploit that's over a round old!.")
            return True

        # don't submit if we haven't found an crash before the last round
        prev_round = Round.prev_round()
        if prev_round is not None and Crash.select().where(
            (Crash.cs == target_cs)
                & (Crash.created_at <= prev_round.created_at)).exists():
            LOG.info("There's a crash that's over two rounds old!")
            return True

        LOG.info("Patch conditions not met!")
        return False
Пример #5
0
    def patch_decision_simple(target_cs, round_):
        """
        Determines the CBNs to submit. Returns None if no submission should be made.
        We only submit 1 patch type per CS.
        """
        LOG.info("CB SUBMISSION START: %s (round %d)", target_cs.name,
                 round_.num)

        # make sure that this binary is not new this round
        if not (target_cs.id
                in [cs.id for cs in ChallengeSet.fielded_in_round(round_)]
                and Round.prev_round() is not None and target_cs.id in [
                    cs.id
                    for cs in ChallengeSet.fielded_in_round(Round.prev_round())
                ]):
            LOG.info("%s - not patching in the first round", target_cs.name)
            return

        current_fielding = ChallengeSetFielding.latest(cs=target_cs,
                                                       team=Team.get_our(),
                                                       round=round_)

        # Fielding should always be not None, or we are in a
        # race condition and do not want to do anything right
        # now, we will be run again, at which point fieldings
        # should be set.
        if current_fielding is None:
            LOG.warning(
                "%s - hit the race condition for latest fielding being None",
                target_cs.name)
            return

        LOG.info("%s - current patch type: %s", target_cs.name,
                 (current_fielding.cbns[0].patch_type.name if
                  current_fielding.cbns[0].patch_type is not None else "None"))

        # if we just submitted, wait a round before making any decisions
        if current_fielding.poll_feedback is not None and (
                current_fielding.poll_feedback.timeout +
                current_fielding.poll_feedback.success +
                current_fielding.poll_feedback.function +
                current_fielding.poll_feedback.connect == 0):
            LOG.warning("%s - skipping 'downed' round", target_cs.name)
            return

        # if we don't have any patches ready, let's wait
        all_patches = target_cs.cbns_by_patch_type()
        if len(all_patches) == 0:
            return

        best_patch_type = sorted(all_patches.keys(),
                                 key=lambda pt: pt.exploitability)[0]
        has_feedback = {
            k: v
            for k, v in all_patches.iteritems() if len(v[0].poll_feedbacks) > 0
        }
        pull_back = any(cbns[0].min_cb_score is not None
                        and cbns[0].min_cb_score < MIN_CB_SCORE
                        for cbns in all_patches.values())

        for k, v in has_feedback.items():
            LOG.info("%s - minimum score of patch %s is %s", target_cs.name,
                     k.name, v[0].min_cb_score)

        if pull_back:
            LOG.info("%s - pulling back the patch :-(", target_cs.name)
            new_cbns = target_cs.cbns_original
        else:
            # if we've already patched, and we're not pulling back, forget about it
            if best_patch_type.name != 'manual' and not CBSubmitter.same_cbns(
                    current_fielding.cbns, target_cs.cbns_original):
                LOG.info("%s - already patched -- aborting!", target_cs.name)
                return

            LOG.info("%s - chose %s patch type!", target_cs.name,
                     best_patch_type.name)
            new_cbns = all_patches[best_patch_type]

        # Check if we have submitted in this round?
        submitted_fielding = ChallengeSetFielding.submissions(
            cs=target_cs, team=Team.get_our(), round=round_)

        if submitted_fielding is not None:
            LOG.info("%s - we have an earlier submission this round...",
                     target_cs.name)
            prior_submission = list(submitted_fielding.cbns)
        else:
            LOG.info("%s - submitting for the first time this round...",
                     target_cs.name)
            prior_submission = list(current_fielding.cbns)

        # if we submitted an exploit for the first time this round, let's not patch
        if not pull_back and ExploitSubmissionCable.select(
        ).join(Exploit).where(
            (ExploitSubmissionCable.cs == target_cs)
                & (ExploitSubmissionCable.processed_at != None)
                & (ExploitSubmissionCable.processed_at >= round_.created_at)
                & (Exploit.method != "backdoor")).exists(
                ) and not ExploitSubmissionCable.select().join(Exploit).where(
                    (ExploitSubmissionCable.cs == target_cs)
                    & (ExploitSubmissionCable.processed_at != None)
                    & (ExploitSubmissionCable.processed_at < round_.created_at)
                    & (Exploit.method != "backdoor")).exists():
            LOG.info(
                "%s - not submitting because we first found an exploit last round",
                target_cs.name)
            new_cbns = list(current_fielding.cbns)

        if CBSubmitter.same_cbns(new_cbns, prior_submission):
            LOG.info("%s - nothing to do, this would be a resubmission",
                     target_cs.name)
            return
        else:
            LOG.info("%s - we have not yet submitted these CBNs this round!",
                     target_cs.name)

        return new_cbns