2018-10-31
Institute of Informatics
Chair for Software and Computational Systems
Prof. Dr. Dirk Beyer
Moritz Buhl
m.buhl@campus.lmu.de
11549061
| Period of Writing: | 2018-04-09 – 2018-09-30 | |
| External Advisor: | Alexander Bluhm | |
| Advisor: | Thomas Lemberger | |
| Supervisor: | Prof. Dr. Dirk Beyer | |
| Project Files: | https://www.moritzbuhl.de/bachelor-thesis |
Bugs are present long after the initial implementation.
Is it possible to find errors in the network stack automatically?
| Patch | Length calculation | Memory handling | NULL pointers | Location |
| 003_mpls | X | X | X | mpls_input() |
| 005_ahopts | X | X | ah_massage_header()[sic] | |
| 006_ipseclen | X | IPsec callback()s | ||
| 006_prevhdr | X | rip6_input(), frag6_input() | ||
| 007_etherip | X | ip_etherip_input() | ||
| 010_ahauth | X | IPsec _input()s | ||
| 010_pipex | X | pipex_pptp_input() |
switch (rt_mpls->mpls_operation) {
case MPLS_OP_POP:
m = mpls_shim_pop(m);
+ if (m == NULL)
+ goto done;
- if (m == NULL)
+ if (m == NULL) {
+ if_put(ifp);
return;
+ }
+ if (m->m_len < sizeof(u_char) &&
+ (m = m_pullup(m, sizeof(u_char))) == NULL)
+ return (NULL);
(L, l₀, G)
L := locations
l₀ := initial locatioin
G := control-flow edges
int ip_deliver(struct mbuf **mp,
int *offp, int nxt, int af) {
const struct protosw *psw;
int naf = af;
while (nxt != IPPROTO_DONE) {
psw = &inetsw[ip_protox[nxt]];
nxt = (*psw->pr_input)(mp, offp, nxt, af);
af = naf;
}
return nxt;
}
𝔻 = (D, ⇝, merge, stop)D = (C, 𝜀,⟦·⟧)𝜀 = (E, ⊤, ⊥, ⊑, ⊔)⟦·⟧: E → 2^C⇝ ⊆ E ⨯ G ⨯ Emerge: E ⨯ E → Estop: E ⨯ 2^E → 𝔹
1: Input: a CPA 𝔻 and an initial state e0 ∈ E
2: Output: a set reached of reachable states
3: waitlist := { e0 }
4: reached := { e0 }
5: while waitlist ≠ {} do
6: pop e from waitlist
7: for each e' with e' ⇝ e do
8: for each e'' ∈ reached do
9: en := merge(e', e'')
10: if en = e then
11: waitlist := (waitlist ∪ {en}) ∪ {e''}
12: reached := (reached ∪ {en}) ∪ {e''}
13: if ¬stop(e', reached) then
14: waitlist := waitlist ∪ {e'}
15: reached := reached ∪ {e'}
16: return reached
Points-to: ● → (addr, target)
Has-value: □ → (offset, type)
1 struct mbuf *
2 m_get(int nowait, int type)
3 {
4 struct mbuf *m;
5
6 if (nowait == M_NOWAIT && __VERIFIER_nondet_bool()) {
7 return (NULL);
8 }
9 m = malloc(sizeof(struct mbuf), 0, 0);
10
11 m->m_type = type;
12 m->m_next = NULL;
13 m->m_nextpkt = NULL;
14 m->m_data = m->m_dat;
15 m->m_flags = 0;
16
17 return (m);
18 }
Use of the __VERIFIER_nondet_ function in the Mbuf API
due to problems with multiple files
$ cat *.c > module.c
#ifndef CPA_bpfilter_h #define CPA_bpfilter_h 1 #include "bpfilter.h" #endif #ifndef CPA_pf_h #define CPA_pf_h 1 #include "pf.h" #endif ...
(not supported by CPAchecker)
#define _SYS_PERCPU_H_ #define COUNTERS_BOOT_MEMORY(_name, _n) #define COUNTERS_BOOT_INITIALIZER(_) ((void *)0)
due to a bug in the SMG CPA
psw = &inetsw[ip_protox[nxt]]; nxt = (*psw->pr_input)(mp, offp, nxt, af);
struct mutex m = { ((void *)0),
((((6)) > 0 && ((6)) < 12)? 12 : ((6))), 0}
extern u_char ip6_protox[]; u_char ip6_protox[256];
extern declarations in block Scope
memroy functions are not POSIX
Adjustments to the svcomp18--memory-safety configuration
Called from ip_deliver()
int ip6_etherip_input(...) {
...
1 if (!etherip_allow &&
(m->m_flags & (M_AUTH|M_CONF)) == 0) {
2 m_freem(m);
3 etheripstat.etherips_pdrops++;
4 - return IPPROTO_NONE;
5 + return IPPROTO_DONE;
6 }
...
1 int main() {
2 struct mbuf *m;
3 int len, off;
4
5 ip_init();
6 ip6_init();
7 m = m_gethdr(0, MT_HEADER);
8 m_tag_init(m);
9
10 len = __VERIFIER_nondet_int();
11 __VERIFIER_assume(len > 0);
12 __VERIFIER_assume(len <= MHLEN);
13 off = __VERIFIER_nondet_int();
14 __VERIFIER_assume(off > 0);
15 __VERIFIER_assume(off <= len);
16
17 m->m_hdr.mh_len = len;
18 m->M_dat.MH.MH_pkthdr.len = len;
19 ip_deliver(&m, &off, IPPROTO_IP, AF_INET6);
20 }
| Patch | Time | Max Memory | Result |
| 007_etherip | 314.712s | 2329MB | ✗ |
| 007_etherip (patched) | 313.433s | 2577MB | ✓ |
In total 11850 LOC
dot breaks at 65K characters on a labelDirk Beyer et al. "Software model checking via large-block encoding". FMCAD 2009. Dirk Beyer and M. Erkan Keremoglu. "CPAchecker: A Tool for Configurable Software Verification". CAV 2011. Dirk Beyer, Thomas A. Henzinger, and Grégory Théoduloz. "Configurable Software Verification: Concretizing the Convergence of Model Checking and Program Analysis". CAV 2007. Kamil Dudka, Petr Peringer, and Tomás Vojnar. "Byte-Precise Verification of Low-Level List Manipulation". Tech. rep. FIT-TR-2012-04.