mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	core_pattern: allow passing of arguments to user mode helper when core_pattern is a pipe
A rewrite of my previous post for this enhancement. It uses jeremy's split_argv/free_argv library functions to translate core_pattern into an argv array to be passed to the user mode helper process. It also adds a translation to format_corename such that the origional value of RLIMIT_CORE can be passed to userspace as an argument. Signed-off-by: Neil Horman <nhorman@tuxdriver.com> Cc: <martin.pitt@ubuntu.com> Cc: <wwoods@redhat.com> Cc: Jeremy Fitzhardinge <jeremy@goop.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
		
							parent
							
								
									7dc0b22e3c
								
							
						
					
					
						commit
						74aadce986
					
				
					 1 changed files with 22 additions and 3 deletions
				
			
		
							
								
								
									
										25
									
								
								fs/exec.c
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								fs/exec.c
									
									
									
									
									
								
							| 
						 | 
					@ -29,6 +29,7 @@
 | 
				
			||||||
#include <linux/stat.h>
 | 
					#include <linux/stat.h>
 | 
				
			||||||
#include <linux/fcntl.h>
 | 
					#include <linux/fcntl.h>
 | 
				
			||||||
#include <linux/smp_lock.h>
 | 
					#include <linux/smp_lock.h>
 | 
				
			||||||
 | 
					#include <linux/string.h>
 | 
				
			||||||
#include <linux/init.h>
 | 
					#include <linux/init.h>
 | 
				
			||||||
#include <linux/pagemap.h>
 | 
					#include <linux/pagemap.h>
 | 
				
			||||||
#include <linux/highmem.h>
 | 
					#include <linux/highmem.h>
 | 
				
			||||||
| 
						 | 
					@ -1514,6 +1515,14 @@ static int format_corename(char *corename, const char *pattern, long signr)
 | 
				
			||||||
					goto out;
 | 
										goto out;
 | 
				
			||||||
				out_ptr += rc;
 | 
									out_ptr += rc;
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
 | 
								/* core limit size */
 | 
				
			||||||
 | 
								case 'c':
 | 
				
			||||||
 | 
									rc = snprintf(out_ptr, out_end - out_ptr,
 | 
				
			||||||
 | 
										      "%lu", current->signal->rlim[RLIMIT_CORE].rlim_cur);
 | 
				
			||||||
 | 
									if (rc > out_end - out_ptr)
 | 
				
			||||||
 | 
										goto out;
 | 
				
			||||||
 | 
									out_ptr += rc;
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
			default:
 | 
								default:
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					@ -1698,6 +1707,9 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
 | 
				
			||||||
	int flag = 0;
 | 
						int flag = 0;
 | 
				
			||||||
	int ispipe = 0;
 | 
						int ispipe = 0;
 | 
				
			||||||
	unsigned long core_limit = current->signal->rlim[RLIMIT_CORE].rlim_cur;
 | 
						unsigned long core_limit = current->signal->rlim[RLIMIT_CORE].rlim_cur;
 | 
				
			||||||
 | 
						char **helper_argv = NULL;
 | 
				
			||||||
 | 
						int helper_argc = 0;
 | 
				
			||||||
 | 
						char *delimit;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	audit_core_dumps(signr);
 | 
						audit_core_dumps(signr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1746,14 +1758,18 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
 | 
				
			||||||
	 * at which point file size limits and permissions will be imposed
 | 
						 * at which point file size limits and permissions will be imposed
 | 
				
			||||||
	 * as it does with any other process
 | 
						 * as it does with any other process
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	if ((!ispipe) &&
 | 
						if ((!ispipe) && (core_limit < binfmt->min_coredump))
 | 
				
			||||||
	   (core_limit < binfmt->min_coredump))
 | 
					 | 
				
			||||||
		goto fail_unlock;
 | 
							goto fail_unlock;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 	if (ispipe) {
 | 
					 	if (ispipe) {
 | 
				
			||||||
		core_limit = RLIM_INFINITY;
 | 
							core_limit = RLIM_INFINITY;
 | 
				
			||||||
 | 
							helper_argv = argv_split(GFP_KERNEL, corename+1, &helper_argc);
 | 
				
			||||||
 | 
							/* Terminate the string before the first option */
 | 
				
			||||||
 | 
							delimit = strchr(corename, ' ');
 | 
				
			||||||
 | 
							if (delimit)
 | 
				
			||||||
 | 
								*delimit = '\0';
 | 
				
			||||||
		/* SIGPIPE can happen, but it's just never processed */
 | 
							/* SIGPIPE can happen, but it's just never processed */
 | 
				
			||||||
 		if(call_usermodehelper_pipe(corename+1, NULL, NULL, &file)) {
 | 
					 		if(call_usermodehelper_pipe(corename+1, helper_argv, NULL, &file)) {
 | 
				
			||||||
 			printk(KERN_INFO "Core dump to %s pipe failed\n",
 | 
					 			printk(KERN_INFO "Core dump to %s pipe failed\n",
 | 
				
			||||||
			       corename);
 | 
								       corename);
 | 
				
			||||||
 			goto fail_unlock;
 | 
					 			goto fail_unlock;
 | 
				
			||||||
| 
						 | 
					@ -1788,6 +1804,9 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs)
 | 
				
			||||||
close_fail:
 | 
					close_fail:
 | 
				
			||||||
	filp_close(file, NULL);
 | 
						filp_close(file, NULL);
 | 
				
			||||||
fail_unlock:
 | 
					fail_unlock:
 | 
				
			||||||
 | 
						if (helper_argv)
 | 
				
			||||||
 | 
							argv_free(helper_argv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	current->fsuid = fsuid;
 | 
						current->fsuid = fsuid;
 | 
				
			||||||
	complete_all(&mm->core_done);
 | 
						complete_all(&mm->core_done);
 | 
				
			||||||
fail:
 | 
					fail:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue