diff options
author | Cedric Le Goater <clg@fr.ibm.com> | 2006-10-02 05:19:00 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-10-02 10:57:25 -0400 |
commit | 9ec52099e4b8678a60e9f93e41ad87885d64f3e6 (patch) | |
tree | a68fe051b39f8f8e8be469cbd3c2f653b9b71a9d | |
parent | 1a657f78dcc8ea7c53eaa1f2a45ea2315738c15f (diff) |
[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>
-rw-r--r-- | arch/mips/sgi-ip22/ip22-reset.c | 3 | ||||
-rw-r--r-- | arch/mips/sgi-ip32/ip32-reset.c | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/iseries/mf.c | 2 | ||||
-rw-r--r-- | drivers/char/nwbutton.c | 5 | ||||
-rw-r--r-- | drivers/char/snsc_event.c | 2 | ||||
-rw-r--r-- | drivers/parisc/power.c | 3 | ||||
-rw-r--r-- | drivers/s390/s390mach.c | 2 | ||||
-rw-r--r-- | include/linux/sched.h | 7 | ||||
-rw-r--r-- | init/main.c | 2 | ||||
-rw-r--r-- | kernel/sys.c | 6 | ||||
-rw-r--r-- | kernel/sysctl.c | 30 |
11 files changed, 48 insertions, 16 deletions
diff --git a/arch/mips/sgi-ip22/ip22-reset.c b/arch/mips/sgi-ip22/ip22-reset.c index 8134220ed600..7a941ecff3bb 100644 --- a/arch/mips/sgi-ip22/ip22-reset.c +++ b/arch/mips/sgi-ip22/ip22-reset.c | |||
@@ -123,7 +123,8 @@ static inline void power_button(void) | |||
123 | if (machine_state & MACHINE_PANICED) | 123 | if (machine_state & MACHINE_PANICED) |
124 | return; | 124 | return; |
125 | 125 | ||
126 | if ((machine_state & MACHINE_SHUTTING_DOWN) || kill_proc(1,SIGINT,1)) { | 126 | if ((machine_state & MACHINE_SHUTTING_DOWN) || |
127 | kill_cad_pid(SIGINT, 1)) { | ||
127 | /* No init process or button pressed twice. */ | 128 | /* No init process or button pressed twice. */ |
128 | sgi_machine_power_off(); | 129 | sgi_machine_power_off(); |
129 | } | 130 | } |
diff --git a/arch/mips/sgi-ip32/ip32-reset.c b/arch/mips/sgi-ip32/ip32-reset.c index 79ddb4605659..fd0932b2d521 100644 --- a/arch/mips/sgi-ip32/ip32-reset.c +++ b/arch/mips/sgi-ip32/ip32-reset.c | |||
@@ -120,7 +120,7 @@ static inline void ip32_power_button(void) | |||
120 | if (has_panicked) | 120 | if (has_panicked) |
121 | return; | 121 | return; |
122 | 122 | ||
123 | if (shuting_down || kill_proc(1, SIGINT, 1)) { | 123 | if (shuting_down || kill_cad_pid(SIGINT, 1)) { |
124 | /* No init process or button pressed twice. */ | 124 | /* No init process or button pressed twice. */ |
125 | ip32_machine_power_off(); | 125 | ip32_machine_power_off(); |
126 | } | 126 | } |
diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c index 1a2c2a50f922..1983b640bac1 100644 --- a/arch/powerpc/platforms/iseries/mf.c +++ b/arch/powerpc/platforms/iseries/mf.c | |||
@@ -357,7 +357,7 @@ static int dma_and_signal_ce_msg(char *ce_msg, | |||
357 | */ | 357 | */ |
358 | static int shutdown(void) | 358 | static int shutdown(void) |
359 | { | 359 | { |
360 | int rc = kill_proc(1, SIGINT, 1); | 360 | int rc = kill_cad_pid(SIGINT, 1); |
361 | 361 | ||
362 | if (rc) { | 362 | if (rc) { |
363 | printk(KERN_ALERT "mf.c: SIGINT to init failed (%d), " | 363 | printk(KERN_ALERT "mf.c: SIGINT to init failed (%d), " |
diff --git a/drivers/char/nwbutton.c b/drivers/char/nwbutton.c index 7c57ebfa8640..ea1aa7764f8e 100644 --- a/drivers/char/nwbutton.c +++ b/drivers/char/nwbutton.c | |||
@@ -127,9 +127,8 @@ static void button_consume_callbacks (int bpcount) | |||
127 | static void button_sequence_finished (unsigned long parameters) | 127 | static void button_sequence_finished (unsigned long parameters) |
128 | { | 128 | { |
129 | #ifdef CONFIG_NWBUTTON_REBOOT /* Reboot using button is enabled */ | 129 | #ifdef CONFIG_NWBUTTON_REBOOT /* Reboot using button is enabled */ |
130 | if (button_press_count == reboot_count) { | 130 | if (button_press_count == reboot_count) |
131 | kill_proc (1, SIGINT, 1); /* Ask init to reboot us */ | 131 | kill_cad_pid(SIGINT, 1); /* Ask init to reboot us */ |
132 | } | ||
133 | #endif /* CONFIG_NWBUTTON_REBOOT */ | 132 | #endif /* CONFIG_NWBUTTON_REBOOT */ |
134 | button_consume_callbacks (button_press_count); | 133 | button_consume_callbacks (button_press_count); |
135 | bcount = sprintf (button_output_buffer, "%d\n", button_press_count); | 134 | bcount = sprintf (button_output_buffer, "%d\n", button_press_count); |
diff --git a/drivers/char/snsc_event.c b/drivers/char/snsc_event.c index d12d4f629cec..864854c58866 100644 --- a/drivers/char/snsc_event.c +++ b/drivers/char/snsc_event.c | |||
@@ -220,7 +220,7 @@ scdrv_dispatch_event(char *event, int len) | |||
220 | " Sending SIGPWR to init...\n"); | 220 | " Sending SIGPWR to init...\n"); |
221 | 221 | ||
222 | /* give a SIGPWR signal to init proc */ | 222 | /* give a SIGPWR signal to init proc */ |
223 | kill_proc(1, SIGPWR, 0); | 223 | kill_cad_pid(SIGPWR, 0); |
224 | } else { | 224 | } else { |
225 | /* print to system log */ | 225 | /* print to system log */ |
226 | printk("%s|$(0x%x)%s\n", severity, esp_code, desc); | 226 | printk("%s|$(0x%x)%s\n", severity, esp_code, desc); |
diff --git a/drivers/parisc/power.c b/drivers/parisc/power.c index fad5a33bf0fa..4a9f025a6b58 100644 --- a/drivers/parisc/power.c +++ b/drivers/parisc/power.c | |||
@@ -84,8 +84,7 @@ | |||
84 | 84 | ||
85 | static void deferred_poweroff(void *dummy) | 85 | static void deferred_poweroff(void *dummy) |
86 | { | 86 | { |
87 | extern int cad_pid; /* from kernel/sys.c */ | 87 | if (kill_cad_pid(SIGINT, 1)) { |
88 | if (kill_proc(cad_pid, SIGINT, 1)) { | ||
89 | /* just in case killing init process failed */ | 88 | /* just in case killing init process failed */ |
90 | machine_power_off(); | 89 | machine_power_off(); |
91 | } | 90 | } |
diff --git a/drivers/s390/s390mach.c b/drivers/s390/s390mach.c index 479364d0332a..e088b5e28711 100644 --- a/drivers/s390/s390mach.c +++ b/drivers/s390/s390mach.c | |||
@@ -208,7 +208,7 @@ s390_handle_mcck(void) | |||
208 | */ | 208 | */ |
209 | __ctl_clear_bit(14, 24); /* Disable WARNING MCH */ | 209 | __ctl_clear_bit(14, 24); /* Disable WARNING MCH */ |
210 | if (xchg(&mchchk_wng_posted, 1) == 0) | 210 | if (xchg(&mchchk_wng_posted, 1) == 0) |
211 | kill_proc(1, SIGPWR, 1); | 211 | kill_cad_pid(SIGPWR, 1); |
212 | } | 212 | } |
213 | #endif | 213 | #endif |
214 | 214 | ||
diff --git a/include/linux/sched.h b/include/linux/sched.h index 9ba959e34266..38530232d92f 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
@@ -1065,6 +1065,8 @@ static inline int is_init(struct task_struct *tsk) | |||
1065 | return tsk->pid == 1; | 1065 | return tsk->pid == 1; |
1066 | } | 1066 | } |
1067 | 1067 | ||
1068 | extern struct pid *cad_pid; | ||
1069 | |||
1068 | extern void free_task(struct task_struct *tsk); | 1070 | extern void free_task(struct task_struct *tsk); |
1069 | #define get_task_struct(tsk) do { atomic_inc(&(tsk)->usage); } while(0) | 1071 | #define get_task_struct(tsk) do { atomic_inc(&(tsk)->usage); } while(0) |
1070 | 1072 | ||
@@ -1292,6 +1294,11 @@ extern int send_group_sigqueue(int, struct sigqueue *, struct task_struct *); | |||
1292 | extern int do_sigaction(int, struct k_sigaction *, struct k_sigaction *); | 1294 | extern int do_sigaction(int, struct k_sigaction *, struct k_sigaction *); |
1293 | extern int do_sigaltstack(const stack_t __user *, stack_t __user *, unsigned long); | 1295 | extern int do_sigaltstack(const stack_t __user *, stack_t __user *, unsigned long); |
1294 | 1296 | ||
1297 | static inline int kill_cad_pid(int sig, int priv) | ||
1298 | { | ||
1299 | return kill_pid(cad_pid, sig, priv); | ||
1300 | } | ||
1301 | |||
1295 | /* These can be the second arg to send_sig_info/send_group_sig_info. */ | 1302 | /* These can be the second arg to send_sig_info/send_group_sig_info. */ |
1296 | #define SEND_SIG_NOINFO ((struct siginfo *) 0) | 1303 | #define SEND_SIG_NOINFO ((struct siginfo *) 0) |
1297 | #define SEND_SIG_PRIV ((struct siginfo *) 1) | 1304 | #define SEND_SIG_PRIV ((struct siginfo *) 1) |
diff --git a/init/main.c b/init/main.c index a49b00235bda..ee123243fb53 100644 --- a/init/main.c +++ b/init/main.c | |||
@@ -721,6 +721,8 @@ static int init(void * unused) | |||
721 | */ | 721 | */ |
722 | child_reaper = current; | 722 | child_reaper = current; |
723 | 723 | ||
724 | cad_pid = task_pid(current); | ||
725 | |||
724 | smp_prepare_cpus(max_cpus); | 726 | smp_prepare_cpus(max_cpus); |
725 | 727 | ||
726 | do_pre_smp_initcalls(); | 728 | do_pre_smp_initcalls(); |
diff --git a/kernel/sys.c b/kernel/sys.c index 3a4776e8f16e..2314867ae34f 100644 --- a/kernel/sys.c +++ b/kernel/sys.c | |||
@@ -92,7 +92,8 @@ EXPORT_SYMBOL(fs_overflowgid); | |||
92 | */ | 92 | */ |
93 | 93 | ||
94 | int C_A_D = 1; | 94 | int C_A_D = 1; |
95 | int cad_pid = 1; | 95 | struct pid *cad_pid; |
96 | EXPORT_SYMBOL(cad_pid); | ||
96 | 97 | ||
97 | /* | 98 | /* |
98 | * Notifier list for kernel code which wants to be called | 99 | * Notifier list for kernel code which wants to be called |
@@ -773,10 +774,9 @@ void ctrl_alt_del(void) | |||
773 | if (C_A_D) | 774 | if (C_A_D) |
774 | schedule_work(&cad_work); | 775 | schedule_work(&cad_work); |
775 | else | 776 | else |
776 | kill_proc(cad_pid, SIGINT, 1); | 777 | kill_cad_pid(SIGINT, 1); |
777 | } | 778 | } |
778 | 779 | ||
779 | |||
780 | /* | 780 | /* |
781 | * Unprivileged users may change the real gid to the effective gid | 781 | * Unprivileged users may change the real gid to the effective gid |
782 | * or vice versa. (BSD-style) | 782 | * or vice versa. (BSD-style) |
diff --git a/kernel/sysctl.c b/kernel/sysctl.c index a79ccf9d113b..8020fb273c4f 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c | |||
@@ -68,7 +68,6 @@ extern int sysrq_enabled; | |||
68 | extern int core_uses_pid; | 68 | extern int core_uses_pid; |
69 | extern int suid_dumpable; | 69 | extern int suid_dumpable; |
70 | extern char core_pattern[]; | 70 | extern char core_pattern[]; |
71 | extern int cad_pid; | ||
72 | extern int pid_max; | 71 | extern int pid_max; |
73 | extern int min_free_kbytes; | 72 | extern int min_free_kbytes; |
74 | extern int printk_ratelimit_jiffies; | 73 | extern int printk_ratelimit_jiffies; |
@@ -137,6 +136,9 @@ static int parse_table(int __user *, int, void __user *, size_t __user *, | |||
137 | static int proc_do_uts_string(ctl_table *table, int write, struct file *filp, | 136 | static int proc_do_uts_string(ctl_table *table, int write, struct file *filp, |
138 | void __user *buffer, size_t *lenp, loff_t *ppos); | 137 | void __user *buffer, size_t *lenp, loff_t *ppos); |
139 | 138 | ||
139 | static int proc_do_cad_pid(ctl_table *table, int write, struct file *filp, | ||
140 | void __user *buffer, size_t *lenp, loff_t *ppos); | ||
141 | |||
140 | static ctl_table root_table[]; | 142 | static ctl_table root_table[]; |
141 | static struct ctl_table_header root_table_header = | 143 | static struct ctl_table_header root_table_header = |
142 | { root_table, LIST_HEAD_INIT(root_table_header.ctl_entry) }; | 144 | { root_table, LIST_HEAD_INIT(root_table_header.ctl_entry) }; |
@@ -543,10 +545,10 @@ static ctl_table kern_table[] = { | |||
543 | { | 545 | { |
544 | .ctl_name = KERN_CADPID, | 546 | .ctl_name = KERN_CADPID, |
545 | .procname = "cad_pid", | 547 | .procname = "cad_pid", |
546 | .data = &cad_pid, | 548 | .data = NULL, |
547 | .maxlen = sizeof (int), | 549 | .maxlen = sizeof (int), |
548 | .mode = 0600, | 550 | .mode = 0600, |
549 | .proc_handler = &proc_dointvec, | 551 | .proc_handler = &proc_do_cad_pid, |
550 | }, | 552 | }, |
551 | { | 553 | { |
552 | .ctl_name = KERN_MAX_THREADS, | 554 | .ctl_name = KERN_MAX_THREADS, |
@@ -2427,6 +2429,28 @@ proc_minmax: | |||
2427 | } | 2429 | } |
2428 | #endif | 2430 | #endif |
2429 | 2431 | ||
2432 | static int proc_do_cad_pid(ctl_table *table, int write, struct file *filp, | ||
2433 | void __user *buffer, size_t *lenp, loff_t *ppos) | ||
2434 | { | ||
2435 | struct pid *new_pid; | ||
2436 | pid_t tmp; | ||
2437 | int r; | ||
2438 | |||
2439 | tmp = pid_nr(cad_pid); | ||
2440 | |||
2441 | r = __do_proc_dointvec(&tmp, table, write, filp, buffer, | ||
2442 | lenp, ppos, NULL, NULL); | ||
2443 | if (r || !write) | ||
2444 | return r; | ||
2445 | |||
2446 | new_pid = find_get_pid(tmp); | ||
2447 | if (!new_pid) | ||
2448 | return -ESRCH; | ||
2449 | |||
2450 | put_pid(xchg(&cad_pid, new_pid)); | ||
2451 | return 0; | ||
2452 | } | ||
2453 | |||
2430 | #else /* CONFIG_PROC_FS */ | 2454 | #else /* CONFIG_PROC_FS */ |
2431 | 2455 | ||
2432 | int proc_dostring(ctl_table *table, int write, struct file *filp, | 2456 | int proc_dostring(ctl_table *table, int write, struct file *filp, |