We cannot restart cacheflush safely if a process provides user-defined signal handler and signal is pending. In this case -EINTR is returned and it is expected that process re-invokes syscall. However, there are a few problems with that: * looks like nobody bothers checking return value from cacheflush * but if it did, we don't provide the restart address for that, so the process has to use the same range again * ...and again, what might lead to looping forever So, remove cacheflush restarting code and terminate cache flushing as early as fatal signal is pending.
Unified · Split
| @@ -44,16 +44,6 @@ struct cpu_context_save { · 43 unmodified lines | |||
| 44 | __u32 extra[2]; /* Xscale 'acc' register, etc */ | 44 | __u32 extra[2]; /* Xscale 'acc' register, etc */ |
| 45 | }; | 45 | }; |
| 46 | 46 | ||
| 47 | struct arm_restart_block { | ||
| 48 | union { | ||
| 49 | /* For user cache flushing */ | ||
| 50 | struct { | ||
| 51 | unsigned long start; | ||
| 52 | unsigned long end; | ||
| 53 | } cache; | ||
| 54 | }; | ||
| 55 | }; | ||
| 56 | |||
| 57 | /* | 47 | /* |
| 58 | * low level task data that entry.S needs immediate access to. | 48 | * low level task data that entry.S needs immediate access to. |
| 59 | * __switch_to() assumes cpu_context follows immediately after cpu_domain. | 49 | * __switch_to() assumes cpu_context follows immediately after cpu_domain. |
| @@ -79,7 +69,6 @@ struct thread_info { · 19 unmodified lines | |||
| 79 | unsigned long thumbee_state; /* ThumbEE Handler Base register */ | 69 | unsigned long thumbee_state; /* ThumbEE Handler Base register */ |
| 80 | #endif | 70 | #endif |
| 81 | struct restart_block restart_block; | 71 | struct restart_block restart_block; |
| 82 | struct arm_restart_block arm_restart_block; | ||
| 83 | }; | 72 | }; |
| 84 | 73 | ||
| 85 | #define INIT_THREAD_INFO(tsk) \ | 74 | #define INIT_THREAD_INFO(tsk) \ |
| @@ -533,8 +533,6 @@ static int bad_syscall(int n, struct pt_regs *regs) · 532 unmodified lines | |||
| 533 | return regs->ARM_r0; | 533 | return regs->ARM_r0; |
| 534 | } | 534 | } |
| 535 | 535 | ||
| 536 | static long do_cache_op_restart(struct restart_block *); | ||
| 537 | |||
| 538 | static inline int | 536 | static inline int |
| 539 | __do_cache_op(unsigned long start, unsigned long end) | 537 | __do_cache_op(unsigned long start, unsigned long end) |
| 540 | { | 538 | { |
| @@ -543,24 +541,8 @@ __do_cache_op(unsigned long start, unsigned long end) · 2 unmodified lines | |||
| 543 | do { | 541 | do { |
| 544 | unsigned long chunk = min(PAGE_SIZE, end - start); | 542 | unsigned long chunk = min(PAGE_SIZE, end - start); |
| 545 | 543 | ||
| 546 | if (signal_pending(current)) { | 544 | if (fatal_signal_pending(current)) |
| 547 | struct thread_info *ti = current_thread_info(); | 545 | return 0; |
| 548 | |||
| 549 | ti->restart_block = (struct restart_block) { | ||
| 550 | .fn = do_cache_op_restart, | ||
| 551 | }; | ||
| 552 | |||
| 553 | ti->arm_restart_block = (struct arm_restart_block) { | ||
| 554 | { | ||
| 555 | .cache = { | ||
| 556 | .start = start, | ||
| 557 | .end = end, | ||
| 558 | }, | ||
| 559 | }, | ||
| 560 | }; | ||
| 561 | |||
| 562 | return -ERESTART_RESTARTBLOCK; | ||
| 563 | } | ||
| 564 | 546 | ||
| 565 | ret = flush_cache_user_range(start, start + chunk); | 547 | ret = flush_cache_user_range(start, start + chunk); |
| 566 | if (ret) | 548 | if (ret) |
| @@ -573,15 +555,6 @@ __do_cache_op(unsigned long start, unsigned long end) · 6 unmodified lines | |||
| 573 | return 0; | 555 | return 0; |
| 574 | } | 556 | } |
| 575 | 557 | ||
| 576 | static long do_cache_op_restart(struct restart_block *unused) | ||
| 577 | { | ||
| 578 | struct arm_restart_block *restart_block; | ||
| 579 | |||
| 580 | restart_block = ¤t_thread_info()->arm_restart_block; | ||
| 581 | return __do_cache_op(restart_block->cache.start, | ||
| 582 | restart_block->cache.end); | ||
| 583 | } | ||
| 584 | |||
| 585 | static inline int | 558 | static inline int |
| 586 | do_cache_op(unsigned long start, unsigned long end, int flags) | 559 | do_cache_op(unsigned long start, unsigned long end, int flags) |
| 587 | { | 560 | { |