Ejemplo n.º 1
0
    def _firewallSendRules(self):
        p_0 = z3.Const('%s_firewall_send_p_0' % (self.fw), self.ctx.packet)
        p_1 = z3.Const('%s_firewall_send_p_1' % (self.fw), self.ctx.packet)
        n_0 = z3.Const('%s_firewall_send_n_0' % (self.fw), self.ctx.node)
        n_1 = z3.Const('%s_firewall_send_n_1' % (self.fw), self.ctx.node)
        t_0 = z3.Int('%s_firewall_send_t_0' % (self.fw))
        t_1 = z3.Int('%s_firewall_send_t_1' % (self.fw))
        t_2 = z3.Int('%s_firewall_send_t_2' % (self.fw))

        self.acl_func = z3.Function('%s_acl_func' % (self.fw), self.ctx.packet,
                                    z3.BoolSort())

        self.constraints.append(z3.ForAll([n_0, p_0, t_0], z3.Implies(self.ctx.send(self.fw, n_0, p_0, t_0), \
                                       z3.Exists([n_1, t_1], \
                                       z3.And(self.ctx.recv(n_1, self.fw, p_0, t_1),\
                                       t_1 < t_0)))))

        self.constraints.append(z3.ForAll([n_0, p_0, t_0], z3.Implies(\
                z3.And(self.ctx.send(self.fw, n_0, p_0, t_0), \
                  z3.Not(self.acl_func(p_0))), \
                z3.Exists([n_1, p_1, t_1], \
                  z3.And(self.ctx.send(self.fw, n_1, p_1, t_1), \
                         t_1 + 1 <= t_0, \
                         self.acl_func(p_1), \
                         self.ctx.packet.src(p_0) == self.ctx.packet.dest(p_1), \
                         self.ctx.packet.dest(p_0) == self.ctx.packet.src(p_1), \
                         self.ctx.src_port(p_0) == self.ctx.dest_port(p_1), \
                         self.ctx.dest_port(p_0) == self.ctx.src_port(p_1), \
                   )))))
Ejemplo n.º 2
0
    def _aclConstraints(self, solver):
        if len(self.acls) == 0:
            return
        #a_0 = z3.Const('%s_firewall_acl_a_0'%(self.fw), self.ctx.address)
        #a_1 = z3.Const('%s_firewall_acl_a_1'%(self.fw), self.ctx.address)
        p = z3.Const('%s_firewall_acl_p' % (self.fw), self.ctx.packet)
        conditions = []
        for (a, b) in self.acls:
            a_part = None
            b_part = None
            if isinstance(a, str):
                a_part = self.sgroup.sgPredicate(a)(self.ctx.packet.src(p))
            elif isinstance(a, bool):
                a_part = a
            else:
                assert (False)

            if isinstance(b, str):
                b_part = self.sgroup.sgPredicate(b)(self.ctx.packet.dest(p))
            elif isinstance(b, bool):
                b_part = b
            else:
                assert (False)
            if isinstance(a, bool) and isinstance(b, bool):
                solver.add(z3.ForAll([p], self.acl_func(p) == (a and b)))
                return

            conditions.append(z3.And(a_part, b_part))
        solver.add(z3.ForAll([p], self.acl_func(p) == z3.Or(conditions)))
Ejemplo n.º 3
0
def core_assertions(env):
    r = z3.Const('r', Unk)
    g = z3.Const('g', Unk)
    x = z3.Const('x', Unk)
    baseline = []

    # r + () = r
    baseline.append(
        z3.ForAll([r],
                  Z.Eq(Z.Concat(r, Unk._), r),
                  patterns=[Z.Concat(r, Unk._)]))

    # () + r = r
    baseline.append(
        z3.ForAll([r],
                  Z.Eq(Z.Concat(Unk._, r), r),
                  patterns=[Z.Concat(Unk._, r)]))

    # f(g, *(x,), ...) = f(g, x, ...)
    baseline.append(
        z3.ForAll([x, g],
                  Z.Eq(Z.Concat(g, Unk.app(Unk._, x)), Unk.app(g, x)),
                  patterns=[Z.Concat(g, Unk.app(Unk._, x))]))

    # f(g, *(*r, x), ...) = f(g, *r, x, ...)
    baseline.append(
        z3.ForAll([x, g, r],
                  Z.Eq(Z.Concat(g, Unk.app(r, x)), Unk.app(Z.Concat(g, r), x)),
                  patterns=[Z.Concat(g, Unk.app(r, x))]))

    return baseline
Ejemplo n.º 4
0
def merge_queries_new_pred(clauses, queries, decls):
    if len(queries) > 1:
        false1 = z3.Bool("CHC_COMP_FALSE")
        decls.add(false1.decl())

        for query in queries:
            assert (z3.is_quantifier(query) and query.is_forall())

            qvars = [
                z3.Const(query.var_name(n), query.var_sort(n))
                for n in range(0, query.num_vars())
            ]

            body = query.body()
            assert (body.decl().kind() == z3.Z3_OP_IMPLIES)
            kids = body.children()
            assert (kids[1] == z3.BoolVal(False))

            newBody = z3.Implies(kids[0], false1)
            newClause = z3.ForAll(qvars, newBody)

            clauses.append(newClause)

        queries.clear()

        queries.append(
            z3.ForAll(z3.Bool("CHC_COMP_UNUSED"),
                      z3.Implies(z3.And(false1), z3.BoolVal(False))))
def intremaps_equiv(conj, ctx, kernelstate):
    index = util.FreshBitVec('index', dt.size_t)  # intremap index

    conj.append(
        z3.ForAll([index],
                  z3.Implies(
                      is_intremap_valid(index),
                      util.global_field_element(
                          ctx, '@intremap_table', 'state',
                          index) == kernelstate.intremaps[index].state)))

    conj.append(
        z3.ForAll([index],
                  z3.Implies(
                      is_intremap_valid(index),
                      util.global_field_element(
                          ctx, '@intremap_table', 'devid',
                          index) == kernelstate.intremaps[index].devid)))

    conj.append(
        z3.ForAll([index],
                  z3.Implies(
                      is_intremap_valid(index),
                      util.global_field_element(
                          ctx, '@intremap_table', 'vector',
                          index) == kernelstate.intremaps[index].vector)))
Ejemplo n.º 6
0
def spec_lemma_nr_ports_refcnt(kernelstate):
    conj = []

    pid = util.FreshBitVec('pid', dt.pid_t)
    port = util.FreshBitVec('port', dt.uint16_t)

    # unused procs don't own any ports
    # valid([port:pid]) ==> [port:pid].state != UNUSED
    conj.append(
        z3.ForAll([port],
                  z3.Implies(
                      is_pid_valid(kernelstate.io[port].owner),
                      kernelstate.procs[kernelstate.io[port].owner].state !=
                      dt.proc_state.PROC_UNUSED)))
    # pid.state == UNUSED ==> pid.nr_ports == 0
    conj.append(
        z3.ForAll(
            [pid],
            z3.Implies(
                kernelstate.procs[pid].state == dt.proc_state.PROC_UNUSED,
                kernelstate.procs[pid].nr_ports() == z3.BitVecVal(
                    0, dt.size_t))))

    # Correctness definition for `permutation` based refcount
    kernelstate.procs.nr_ports.check(
        conj,
        is_owner_valid=is_pid_valid,
        is_owned_valid=lambda n: z3.BoolVal(True),
        max_refs=2**dt.uint16_t.size(),
        ownerfn=lambda port0: kernelstate.io[port0].owner)

    return z3.And(*conj)
Ejemplo n.º 7
0
    def _populateLoadBalancerConstraints(self):
        self.hash_function = z3.Function(
            'load_balancer_hash_%s' % (self.balancer), z3.IntSort(),
            z3.IntSort(), z3.IntSort())
        p0 = z3.Const('_load_balancer_p0_%s' % (self.balancer),
                      self.ctx.packet)
        p1 = z3.Const('_load_balancer_p1_%s' % (self.balancer),
                      self.ctx.packet)
        n0 = z3.Const('_load_balancer_n0_%s' % (self.balancer), self.ctx.node)
        n1 = z3.Const('_load_balancer_n1_%s' % (self.balancer), self.ctx.node)
        n2 = z3.Const('_load_balancer_n2_%s' % (self.balancer), self.ctx.node)
        hash_same = [self.ctx.packet.src(p0) == self.ctx.packet.src(p1), \
                     self.ctx.packet.dest(p0) == self.ctx.packet.dest(p1), \
                     self.hash_function(self.ctx.src_port(p0), self.ctx.dest_port(p0)) == \
                        self.hash_function(self.ctx.src_port(p1), self.ctx.dest_port(p1)), \
                     self.ctx.send(self.balancer, n0, p0), \
                     self.ctx.send(self.balancer, n1, p1)
                    ]
        self.constraints.append(z3.ForAll([n0, p0, n1, p1], \
                                z3.Implies(z3.And(hash_same), \
                                            n0 == n1)))

        self.constraints.append(z3.ForAll([n0, p0], \
                                  z3.Implies(\
                                      self.ctx.send(self.balancer, n0, p0), \
                                    z3.And( \
                                        z3.Exists([n1], \
                                          z3.And(self.ctx.recv(n1, self.balancer, p0), \
                                            n1 != n0)), \
                                          z3.Not(z3.Exists([n2], \
                                              z3.And(n2 != n0, \
                                                self.ctx.send(self.balancer, n2, p0)))), \
                                          self.ctx.etime(self.balancer, p0, self.ctx.send_event) > \
                                            self.ctx.etime(self.balancer, p0, self.ctx.recv_event)))))
Ejemplo n.º 8
0
def spec_lemma_nr_dmapages_refcnt(kernelstate):
    conj = []

    pid = util.FreshBitVec('pid', dt.pid_t)
    dmapn = util.FreshBitVec('dmapn', dt.dmapn_t)

    # General invariant -- a free dma page has no owner
    conj.append(
        z3.ForAll([dmapn],
                  z3.Implies(
                      is_dmapn_valid(dmapn),
                      is_pid_valid(kernelstate.dmapages[dmapn].owner) == (
                          kernelstate.dmapages[dmapn].type !=
                          dt.page_type.PAGE_TYPE_FREE))))

    # PROC_UNUSED state implies refcount is 0 (sys_clone needs this)
    conj.append(
        z3.ForAll(
            [pid],
            z3.Implies(
                is_pid_valid(pid),
                z3.Implies(
                    kernelstate.procs[pid].state == dt.proc_state.PROC_UNUSED,
                    kernelstate.procs[pid].nr_dmapages() == z3.BitVecVal(
                        0, dt.size_t)))))

    # # Correctness definition for `permutation` based refcount
    kernelstate.procs.nr_dmapages.check(
        conj,
        is_owner_valid=is_pid_valid,
        is_owned_valid=is_dmapn_valid,
        max_refs=dt.NDMAPAGE,
        ownerfn=lambda dmapn: kernelstate.dmapages[dmapn].owner)

    return z3.And(*conj)
Ejemplo n.º 9
0
    def _constraints(self):
        #self.count_func = z3.Function('count_%s'%(self.node), self.ctx.address, self.ctx.address, \
        #z3.IntSort(), z3.IntSort())
        p0 = z3.Const('_counter_p0_%s' % (self.node), self.ctx.packet)
        p1 = z3.Const('_counter_p1_%s' % (self.node), self.ctx.packet)
        n0 = z3.Const('_counter_n0_%s' % (self.node), self.ctx.node)
        n1 = z3.Const('_counter_n1_%s' % (self.node), self.ctx.node)
        n2 = z3.Const('_counter_n2_%s' % (self.node), self.ctx.node)
        t0 = z3.Int('_counter_t0_%s' % (self.node))
        t1 = z3.Int('_counter_t1_%s' % (self.node))
        a0 = z3.Const('_counter_a0_%s' % (self.node), self.ctx.address)
        a1 = z3.Const('_counter_a1_%s' % (self.node), self.ctx.address)

        # Make sure all packets sent were first recved
        self.constraints.append(z3.ForAll([n0, p0], \
                              z3.Implies(self.ctx.send(self.node, n0, p0), \
                                z3.And( \
                                    z3.Exists([n1], \
                                      z3.And (self.ctx.recv(n1, self.node, p0), \
                                       n0 != n1)), \
                                       z3.Not(z3.Exists([n2], \
                                              z3.And(self.ctx.send(self.node, n2, p0), \
                                                     n2 != n0))), \
                                       self.ctx.etime(self.node, p0, self.ctx.send_event) > \
                                           self.ctx.etime(self.node, p0, self.ctx.recv_event)))))

        # Make sure packets go one at a time
        self.constraints.append(z3.ForAll([p0, t0], \
                              z3.Implies(z3.And(self.ctx.etime(self.node, p0, self.ctx.send_event) == t0, \
                                               t0 != 0), \
                                           z3.ForAll([p1], \
                                                z3.Or(p0 == p1, \
                                                   self.ctx.etime(self.node, p1, \
                                                                 self.ctx.send_event) != \
                                                       t0)))))
Ejemplo n.º 10
0
    def _addConstraints(self, solver):
        solver.add(self.constraints)
        p = z3.Const('__ips_acl_Packet_%s' % (self.ips), self.ctx.packet)
        addr_a = z3.Const('__ips_acl_cache_a_%s' % (self.ips),
                          self.ctx.address)
        port_a = z3.Const('__ips_acl_port_a_%s' % (self.ips), z3.IntSort())
        addr_b = z3.Const('__ips_acl_cache_b_%s' % (self.ips),
                          self.ctx.address)
        port_b = z3.Const('__ips_acl_port_b_%s' % (self.ips), z3.IntSort())
        aclConstraints = map(lambda (a, b): z3.And(self.ctx.packet.src(p) == a, \
                                              self.ctx.packet.dest(p) == b),
                                              self.acls)
        eh = z3.Const('__ips_acl_node_%s' % (self.ips), self.ctx.node)

        # Constraints for what holes are punched
        # \forall a, b cached(a, b) \iff \exists e, p send(f, e, p) \land
        #                 p.src == a \land p.dest == b \land ctime(a, b) = etime(ips, p, R) \land
        #                   neg(ACL(p))
        if len(aclConstraints) > 0:
            solver.add(z3.ForAll([addr_a, port_a, addr_b, port_b], self.cached(addr_a, port_a, addr_b, port_b) ==\
                           z3.Exists([eh, p], \
                               z3.And(self.ctx.recv(eh, self.ips, p), \
                               z3.And(self.ctx.packet.src (p) == addr_a, self.ctx.packet.dest(p) == addr_b, \
                                       self.ctx.src_port (p) == port_a,  self.ctx.dest_port (p) == port_b, \
                                       self.ctime (addr_a, port_a, addr_b, port_b) == self.ctx.etime(self.ips, p, self.ctx.recv_event), \
                                       z3.Not(z3.Or(aclConstraints)))))))
        else:
            solver.add(z3.ForAll([addr_a, port_a, addr_b, port_b], self.cached(addr_a, port_a, addr_b, port_b) ==\
                           z3.Exists([eh, p], \
                               z3.And(self.ctx.recv(eh, self.ips, p), \
                               z3.And(self.ctx.packet.src (p) == addr_a, self.ctx.packet.dest(p) == addr_b, \
                                       self.ctx.src_port (p) == port_a,  self.ctx.dest_port (p) == port_b, \
                                       self.ctime (addr_a, port_a, addr_b, port_b) == self.ctx.etime(self.ips, p, self.ctx.recv_event))))))
Ejemplo n.º 11
0
def spec_lemma_nr_devs_refcnt(kernelstate):
    conj = []

    pid = util.FreshBitVec('pid', dt.pid_t)
    devid = util.FreshBitVec('devid', dt.devid_t)

    # unused procs don't own any devices
    conj.append(
        z3.ForAll([devid],
                  z3.Implies(
                      is_pid_valid(kernelstate.pci[devid].owner),
                      kernelstate.procs[kernelstate.pci[devid].owner].state !=
                      dt.proc_state.PROC_UNUSED)))

    conj.append(
        z3.ForAll(
            [pid],
            z3.Implies(
                kernelstate.procs[pid].state == dt.proc_state.PROC_UNUSED,
                kernelstate.procs[pid].nr_devs() == z3.BitVecVal(0,
                                                                 dt.size_t))))

    # Correctness definition for `permutation` based refcount
    kernelstate.procs.nr_devs.check(
        conj,
        is_owner_valid=is_pid_valid,
        is_owned_valid=lambda n: z3.BoolVal(True),
        max_refs=2**dt.devid_t.size(),
        ownerfn=lambda devid0: kernelstate.pci[devid0].owner)

    return z3.And(*conj)
Ejemplo n.º 12
0
 def _ipsFunctions(self):
     self.cached = z3.Function('__ips_cached_rules_%s' % (self.ips),
                               self.ctx.address,
                               z3.IntSort(), self.ctx.address, z3.IntSort(),
                               z3.BoolSort())
     self.ctime = z3.Function('__ips_cached_time_%s' % (self.ips),
                              self.ctx.address, z3.IntSort(),
                              self.ctx.address, z3.IntSort(), z3.IntSort())
     addr_a = z3.Const('__ips_addr_cache_a_%s' % (self.ips),
                       self.ctx.address)
     port_a = z3.Const('__ips_addr_port_a_%s' % (self.ips), z3.IntSort())
     addr_b = z3.Const('__ips_addr_cache_b_%s' % (self.ips),
                       self.ctx.address)
     port_b = z3.Const('__ips_addr_port_b_%s' % (self.ips), z3.IntSort())
     self.constraints.append(z3.ForAll([addr_a, port_a, addr_b, port_b], z3.Implies(\
                     z3.Or(port_a < 0, \
                           port_a > Core.MAX_PORT, \
                           port_b < 0, \
                           port_a > Core.MAX_PORT), \
                     z3.Not(self.cached(addr_a, port_a, addr_b, port_b)))))
     self.constraints.append(z3.ForAll([addr_a, port_a, addr_b, port_b], self.ctime (addr_a, port_a, addr_b, port_b) \
                                         >= 0))
     self.constraints.append(z3.ForAll([addr_a, port_a, addr_b, port_b], z3.Implies(\
                     z3.Not(self.cached(addr_a, port_a, addr_b, port_b)), \
                     self.ctime (addr_a, port_a, addr_b, port_b) == 0)))
Ejemplo n.º 13
0
    def _ipsSendRules(self):
        p = z3.Const('__ips_Packet_%s' % (self.ips), self.ctx.packet)
        eh = z3.Const('__ips_node1_%s' % (self.ips), self.ctx.node)
        eh2 = z3.Const('__ips_node2_%s' % (self.ips), self.ctx.node)
        eh3 = z3.Const('__ips_node3_%s' % (self.ips), self.ctx.node)

        # The ips never invents packets
        # \forall e_1, p\ send (f, e_1, p) \Rightarrow \exists e_2 recv(e_2, f, p)
        self.constraints.append(z3.ForAll([eh, p], z3.Implies(self.ctx.send(self.ips, eh, p), \
                z3.Exists([eh2], \
                 z3.And(self.ctx.recv(eh2, self.ips, p), \
                    z3.Not(z3.Exists([eh3], z3.And(self.ctx.send(self.ips, eh3, p),\
                                                   eh3 != eh))), \
                    self.ctx.etime(self.ips, p, self.ctx.recv_event) < \
                        self.ctx.etime(self.ips, p, self.ctx.send_event))))))

        # Actually enforce ips rules
        # \forall e_1, p send(f, e_1, p) \Rightarrow (cached(p.src, p.dest)
        #                       \land ctime(p.src, p.dest) <= etime(ips, p, R))
        #                       \lor (cached(p.dest, p.src) \land ctime(p.dest, p.src) <= etime(ips. p, R))
        self.constraints.append(z3.ForAll([eh, p], z3.Implies(self.ctx.send(self.ips, eh, p), \
                 z3.And(z3.Not(self.policy.dpi_match(self.ctx.packet.body(p))), \
                        z3.Or(z3.And(self.cached(self.ctx.packet.src(p), self.ctx.src_port(p), self.ctx.packet.dest(p), self.ctx.dest_port(p)), \
                                        self.ctime(self.ctx.packet.src(p), self.ctx.src_port(p), self.ctx.packet.dest(p), self.ctx.dest_port(p)) <\
                                                        self.ctx.etime(self.ips, p, self.ctx.recv_event)), \
                              z3.And(self.cached(self.ctx.packet.dest(p), self.ctx.dest_port(p), self.ctx.packet.src(p), self.ctx.src_port(p)), \
                                        self.ctime(self.ctx.packet.dest(p), self.ctx.dest_port(p), self.ctx.packet.src(p), self.ctx.src_port(p)) <\
                                                        self.ctx.etime(self.ips, p, self.ctx.recv_event)))))))
def pages_equiv(conj, ctx, kernelstate):
    pn = util.FreshBitVec('pn', dt.pn_t)
    idx = util.FreshBitVec('page_index', 64)

    conj.append(
        z3.ForAll([pn, idx],
                  z3.Implies(
                      z3.And(is_pn_valid(pn), z3.ULT(idx, 512)),
                      util.global_to_uf_dict(ctx, '@pages')[()](
                          util.i64(0), pn,
                          idx) == kernelstate.pages[pn].data(idx))))

    conj.append(
        z3.ForAll(
            [pn],
            z3.Implies(
                is_pn_valid(pn),
                util.global_field_element(ctx, '@page_desc_table', 'pid',
                                          pn) == kernelstate.pages[pn].owner)))

    conj.append(
        z3.ForAll(
            [pn],
            z3.Implies(
                is_pn_valid(pn),
                util.global_field_element(ctx, '@page_desc_table', 'type',
                                          pn) == kernelstate.pages[pn].type)))
Ejemplo n.º 15
0
 def setAddressMappings(self, addrmap):
     """Specify host to address mapping"""
     # Set address mapping for nodes.
     for node, addr in addrmap:
         a_0 = z3.Const('%s_address_mapping_a_0' % (node), self.ctx.address)
         # Node has a single address
         if not isinstance(addr, list) or len(addr) == 0:
             # $$addrToNode(addr) = node$$
             self.constraints.append(
                 self.ctx.addrToNode(addr) == node.z3Node)
             # $$nodeHasAddr(node, a_0) \iff a_0 = addr$$
             # Note we need the $\iff$ here to make sure that we set nodeHasAddr to false
             # for other addresses.
             self.constraints.append(z3.ForAll([a_0], \
                 (a_0 == addr) == self.ctx.nodeHasAddr(node.z3Node, a_0)))
         # Node has several addresses
         else:
             or_clause = []
             for ad in addr:
                 # $$addrToNode(addr) = node$$
                 self.constraints.append(
                     self.ctx.addrToNode(ad) == node.z3Node)
                 or_clause.append(a_0 == ad)
             # Note we need the $\iff$ here to make sure that we set nodeHasAddr to false
             # for other addresses.
             self.constraints.append(z3.ForAll([a_0], \
                     z3.Or(or_clause) == self.ctx.nodeHasAddr(node.z3Node, a_0)))
Ejemplo n.º 16
0
def make_array(creator: SymbolicFactory) -> object:
    space = creator.space
    code, minval, maxval = pick_code(space)
    nums = SymbolicArrayBasedUniformTuple(creator.varname, Tuple[int, ...])
    z3_array = nums._arr()
    qvar = z3.Int("arrvar" + space.uniq())
    space.add(z3.ForAll([qvar], minval <= z3.Select(z3_array, qvar)))
    space.add(z3.ForAll([qvar], z3.Select(z3_array, qvar) < maxval))
    return SymbolicArray(code, nums)
def impl_invariants_c(ctx):
    conj = []

    pid = util.FreshBitVec('pid', dt.pid_t)
    pn = util.FreshBitVec('pn', dt.pn_t)
    fd = util.FreshBitVec('fd', dt.fd_t)

    try:
        old_solver = ctx.solver
        old_globals = ctx.globals

        def implies(ctx, a, b):
            return z3.Implies(a, b)

        def and_(ctx, *args):
            return z3.And(*args)

        def or_(ctx, *args):
            return z3.Or(*args)

        ctx.globals['@implies'] = implies
        ctx.globals['@and2'] = and_
        ctx.globals['@and3'] = and_
        ctx.globals['@and4'] = and_
        ctx.globals['@and5'] = and_
        ctx.globals['@and6'] = and_
        ctx.globals['@and7'] = and_
        ctx.globals['@and8'] = and_
        ctx.globals['@and9'] = and_
        ctx.globals['@or2'] = or_
        ctx.globals['@or3'] = or_
        ctx.globals['@or4'] = or_

        ctx.solver = solver.Solver()
        ctx.solver.add(z3.BoolVal(False))

        conj.append(z3.ForAll([pid], ctx.call('@inv_proc_owns_pns', pid)))
        conj.append(z3.ForAll([pid], ctx.call(
            '@inv_sleeping_proc_owns_ipc', pid)))
        conj.append(z3.ForAll([pid], ctx.call(
            '@inv_sleeping_proc_ipc_fd_valid_empty', pid)))
        conj.append(z3.ForAll([pid], ctx.call('@inv_proc_pns_valid', pid)))
        conj.append(z3.ForAll([pid], ctx.call('@inv_io_bitmap', pid)))
        conj.append(z3.ForAll([pn], ctx.call('@inv_page_owner', pn)))
        conj.append(z3.ForAll([pn], ctx.call('@inv_proc_unused_refs', pn)))
        conj.append(z3.ForAll([pid, fd], ctx.call( '@inv_proc_fds_valid', pid, fd)))
        conj.append(z3.ForAll([pn], ctx.call('@inv_page_freelist_valid', pn)))
        conj.append(z3.ForAll([pid], ctx.call('@inv_proc_freelist_valid', pid)))
        conj.append(ctx.call('@inv_current_valid'))
        conj.append(ctx.call('@inv_current_running'))

    finally:
        ctx.solver = old_solver
        ctx.globals = old_globals

    return z3.And(*conj)
Ejemplo n.º 18
0
def spec_lemma_nr_children_refcnt(kernelstate):
    conj = []

    pid = util.FreshBitVec('pid', dt.pid_t)

    # pid has a parent <=> pid is not PROC_UNUSED
    # valid(pid) & valid(ppid) ==> state(pid) != PROC_UNUSED
    conj.append(
        z3.ForAll([pid],
                  z3.Implies(
                      is_pid_valid(pid),
                      is_pid_valid(kernelstate.procs[pid].ppid) == (
                          kernelstate.procs[pid].state !=
                          dt.proc_state.PROC_UNUSED))))

    # valid(pid) & state(pid) == PROC_UNUSED ==> !valid(ppid)
    conj.append(
        z3.ForAll(
            [pid],
            z3.Implies(
                is_pid_valid(pid),
                z3.Implies(
                    kernelstate.procs[pid].state == dt.proc_state.PROC_UNUSED,
                    z3.Not(is_pid_valid(kernelstate.procs[pid].ppid))))))

    # PROC_UNUSED state implies refcnt is 0
    # valid(pid) & state(pid) == PROC_UNUSED ==> pid.nr_children == 0
    conj.append(
        z3.ForAll(
            [pid],
            z3.Implies(
                is_pid_valid(pid),
                z3.Implies(
                    kernelstate.procs[pid].state == dt.proc_state.PROC_UNUSED,
                    kernelstate.procs[pid].nr_children() == z3.BitVecVal(
                        0, dt.size_t)))))

    # unused procs don't have a parent
    conj.append(
        z3.ForAll(
            [pid],
            z3.Implies(
                z3.And(
                    is_pid_valid(pid),
                    kernelstate.procs[pid].state == dt.proc_state.PROC_UNUSED),
                kernelstate.procs[pid].ppid == z3.BitVecVal(0, dt.pid_t))))

    # Correctness definition for `permutation` based refcount
    kernelstate.procs.nr_children.check(
        conj,
        is_owner_valid=is_pid_valid,
        is_owned_valid=is_pid_valid,
        max_refs=dt.NPROC - 1,
        ownerfn=lambda pid0: kernelstate.procs[pid0].ppid)

    return z3.And(*conj)
Ejemplo n.º 19
0
    def __eq__(self, other):

        ino = z3.Int(fresh_name('ino'))
        ino_match = z3.ForAll(
            [ino], z3.And(self.inode_nlink(ino) == other.inode_nlink(ino)))

        fname = z3.Int(fresh_name('fname'))
        fname_match = z3.ForAll(
            [fname],
            self.fname_inode(fname) == other.fname_inode(fname))
        return z3.And(ino_match, fname_match)
Ejemplo n.º 20
0
    def _add_column(self, numbers, skip, base, size, prefix):
        """Converts numbers in one line into assertions for self._solver.

        Args:
          numbers: A list of constraint numbers in one
                   (either horizontal or vertical) line.
          skip, base, size: Specifies the line where the numbers come from.
          prefix: The name prefix of the new variables used in the assertion.

        Retunes: None.

        This provides set of assertions into self._solver.
        This is only expected to be called from the _solve() method."""

        if numbers == []:
            # No numbers. All the field in this line should be False.
            for i in xrange(size):
                self._solver.add(z3.Not(self._field[base + skip * i]))
            return

        # Variables for the position of the sequence in the line.
        # If numbers = [4,6], v[0] is the index of the 4-length sequence,
        # v[1] is the index for the 6-length sequence.
        v = [z3.Int('%s%d' % (prefix, i)) for i in range(len(numbers))]

        # Assertions for v[].
        # 0 <= v[0], v[0] + n[0] < v[1], ..., v[len-1] + n[len-1] <= size.
        self._solver.add(v[0] >= 0)
        for i in xrange(len(numbers) - 1):
            self._solver.add(v[i] + numbers[i] < v[i + 1])
        self._solver.add(v[-1] + numbers[-1] <= size)

        # Assertions for filled fields.
        for s, c in zip(v, numbers):
            for i in xrange(c):
                self._solver.add(self._field[base + (s + i) * skip])

        # Assertions for unfilled fields.
        fa = z3.Int('%s__1' % prefix)
        self._solver.add(
            z3.ForAll([fa],
                      z3.Or(fa < 0, v[0] <= fa,
                            z3.Not(self._field[base + skip * fa]))))
        for i in xrange(len(numbers) - 1):
            fa = z3.Int('%s_%d' % (prefix, i))
            self._solver.add(
                z3.ForAll([fa],
                          z3.Or(fa < v[i] + numbers[i], v[i + 1] <= fa,
                                z3.Not(self._field[base + skip * fa]))))
        fa = z3.Int('%s_%d' % (prefix, len(numbers)))
        self._solver.add(
            z3.ForAll([fa],
                      z3.Or(fa < v[-1] + numbers[-1], size <= fa,
                            z3.Not(self._field[base + skip * fa]))))
Ejemplo n.º 21
0
 def _idsSendRules(self):
     p_0 = z3.Const('%s_p_0' % (self.node), self.ctx.packet)
     n_0 = z3.Const('%s_n_0' % (self.node), self.ctx.node)
     n_1 = z3.Const('%s_n_1' % (self.node), self.ctx.node)
     t_0 = z3.Int('%s_t_0' % self.node)
     t_1 = z3.Int('%s_t_1' % self.node)
     self.constraints.append(z3.ForAll([n_0, p_0, t_0], z3.Implies(self.ctx.send(self.node, n_0, p_0, t_0), \
                                z3.Exists([n_1, t_1], \
                                  z3.And(self.ctx.recv(n_1, self.node, p_0, t_1), \
                                         t_1 < t_0)))))
     self.constraints.append(z3.ForAll([n_0, p_0, t_0], \
             z3.Implies(z3.And(self.ctx.send(self.node, n_0, p_0, t_0), \
                               self.suspicious(p_0)), \
                         n_0 == self.shunt)))
Ejemplo n.º 22
0
def spec_lemma_nr_fds_refcnt(kernelstate):
    conj = []

    pid = util.FreshBitVec('pid', dt.pid_t)
    fd = util.FreshBitVec('fd', dt.fd_t)

    # unused procs do not have any fds.
    # valid(pid) & state(pid)== PROC_UNUSED ==> pid.nr_fds == 0
    conj.append(
        z3.ForAll(
            [pid],
            z3.Implies(
                is_pid_valid(pid),
                z3.Implies(
                    kernelstate.procs[pid].state == dt.proc_state.PROC_UNUSED,
                    kernelstate.procs[pid].nr_fds() == z3.BitVecVal(
                        0, dt.size_t)))))

    # unused procs do not have any opened files
    # valid(pid) & valid(fd) & state(pid) == PROC_UNUSED ==> !valid(openedfile(pid, fd))
    conj.append(
        z3.ForAll(
            [pid, fd],
            z3.Implies(
                z3.And(is_pid_valid(pid), is_fd_valid(fd)),
                z3.Implies(
                    kernelstate.procs[pid].state == dt.proc_state.PROC_UNUSED,
                    z3.Not(is_fn_valid(kernelstate.procs[pid].ofile(fd)))))))

    # a procs have opened a file, the state of this procs must not be UNUSED
    # valid(pid) & valid(fd) & valid(fn)  ==> state(pid) != PROC_UNUSED
    conj.append(
        z3.ForAll(
            [pid, fd],
            z3.Implies(
                z3.And(is_pid_valid(pid), is_fd_valid(fd),
                       is_fn_valid(kernelstate.procs[pid].ofile(fd))),
                kernelstate.procs[pid].state != dt.proc_state.PROC_UNUSED)))

    # Correctness definition for `permutation` based refcount
    kernelstate.procs.nr_fds.check(
        conj,
        is_owner_valid=is_pid_valid,
        is_owned_valid=is_fd_valid,
        max_refs=dt.NOFILE,
        ownedby=lambda pid, fd: is_fn_valid(kernelstate.procs[pid].ofile(fd)))

    return z3.And(*conj)
def state_equiv(kernelstate, userstate):
    conj = []

    pid = util.FreshBitVec('pid.eq', kdt.pid_t)

    idx1 = util.FreshBitVec('idx1.eq', kdt.size_t)
    idx2 = util.FreshBitVec('idx2.eq', kdt.size_t)
    idx3 = util.FreshBitVec('idx', kdt.size_t)
    idx4 = util.FreshBitVec('idx', kdt.size_t)

    conj.append(z3.ForAll([pid, idx1, idx2, idx3, idx4],
        z3.Implies(
            z3.And(
                kspec.is_pid_valid(pid),
                kspec.is_status_live(kernelstate.procs[pid].state),

                z3.ULT(idx1, 512),
                z3.ULT(idx2, 512),
                z3.ULT(idx3, 512),
                z3.ULT(idx4, 512),
                ),
            z3.And(
                pgwalk_rw(kernelstate, pid,  idx1, idx2, idx3, idx4) ==
                userstate.writable(pid, idx1, idx2, idx3, idx4)
            ))))

    return z3.And(*conj)
Ejemplo n.º 24
0
 def test_successs_with_mock(self):
     x = z3.Int('pkt_0_0_0_0')
     simple_formula = z3.ForAll([x], z3.And(x > 3, x < 2))
     pkt_fields, state_vars = z3_utils.generate_counterexamples(
         simple_formula)
     self.assertTrue('pkt_0' in pkt_fields)
     self.assertDictEqual(state_vars, {})
Ejemplo n.º 25
0
 def test_state_group_with_alphabets(self):
     x = z3.Int('state_group_1_state_0_b_b_0')
     simple_formula = z3.ForAll([x], z3.And(x > 3, x < 2))
     pkt_fields, state_vars = z3_utils.generate_counterexamples(
         simple_formula)
     self.assertDictEqual(pkt_fields, {})
     self.assertTrue('state_group_1_state_0' in state_vars)
Ejemplo n.º 26
0
def check(*assertions, for_all=[], return_type='str'):
    ctx = Context()
    with munge_exceptions():
        assertions = unwrap([assertion.eval(ctx) for assertion in assertions])
    if for_all:
        for_all = unwrap([f.eval(ctx) for f in for_all])
        assertions = [z3.ForAll(for_all, v) for v in assertions]
    SOLVER.reset()
    result = SOLVER.check(*assertions)
    if result != z3.sat:
        return (result, None)
    # The expression is satisfiable. Create a dictionary from the resulting
    # model, since the model returned by Z3 uses Z3 variables as keys, which
    # are only created on-demand in eval() above, thus not very useful outside
    # of this function
    model = SOLVER.model()
    if return_type == 'str':
        model = {
            v.name():
            '%#0*x' % ((model[v].size() + 3) // 4 + 2, model[v].as_long())
            for v in model
        }
    elif return_type == 'int':
        model = {v.name(): model[v].as_long() for v in model}
    elif return_type == 'var':
        model = {v.name(): model[v] for v in model}
    elif return_type.startswith('serial'):
        etype = return_type[7:]
        model = {v.name(): serialize(model[v], etype) for v in model}
    else:
        assert False, 'return type must be one of "str", "int", "var", or "serial:<type>"'
    return (result, model)
Ejemplo n.º 27
0
 def _aclConstraints(self, solver):
     if len(self.acls) == 0:
         return
     a_0 = z3.Const('%s_firewall_acl_a_0'%(self.fw), self.ctx.address)
     a_1 = z3.Const('%s_firewall_acl_a_1'%(self.fw), self.ctx.address)
     acl_map = map(lambda (a, b): z3.Or(z3.And(a_0 == a, a_1 == b), z3.And(a_0 == b, a_1 == a)), self.acls)
     solver.add(z3.ForAll([a_0, a_1], self.acl_func(a_0, a_1) == z3.Or(acl_map)))
Ejemplo n.º 28
0
def fix_clause(clause):
    context = extract_implies(clause)
    # print 'working on'
    # print_context(context, pref='  ')

    qvars = context['qvars']
    body_exprs = []
    for expr in context['body']:
        # res = fix_pred_app(qvars, expr)
        # qvars = res[0]
        # body_exprs.append(res[1])
        # for expr in res[2]:
        #     body_exprs.append(expr)
        body_exprs.append(expr)

    res = fix_pred_app(qvars, context['head'])
    qvars = res[0]
    head = res[1]
    for expr in res[2]:
        body_exprs.append(expr)
    if len(body_exprs) > 1:
        body = z3.And(body_exprs)
    elif len(body_exprs) == 1:
        body = body_exprs[0]
    else:
        raise Exception('unexpected empty clause body')
    query = head.decl().kind() != z3.Z3_OP_UNINTERPRETED
    implies = z3.Implies(body, head)

    quantified = z3.ForAll(qvars, implies)

    # print(quantified)

    return (quantified, query)
Ejemplo n.º 29
0
def spec_lemma_nr_pages_refcnt(kernelstate):
    conj = []

    pid = util.FreshBitVec('pid', dt.pid_t)

    # PROC_UNUSED state implies refcount is 0 (sys_clone needs this)
    conj.append(
        z3.ForAll(
            [pid],
            z3.Implies(
                is_pid_valid(pid),
                z3.Implies(
                    kernelstate.procs[pid].state == dt.proc_state.PROC_UNUSED,
                    kernelstate.procs[pid].nr_pages() == z3.BitVecVal(
                        0, dt.size_t)))))

    # Correctness definition for `permutation` based refcount
    kernelstate.procs.nr_pages.check(
        conj,
        is_owner_valid=is_pid_valid,
        is_owned_valid=is_pn_valid,
        max_refs=dt.NPAGE,
        ownerfn=lambda pn: kernelstate.pages[pn].owner)

    return z3.And(*conj)
Ejemplo n.º 30
0
def spec_corollary_pgwalk(kernelstate):
    pid = util.FreshBitVec('pid', dt.pid_t)
    va = dt.FreshVA()

    pml4 = kernelstate.procs[pid].page_table_root
    # Abstract model of a page_walk starting from some root
    page, writable, present = page_walk(kernelstate, pml4, *va)

    # If a four level page-walk from some pid returns a page,
    # that page must be exclusively owned by the pid.
    # furthermore, if the page is writable,
    # it has to be a frame.
    isolation = util.Implies(
        present, kernelstate.pages[page].owner == pid,
        z3.Implies(
            writable,
            kernelstate.pages[page].type == dt.page_type.PAGE_TYPE_FRAME))
    # valid(pid) & pid.state == active & valid(va) ==> page.owner == pid && page.type == FRAME (active is either EMBRYO, RUNNABLE or RUNNING)

    return z3.ForAll([pid] + va,
                     z3.Implies(
                         z3.And(
                             is_pid_valid(pid),
                             is_status_live(kernelstate.procs[pid].state),
                             is_va_valid(va),
                         ), isolation))