Efficient Memory Safety for TinyOS David Gay John Regehr

advertisement
Efficient Memory Safety for TinyOS
Nathan Cooprider Will Archer Eric Eide
David Gay† John Regehr
University of Utah
School of Computing
†Intel
Research
Berkeley
1
Suppose we have a WSN…
●
What happened?
–
–
State got corrupted
Hard to debug
●
●
Limited visibility into executing systems
Difficult to replicate complex bugs
2
Goal
●
Catch all pointer and array bounds errors
–
●
●
Before they corrupt state
Provide a choice of recovery action
Put WSN software development on a solid
foundation
3
Our contribution: Safe TinyOS
Expand
• Modify TinyOS to work
with Deputy
Enforce Deputy’s safety
Deputy: Practical• for
model under concurrency
deployment
existing solution
• Reduce overhead
for making C safe
into system safety
– 5.2% duty cycle increase
– 13% code size increase
4
Example builds
$ make mica2
$ make mica2 safe
$ make mica2 safe optimize
5
Language safety
Language
safety
System
safety
Deputy Our work Safe TinyOS
●
Deputy is the starting point
–
–
–
Safe C dialect developed at Berkeley
Annotations exploit values present in code to
specify bounds/etc information
Translates a C program into a safe C program
by inserting safety checks
6
Annotations in nesC
Example interface
from TinyOS 2
/* Buffered high data rate reading, usually from sensor devices */
interface ReadStream<val_t> {
command error_t postBuffer(val_t* buf, uint16_t n);
command error_t read(uint32_t usPeriod);
event void bufferDone(error_t result,
val_t* buf, uint16_t n);
event void readDone(error_t result, uint32_t usActualPeriod);
}
7
Annotations in nesC
COUNT  Either
null or array
/* Buffered high data rate reading, usually from sensor devices */
interface ReadStream<val_t> {
command error_t postBuffer(val_t* COUNT(n) buf, uint16_t n);
command error_t read(uint32_t usPeriod);
event void bufferDone(error_t result,
val_t* COUNT(n) buf, uint16_t n);
event void readDone(error_t result, uint32_t usActualPeriod);
}
8
Few lines changed
●
253 nesC files
–
●
16/2541 or 0.63%
Application lines
26,022 loc
133/20455 or 0.65%
TinyOS Component lines
0.74% changed
–
1 in 135 lines
23%
8%
44/3026 or 1.5%
TinyOS Interface lines
Applications
TinyOS Components
TinyOS Interfaces
69%
9
run modified
nesC compiler
enforce safety
using Deputy
deal with
concurrency
●
●
Atomic block
Concurrency
Deputy enforces safety
in sequential code
Static analysis to avoid
extraneous protection
–
Potentially
unsafe read
to local
Interrupt
Deputy check
Potentially
Read local )
If ( unsafe
read
Few actually need protection
10
Compress error messages
run modified
nesC compiler
●
–
enforce safety
using Deputy
–
●
deal with
concurrency
compress
error messages
0x0773
Deputy’s verbose messages
Use precious memory
No screen on the mote
Replaced with integer ID
–
–
Fault location identifiers, FLIDs
FLIDs blinked on LEDs or sent
to network
tos/chips/cc2420/CC2420ReceiveP.nc:
241:
decode CC2420ReceiveP$receiveDone_task$runTask:
Assertion failed in upper bound coercion:
FLID
CC2420ReceiveP$m_p_rx_buf->data + length <=
CC2420ReceiveP$m_p_rx_buf + 28
11
Code improvements
run modified
nesC compiler
●
Dataflow analysis
–
–
enforce safety
using Deputy
–
Interprocedural and whole-program
Simultaneous pointer analysis
Handles concurrent programs
●
deal with
concurrency
compress
error messages
whole-program
optimization
●
Propagate data through globals
More aggressive than gcc is, or
can be:
–
Inlining
–
Dead code elimination
–
Value propagation
–
Synchronization removal
12
Safe TinyOS toolchain
run modified
nesC compiler
enforce safety
using Deputy
deal with
concurrency
compress
error messages
Safe
whole-program
optimization
TinyOS
app
TinyOS
code
Annotate
Safe
TinyOS
code
Modify TinyOS to work
with Deputy
Enforce Deputy’s safety
model under
concurrency
Reduce overhead
13
Resource usage
●
Six TinyOS 2 benchmarks
–
●
No RAM usage increase
–
–
●
3,561 to 25,773 lines of C code
Deputy exploits existing bounds info.
Optimizer saves a little RAM
Duty cycle obtained with Avrora simulator
–
Duty cycle = % of time processor is on
14
Code size
15
Code size
35%
13%
-11%
16
Duty cycle
24%
5.2%
-9.7%
17
On to bug hunting
●
●
●
Ran Safe TinyOS applications on motes
Found four bugs
Will talk about three of them
18
A bug
Buffer length
Safety violation
Serial
caught by
Dispatcher
Safe TinyOS
●
Serial stack – passed in a buffer
–
●
●
Passes along one byte at a time
Problem: given buffer length too large
Out-of-bounds index for buffer
19
Another bug
●
Active Message Queue
–
●
●
Queue moves on to next
client on send done event
With no clients
–
–
●
Scheduling of network link
Spurious report of
completion
Invalid array index
Difficult to replicate
–
Several minutes, many nodes
Send
Send
Send
done
done
done
0
3
2
1
Current
Safety violation
caught by
Safe TinyOS
20
Yet another bug
for (i = 0; i < NUM_BUFFERS; i++) {
if (m_pool[i].msg == NULL) break;
}
i can point to one past end of buffer
if (m_pool[i].msg == NULL) {
m_pool[i].msg = _msg;
}
●
●
●
Time synchronization and leader election
Upon discovery
Array out-of-bounds
access
Difficult
to locate
Bug already
fixed in latest release
– After 20
of minutes
third-party component
–
In “third-party” networking code
21
Increased availability
Array
Out-of-bounds
Normal
TinyOS
Array
Out-of-bounds
Safe
TinyOS
Normal TinyOS:
0% average
availability
Safe TinyOS:
95% average
availability
Rebuild
Soft state
Reboot
22
Conclusion
●
Type and memory safety is practical for
tiny embedded systems
–
–
–
Safety for entire system
Low run-time cost compared to original unsafe
applications
Can easily fit into existing programming
practice
We plan to make it available soon…
23
Download