diff options
author | Adrian Hunter <ext-adrian.hunter@nokia.com> | 2008-10-17 09:52:10 -0400 |
---|---|---|
committer | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2008-10-19 06:01:21 -0400 |
commit | 727d2dc045930b29dc68d56d5032d23661ba8503 (patch) | |
tree | 66fc9a3dccd7639acf47774274f3b69a888caeb8 /fs/ubifs | |
parent | be2f6bd62d0d4246a9227dacbe2469e1f0eccf26 (diff) |
UBIFS: do not read unnecessary bytes when unpacking bits
Fixes the following Oops:
BUG: unable to handle kernel paging request at f8d24000
IP: [<f8ff0657>] :ubifs:ubifs_unpack_bits+0xcd/0x231
*pde = 34333067 *pte = 00000000
Oops: 0000 [#1] PREEMPT SMP
Modules linked in: deflate zlib_deflate lzo lzo_decompress lzo_compress
ubifs ubi nandsim nand nand_ids nand_ecc mtd nfsd lockd sunrpc exportfs
[last unloaded: nand_ecc]
Pid: 7450, comm: sync Not tainted (2.6.27-rc8-ubifs-2.6 #27)
EIP: 0060:[<f8ff0657>] EFLAGS: 00010206 CPU: 0
EIP is at ubifs_unpack_bits+0xcd/0x231 [ubifs]
EAX: 00000000 EBX: 00000000 ECX: d7e43dc0 EDX: 0000ff00
ESI: 00000004 EDI: f8d23ffe EBP: d7e43db4 ESP: d7e43d8c
DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068
Process sync (pid: 7450, ti=d7e42000 task=eb6f9530 task.ti=d7e42000)
Stack: 00000400 c0103db4 dc5e8090 d7e43dc0 d7e43dc0 d7e43dc4 0000001c 00000004
f496d1e0 f8d23ffc d7e43dd4 f8ffac7e f8d23ffe 00000000 f8d23ffe f2b7af68
f496d1e0 f8d23ffc d7e43e2c f8ffadc5 00000000 0001f000 00000000 c03b10a7
Call Trace:
[<c0103db4>] ? restore_nocheck_notrace+0x0/0xe
[<f8ffac7e>] ? is_a_node+0x43/0x92 [ubifs]
[<f8ffadc5>] ? dbg_check_ltab+0xf8/0x5c9 [ubifs]
[<c03b10a7>] ? mutex_lock_nested+0x1b2/0x2a0
[<f8ffc86e>] ? ubifs_lpt_start_commit+0x49/0xecb [ubifs]
[<c03b0ef3>] ? mutex_unlock+0xd/0xf
[<f8fef017>] ? ubifs_tnc_start_commit+0x1cf/0xef8 [ubifs]
[<f8fe65d8>] ? do_commit+0x18f/0x52d [ubifs]
[<f8fe69f6>] ? ubifs_run_commit+0x80/0xca [ubifs]
[<f8fd8d35>] ? ubifs_sync_fs+0xdb/0xf6 [ubifs]
[<c0181a07>] ? sync_filesystems+0xc6/0x10c
[<c019f279>] ? do_sync+0x3b/0x6a
[<c019f2ba>] ? sys_sync+0x12/0x18
[<c0103ced>] ? sysenter_do_call+0x12/0x35
=======================
Code: 4d ec 89 01 8b 45 e8 89 10 89 d8 89 f1 d3 e8 85 c0 74 07 29 d6 83 fe
20 75 2a 89 d8 83 c4 1c 5b 5e 5f 5d c3 0f b6 57 01 c1 e2 08 <0f> b6 47 02
c1 e0 10 09 c2 0f b6 07 09 c2 0f b
EIP: [<f8ff0657>] ubifs_unpack_bits+0xcd/0x231 [ubifs] SS:ESP 0068:d7e43d8c
---[ end trace 1bbb4c407a6dd816 ]---
Signed-off-by: Adrian Hunter <ext-adrian.hunter@nokia.com>
Diffstat (limited to 'fs/ubifs')
-rw-r--r-- | fs/ubifs/lpt.c | 45 |
1 files changed, 38 insertions, 7 deletions
diff --git a/fs/ubifs/lpt.c b/fs/ubifs/lpt.c index cd11b23a1875..db8bd0e518b2 100644 --- a/fs/ubifs/lpt.c +++ b/fs/ubifs/lpt.c | |||
@@ -288,25 +288,56 @@ uint32_t ubifs_unpack_bits(uint8_t **addr, int *pos, int nrbits) | |||
288 | const int k = 32 - nrbits; | 288 | const int k = 32 - nrbits; |
289 | uint8_t *p = *addr; | 289 | uint8_t *p = *addr; |
290 | int b = *pos; | 290 | int b = *pos; |
291 | uint32_t val; | 291 | uint32_t uninitialized_var(val); |
292 | const int bytes = (nrbits + b + 7) >> 3; | ||
292 | 293 | ||
293 | ubifs_assert(nrbits > 0); | 294 | ubifs_assert(nrbits > 0); |
294 | ubifs_assert(nrbits <= 32); | 295 | ubifs_assert(nrbits <= 32); |
295 | ubifs_assert(*pos >= 0); | 296 | ubifs_assert(*pos >= 0); |
296 | ubifs_assert(*pos < 8); | 297 | ubifs_assert(*pos < 8); |
297 | if (b) { | 298 | if (b) { |
298 | val = p[1] | ((uint32_t)p[2] << 8) | ((uint32_t)p[3] << 16) | | 299 | switch (bytes) { |
299 | ((uint32_t)p[4] << 24); | 300 | case 2: |
301 | val = p[1]; | ||
302 | break; | ||
303 | case 3: | ||
304 | val = p[1] | ((uint32_t)p[2] << 8); | ||
305 | break; | ||
306 | case 4: | ||
307 | val = p[1] | ((uint32_t)p[2] << 8) | | ||
308 | ((uint32_t)p[3] << 16); | ||
309 | break; | ||
310 | case 5: | ||
311 | val = p[1] | ((uint32_t)p[2] << 8) | | ||
312 | ((uint32_t)p[3] << 16) | | ||
313 | ((uint32_t)p[4] << 24); | ||
314 | } | ||
300 | val <<= (8 - b); | 315 | val <<= (8 - b); |
301 | val |= *p >> b; | 316 | val |= *p >> b; |
302 | nrbits += b; | 317 | nrbits += b; |
303 | } else | 318 | } else { |
304 | val = p[0] | ((uint32_t)p[1] << 8) | ((uint32_t)p[2] << 16) | | 319 | switch (bytes) { |
305 | ((uint32_t)p[3] << 24); | 320 | case 1: |
321 | val = p[0]; | ||
322 | break; | ||
323 | case 2: | ||
324 | val = p[0] | ((uint32_t)p[1] << 8); | ||
325 | break; | ||
326 | case 3: | ||
327 | val = p[0] | ((uint32_t)p[1] << 8) | | ||
328 | ((uint32_t)p[2] << 16); | ||
329 | break; | ||
330 | case 4: | ||
331 | val = p[0] | ((uint32_t)p[1] << 8) | | ||
332 | ((uint32_t)p[2] << 16) | | ||
333 | ((uint32_t)p[3] << 24); | ||
334 | break; | ||
335 | } | ||
336 | } | ||
306 | val <<= k; | 337 | val <<= k; |
307 | val >>= k; | 338 | val >>= k; |
308 | b = nrbits & 7; | 339 | b = nrbits & 7; |
309 | p += nrbits / 8; | 340 | p += nrbits >> 3; |
310 | *addr = p; | 341 | *addr = p; |
311 | *pos = b; | 342 | *pos = b; |
312 | ubifs_assert((val >> nrbits) == 0 || nrbits - b == 32); | 343 | ubifs_assert((val >> nrbits) == 0 || nrbits - b == 32); |