forked from mirrors/linux
		
	md: don't use flush_signals in userspace processes
The function flush_signals clears all pending signals for the process. It may be used by kernel threads when we need to prepare a kernel thread for responding to signals. However using this function for an userspaces processes is incorrect - clearing signals without the program expecting it can cause misbehavior. The raid1 and raid5 code uses flush_signals in its request routine because it wants to prepare for an interruptible wait. This patch drops flush_signals and uses sigprocmask instead to block all signals (including SIGKILL) around the schedule() call. The signals are not lost, but the schedule() call won't respond to them. Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> Cc: stable@vger.kernel.org Acked-by: NeilBrown <neilb@suse.com> Signed-off-by: Shaohua Li <shli@fb.com>
This commit is contained in:
		
							parent
							
								
									cc27b0c78c
								
							
						
					
					
						commit
						f9c79bc05a
					
				
					 2 changed files with 8 additions and 2 deletions
				
			
		|  | @ -1334,7 +1334,7 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio, | |||
| 		 */ | ||||
| 		DEFINE_WAIT(w); | ||||
| 		for (;;) { | ||||
| 			flush_signals(current); | ||||
| 			sigset_t full, old; | ||||
| 			prepare_to_wait(&conf->wait_barrier, | ||||
| 					&w, TASK_INTERRUPTIBLE); | ||||
| 			if (bio_end_sector(bio) <= mddev->suspend_lo || | ||||
|  | @ -1344,7 +1344,10 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio, | |||
| 				     bio->bi_iter.bi_sector, | ||||
| 				     bio_end_sector(bio)))) | ||||
| 				break; | ||||
| 			sigfillset(&full); | ||||
| 			sigprocmask(SIG_BLOCK, &full, &old); | ||||
| 			schedule(); | ||||
| 			sigprocmask(SIG_SETMASK, &old, NULL); | ||||
| 		} | ||||
| 		finish_wait(&conf->wait_barrier, &w); | ||||
| 	} | ||||
|  |  | |||
|  | @ -5693,12 +5693,15 @@ static bool raid5_make_request(struct mddev *mddev, struct bio * bi) | |||
| 				 * userspace, we want an interruptible | ||||
| 				 * wait. | ||||
| 				 */ | ||||
| 				flush_signals(current); | ||||
| 				prepare_to_wait(&conf->wait_for_overlap, | ||||
| 						&w, TASK_INTERRUPTIBLE); | ||||
| 				if (logical_sector >= mddev->suspend_lo && | ||||
| 				    logical_sector < mddev->suspend_hi) { | ||||
| 					sigset_t full, old; | ||||
| 					sigfillset(&full); | ||||
| 					sigprocmask(SIG_BLOCK, &full, &old); | ||||
| 					schedule(); | ||||
| 					sigprocmask(SIG_SETMASK, &old, NULL); | ||||
| 					do_prepare = true; | ||||
| 				} | ||||
| 				goto retry; | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Mikulas Patocka
						Mikulas Patocka