[OLPC Security] Securing the laptop: DoS

John Moser john.r.moser at gmail.com
Sun Oct 8 03:11:07 EDT 2006


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1



Simson Garfinkel wrote:
> 
> On Oct 7, 2006, at 11:17 PM, John Moser wrote:
> 
>> -----BEGIN PGP SIGNED MESSAGE-----
>> Hash: SHA1
>>
>>
>>
>> Simson L. Garfinkel wrote:
>>> This is pretty easy to defeat: just bust the cache so that the system
>>> doesn't know the difference between data that's going to be overwritten
>>> and data that isn't.

> What if the malware creates 1000 files, each one 256K in size, then
> starts to delete the files from the beginning? By the time the malware
> has gotten to the end of the first 1000 files, they have been flushed
> from the cache to memory. The system just doesn't have enough buffer, if
> you assume that the flash is bigger than RAM. If the flash is smaller
> than RAM, then this isn't a problem.

It still has to write 256,000 kilobytes of stuff to the files, if you
assume the cache is smart enough to handle files sparsely.  Granted,
this may not be as big a problem as one would hope.

(Caveat:  It has to actually touch different places of memory, far less
than 256,000 places, just enough single bytes to get different blocks
written to disk; however, jffs2 does compression, so this is not a 1:1
problem.  Still, by crafting the file so that your single byte writes
fall into data that doesn't compress well...)

I did not consider this case; although you can still make it a matter of
writing to the files rather than create-delete by handling the files
sparsely in cache.

You can probably write around randomly and fill up cache still, but
sparse cache could entail some sort of structure...

chunk_struct {
	int	len;
	char	*data;
};

struct chunk_struct chunk;
chunk = allocate(sizeof(chunk_struct) + lengthof(write));
chunk->len = lengthof(write);
chunk->data = (char*)(chunk + 1); // 1 chunk_struct past
memcpy(chunk->data, write, lengthof(write));

Again, this kind of behavior is unlikely to actually exist; I'm just
spouting "what could possibly be done."  And you may have a
counter-example, although the immediate obvious counter-example is to
create and delete files and actually write a bunch of data to them to
flood the cache.  I would like to note that memcpy() is memory bound, so
this will slow down the process; by how much I can't tell you, I could
measure it though to see if it's significant.  Tomorrow, it's like 3am.


> 
>>
>> My thinking is that to beat this, you have to create a very big file or
>> a large set of files, and write over them in a bunch of different places
>> a lot, to scatter writes in different sectors so that the NAND has to
>> erase/program those sectors.  You won't fill the cache with dirty just
>> by writing to the same place a lot of times.
> 
> If you write in the same place, JFFS2 spreads it out to different
> places. So it doesn't matter if you are writing to the same file or
> writing to different files; JFFS2 makes all of the sectors age together.
> 

Yes, but in the context of cache in memory, you have to write to a lot
of places to fill it up.  Further, if you get a single sector flushed a
bunch of times, wear leveling will work at maximum efficiency.  If you
get a bunch of scattered sectors to flush continuously, then wear
leveling will level the damage; but it will level it to multiple sectors
at once.  So instead of every flush damaging 1 64K block, every flush
damages 300 64K blocks.

In theory if the data is scattered enough, a flush will have every
sector in the NAND to write to, and wear leveling is nullified; this
won't happen because memory is limited.  (the above sparse caching
discussion would allow this, but you'd have to actually write enough
data to fill up cache, and would push data out iteratively anyway except
on flushes where all the sparse data would be written back in one swing.
 Plus compression might come into play.)

>>
>> Essentially, if there's room for 60 megs of cache, you have to write 60
>> megs of data minus whatever else is legitimately cached and likely to
>> stay there through the attack.  While the system is writing cache back
>> to disk, the attacking program is probably going to be blocked by
>> write(), because the kernel has nowhere to put the extra data.
>>
>>> Hell, use a PNG so that the system can't tell the difference.
>>
>> PNG??  Image?  Can't tell the difference between what and what?
> 
> Pseudorandom Number Generator. The system can't tell the difference
> between random user data and malicious program data.
> 

Obviously; the system isn't analyzing the data to detect malware
activity.  You could write all zeroes if it weren't for compression. A
PRNG would get you data that's particularly useful because jffs2 won't
compress it great.

> 
> 
> 
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.3 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iQIVAwUBRSikiQs1xW0HCTEFAQLzLA//bc/D1YQJCftCEIfvfzQFz50YBtJmavkZ
0yd0+K9PRoXXMJBJORWbxGw7++MYwgmHm/wRyYFRKdHuFfesTUs5SsLDdNlLWEc+
X6zZDlNKkrYIg2nN8w8ryD0/RzXOcoaVklNdKniryYNUjy2QBHqMdZhCSFzH+yeH
XeuyBAxVhU1WyVQ2/BMrjAJjyOxpYD6ZiZwIKcG8nBIBcBbqrse5fiQlFqTY0Y3C
wp4AcqqSdz+V6t8ru6B4QGjlNRo7vTYDRzMVvhr+L+seHNEzB7faYlLORDhZ0Fto
q3pZzp+G+s8Raw+uKPCgam47r2wncUJKIlPg/2bX4M3L1TN6/bxcbb4nl5TnfS2c
BXKwDi9Y68WXoWR3Sr3Zsu6zbmnbPbTm/K3eJPgCRDCjx8MZeCkist2jdPwEMMRD
KREChxMjnhxYtBbUSRqtOc5/pyM20OF3D9k69nf3/ZYg9zq53IpVYtBsOb+6cFT3
+gsXTSzTIlwJtbs/C/UpDzYv6+TU8TOrh/ub+E4sm5lVUA5G9BePg7lyzzZWa1R2
xZi7sP/P25vtWD99rCAJs9yLjMj88dVPVQbQpBReHkZgYl0HflLqJdsFdiGrj4/p
y+LhIKMQ51W2sfG05d5BYEyBQzAlriylP7KW/cQSz/ikKu1Cza/s9rbTaSq4sqK9
YKCkV6+Szd4=
=H4DB
-----END PGP SIGNATURE-----


More information about the Security mailing list