mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	[PATCH] replace cad_pid by a struct pid
There are a few places in the kernel where the init task is signaled. The ctrl+alt+del sequence is one them. It kills a task, usually init, using a cached pid (cad_pid). This patch replaces the pid_t by a struct pid to avoid pid wrap around problem. The struct pid is initialized at boot time in init() and can be modified through systctl with /proc/sys/kernel/cad_pid [ I haven't found any distro using it ? ] It also introduces a small helper routine kill_cad_pid() which is used where it seemed ok to use cad_pid instead of pid 1. [akpm@osdl.org: cleanups, build fix] Signed-off-by: Cedric Le Goater <clg@fr.ibm.com> Cc: Eric W. Biederman <ebiederm@xmission.com> Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> Cc: Paul Mackerras <paulus@samba.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
		
							parent
							
								
									1a657f78dc
								
							
						
					
					
						commit
						9ec52099e4
					
				
					 11 changed files with 48 additions and 16 deletions
				
			
		| 
						 | 
				
			
			@ -123,7 +123,8 @@ static inline void power_button(void)
 | 
			
		|||
	if (machine_state & MACHINE_PANICED)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	if ((machine_state & MACHINE_SHUTTING_DOWN) || kill_proc(1,SIGINT,1)) {
 | 
			
		||||
	if ((machine_state & MACHINE_SHUTTING_DOWN) ||
 | 
			
		||||
			kill_cad_pid(SIGINT, 1)) {
 | 
			
		||||
		/* No init process or button pressed twice.  */
 | 
			
		||||
		sgi_machine_power_off();
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -120,7 +120,7 @@ static inline void ip32_power_button(void)
 | 
			
		|||
	if (has_panicked)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	if (shuting_down || kill_proc(1, SIGINT, 1)) {
 | 
			
		||||
	if (shuting_down || kill_cad_pid(SIGINT, 1)) {
 | 
			
		||||
		/* No init process or button pressed twice.  */
 | 
			
		||||
		ip32_machine_power_off();
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -357,7 +357,7 @@ static int dma_and_signal_ce_msg(char *ce_msg,
 | 
			
		|||
 */
 | 
			
		||||
static int shutdown(void)
 | 
			
		||||
{
 | 
			
		||||
	int rc = kill_proc(1, SIGINT, 1);
 | 
			
		||||
	int rc = kill_cad_pid(SIGINT, 1);
 | 
			
		||||
 | 
			
		||||
	if (rc) {
 | 
			
		||||
		printk(KERN_ALERT "mf.c: SIGINT to init failed (%d), "
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -127,9 +127,8 @@ static void button_consume_callbacks (int bpcount)
 | 
			
		|||
static void button_sequence_finished (unsigned long parameters)
 | 
			
		||||
{
 | 
			
		||||
#ifdef CONFIG_NWBUTTON_REBOOT		/* Reboot using button is enabled */
 | 
			
		||||
	if (button_press_count == reboot_count) {
 | 
			
		||||
		kill_proc (1, SIGINT, 1);	/* Ask init to reboot us */
 | 
			
		||||
	}
 | 
			
		||||
	if (button_press_count == reboot_count)
 | 
			
		||||
		kill_cad_pid(SIGINT, 1);	/* Ask init to reboot us */
 | 
			
		||||
#endif /* CONFIG_NWBUTTON_REBOOT */
 | 
			
		||||
	button_consume_callbacks (button_press_count);
 | 
			
		||||
	bcount = sprintf (button_output_buffer, "%d\n", button_press_count);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -220,7 +220,7 @@ scdrv_dispatch_event(char *event, int len)
 | 
			
		|||
			       " Sending SIGPWR to init...\n");
 | 
			
		||||
 | 
			
		||||
		/* give a SIGPWR signal to init proc */
 | 
			
		||||
		kill_proc(1, SIGPWR, 0);
 | 
			
		||||
		kill_cad_pid(SIGPWR, 0);
 | 
			
		||||
	} else {
 | 
			
		||||
		/* print to system log */
 | 
			
		||||
		printk("%s|$(0x%x)%s\n", severity, esp_code, desc);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -84,8 +84,7 @@
 | 
			
		|||
 | 
			
		||||
static void deferred_poweroff(void *dummy)
 | 
			
		||||
{
 | 
			
		||||
	extern int cad_pid;	/* from kernel/sys.c */
 | 
			
		||||
	if (kill_proc(cad_pid, SIGINT, 1)) {
 | 
			
		||||
	if (kill_cad_pid(SIGINT, 1)) {
 | 
			
		||||
		/* just in case killing init process failed */
 | 
			
		||||
		machine_power_off();
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -208,7 +208,7 @@ s390_handle_mcck(void)
 | 
			
		|||
		 */
 | 
			
		||||
		__ctl_clear_bit(14, 24);	/* Disable WARNING MCH */
 | 
			
		||||
		if (xchg(&mchchk_wng_posted, 1) == 0)
 | 
			
		||||
			kill_proc(1, SIGPWR, 1);
 | 
			
		||||
			kill_cad_pid(SIGPWR, 1);
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1065,6 +1065,8 @@ static inline int is_init(struct task_struct *tsk)
 | 
			
		|||
	return tsk->pid == 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern struct pid *cad_pid;
 | 
			
		||||
 | 
			
		||||
extern void free_task(struct task_struct *tsk);
 | 
			
		||||
#define get_task_struct(tsk) do { atomic_inc(&(tsk)->usage); } while(0)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1292,6 +1294,11 @@ extern int send_group_sigqueue(int, struct sigqueue *,  struct task_struct *);
 | 
			
		|||
extern int do_sigaction(int, struct k_sigaction *, struct k_sigaction *);
 | 
			
		||||
extern int do_sigaltstack(const stack_t __user *, stack_t __user *, unsigned long);
 | 
			
		||||
 | 
			
		||||
static inline int kill_cad_pid(int sig, int priv)
 | 
			
		||||
{
 | 
			
		||||
	return kill_pid(cad_pid, sig, priv);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* These can be the second arg to send_sig_info/send_group_sig_info.  */
 | 
			
		||||
#define SEND_SIG_NOINFO ((struct siginfo *) 0)
 | 
			
		||||
#define SEND_SIG_PRIV	((struct siginfo *) 1)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -721,6 +721,8 @@ static int init(void * unused)
 | 
			
		|||
	 */
 | 
			
		||||
	child_reaper = current;
 | 
			
		||||
 | 
			
		||||
	cad_pid = task_pid(current);
 | 
			
		||||
 | 
			
		||||
	smp_prepare_cpus(max_cpus);
 | 
			
		||||
 | 
			
		||||
	do_pre_smp_initcalls();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -92,7 +92,8 @@ EXPORT_SYMBOL(fs_overflowgid);
 | 
			
		|||
 */
 | 
			
		||||
 | 
			
		||||
int C_A_D = 1;
 | 
			
		||||
int cad_pid = 1;
 | 
			
		||||
struct pid *cad_pid;
 | 
			
		||||
EXPORT_SYMBOL(cad_pid);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 *	Notifier list for kernel code which wants to be called
 | 
			
		||||
| 
						 | 
				
			
			@ -773,10 +774,9 @@ void ctrl_alt_del(void)
 | 
			
		|||
	if (C_A_D)
 | 
			
		||||
		schedule_work(&cad_work);
 | 
			
		||||
	else
 | 
			
		||||
		kill_proc(cad_pid, SIGINT, 1);
 | 
			
		||||
		kill_cad_pid(SIGINT, 1);
 | 
			
		||||
}
 | 
			
		||||
	
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Unprivileged users may change the real gid to the effective gid
 | 
			
		||||
 * or vice versa.  (BSD-style)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -68,7 +68,6 @@ extern int sysrq_enabled;
 | 
			
		|||
extern int core_uses_pid;
 | 
			
		||||
extern int suid_dumpable;
 | 
			
		||||
extern char core_pattern[];
 | 
			
		||||
extern int cad_pid;
 | 
			
		||||
extern int pid_max;
 | 
			
		||||
extern int min_free_kbytes;
 | 
			
		||||
extern int printk_ratelimit_jiffies;
 | 
			
		||||
| 
						 | 
				
			
			@ -137,6 +136,9 @@ static int parse_table(int __user *, int, void __user *, size_t __user *,
 | 
			
		|||
static int proc_do_uts_string(ctl_table *table, int write, struct file *filp,
 | 
			
		||||
		  void __user *buffer, size_t *lenp, loff_t *ppos);
 | 
			
		||||
 | 
			
		||||
static int proc_do_cad_pid(ctl_table *table, int write, struct file *filp,
 | 
			
		||||
		  void __user *buffer, size_t *lenp, loff_t *ppos);
 | 
			
		||||
 | 
			
		||||
static ctl_table root_table[];
 | 
			
		||||
static struct ctl_table_header root_table_header =
 | 
			
		||||
	{ root_table, LIST_HEAD_INIT(root_table_header.ctl_entry) };
 | 
			
		||||
| 
						 | 
				
			
			@ -543,10 +545,10 @@ static ctl_table kern_table[] = {
 | 
			
		|||
	{
 | 
			
		||||
		.ctl_name	= KERN_CADPID,
 | 
			
		||||
		.procname	= "cad_pid",
 | 
			
		||||
		.data		= &cad_pid,
 | 
			
		||||
		.data		= NULL,
 | 
			
		||||
		.maxlen		= sizeof (int),
 | 
			
		||||
		.mode		= 0600,
 | 
			
		||||
		.proc_handler	= &proc_dointvec,
 | 
			
		||||
		.proc_handler	= &proc_do_cad_pid,
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		.ctl_name	= KERN_MAX_THREADS,
 | 
			
		||||
| 
						 | 
				
			
			@ -2427,6 +2429,28 @@ static int proc_do_ipc_string(ctl_table *table, int write, struct file *filp,
 | 
			
		|||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static int proc_do_cad_pid(ctl_table *table, int write, struct file *filp,
 | 
			
		||||
			   void __user *buffer, size_t *lenp, loff_t *ppos)
 | 
			
		||||
{
 | 
			
		||||
	struct pid *new_pid;
 | 
			
		||||
	pid_t tmp;
 | 
			
		||||
	int r;
 | 
			
		||||
 | 
			
		||||
	tmp = pid_nr(cad_pid);
 | 
			
		||||
 | 
			
		||||
	r = __do_proc_dointvec(&tmp, table, write, filp, buffer,
 | 
			
		||||
			       lenp, ppos, NULL, NULL);
 | 
			
		||||
	if (r || !write)
 | 
			
		||||
		return r;
 | 
			
		||||
 | 
			
		||||
	new_pid = find_get_pid(tmp);
 | 
			
		||||
	if (!new_pid)
 | 
			
		||||
		return -ESRCH;
 | 
			
		||||
 | 
			
		||||
	put_pid(xchg(&cad_pid, new_pid));
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#else /* CONFIG_PROC_FS */
 | 
			
		||||
 | 
			
		||||
int proc_dostring(ctl_table *table, int write, struct file *filp,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue