]>
Commit | Line | Data |
---|---|---|
7642a5f6 JR |
1 | Vulnerability: CAN-2003-0127 |
2 | ||
3 | The Linux 2.2 and Linux 2.4 kernels have a flaw in ptrace. This hole allows | |
4 | local users to obtain full privileges. Remote exploitation of this hole is | |
5 | not possible. Linux 2.5 is not believed to be vulnerable. | |
6 | ||
7 | Linux 2.2.25 has been released to correct Linux 2.2. It contains no other | |
8 | changes. The bug fixes that would have been in 2.2.5pre1 will now appear in | |
9 | 2.2.26pre1. The patch will apply directly to most older 2.2 releases. | |
10 | ||
11 | A patch for Linux 2.4.20/Linux 2.4.21pre is attached. The patch also | |
12 | subtly changes the PR_SET_DUMPABLE prctl. We believe this is neccessary and | |
13 | that it will not affect any software. The functionality change is specific | |
14 | to unusual debugging situations. | |
15 | ||
16 | We would like to thank Andrzej Szombierski who found the problem, and | |
17 | wrote an initial patch. Seth Arnold cleaned up the 2.2 change. Arjan van | |
18 | de Ven and Ben LaHaise identified additional problems with the original | |
19 | fix. | |
20 | ||
21 | Alan | |
22 | ||
23 | diff -purN linux.orig/arch/alpha/kernel/entry.S linux/arch/alpha/kernel/entry.S | |
24 | --- linux.orig/arch/alpha/kernel/entry.S Thu Mar 13 12:01:46 2003 | |
25 | +++ linux/arch/alpha/kernel/entry.S Thu Mar 13 13:28:49 2003 | |
26 | @@ -231,12 +231,12 @@ kernel_clone: | |
27 | .end kernel_clone | |
28 | ||
29 | /* | |
30 | - * kernel_thread(fn, arg, clone_flags) | |
31 | + * arch_kernel_thread(fn, arg, clone_flags) | |
32 | */ | |
33 | .align 3 | |
34 | .globl kernel_thread | |
35 | .ent kernel_thread | |
36 | -kernel_thread: | |
37 | +arch_kernel_thread: | |
38 | ldgp $29,0($27) /* we can be called from a module */ | |
39 | .frame $30, 4*8, $26 | |
40 | subq $30,4*8,$30 | |
41 | diff -purN linux.orig/arch/arm/kernel/process.c linux/arch/arm/kernel/process.c | |
42 | --- linux.orig/arch/arm/kernel/process.c Thu Mar 13 12:01:29 2003 | |
43 | +++ linux/arch/arm/kernel/process.c Thu Mar 13 13:25:56 2003 | |
44 | @@ -366,7 +366,7 @@ void dump_thread(struct pt_regs * regs, | |
45 | * a system call from a "real" process, but the process memory space will | |
46 | * not be free'd until both the parent and the child have exited. | |
47 | */ | |
48 | -pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) | |
49 | +pid_t arch_kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) | |
50 | { | |
51 | pid_t __ret; | |
52 | ||
53 | diff -purN linux.orig/arch/cris/kernel/entry.S linux/arch/cris/kernel/entry.S | |
54 | --- linux.orig/arch/cris/kernel/entry.S Thu Mar 13 12:01:29 2003 | |
55 | +++ linux/arch/cris/kernel/entry.S Thu Mar 13 13:30:30 2003 | |
56 | @@ -736,12 +736,12 @@ hw_bp_trig_ptr: | |
57 | * the grosser the code, at least with the gcc version in cris-dist-1.13. | |
58 | */ | |
59 | ||
60 | -/* int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) */ | |
61 | +/* int arch_kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) */ | |
62 | /* r10 r11 r12 */ | |
63 | ||
64 | .text | |
65 | - .global kernel_thread | |
66 | -kernel_thread: | |
67 | + .global arch_kernel_thread | |
68 | +arch_kernel_thread: | |
69 | ||
70 | /* Save ARG for later. */ | |
71 | move.d $r11, $r13 | |
72 | diff -purN linux.orig/arch/i386/kernel/process.c linux/arch/i386/kernel/process.c | |
73 | --- linux.orig/arch/i386/kernel/process.c Thu Mar 13 12:01:57 2003 | |
74 | +++ linux/arch/i386/kernel/process.c Thu Mar 13 13:26:08 2003 | |
75 | @@ -495,7 +495,7 @@ void release_segments(struct mm_struct * | |
76 | /* | |
77 | * Create a kernel thread | |
78 | */ | |
79 | -int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | |
80 | +int arch_kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | |
81 | { | |
82 | long retval, d0; | |
83 | ||
84 | @@ -518,6 +518,7 @@ int kernel_thread(int (*fn)(void *), voi | |
85 | "r" (arg), "r" (fn), | |
86 | "b" (flags | CLONE_VM) | |
87 | : "memory"); | |
88 | + | |
89 | return retval; | |
90 | } | |
91 | ||
92 | diff -purN linux.orig/arch/ia64/kernel/process.c linux/arch/ia64/kernel/process.c | |
93 | --- linux.orig/arch/ia64/kernel/process.c Thu Mar 13 12:01:29 2003 | |
94 | +++ linux/arch/ia64/kernel/process.c Thu Mar 13 13:26:15 2003 | |
95 | @@ -220,7 +220,7 @@ ia64_load_extra (struct task_struct *tas | |
96 | * | | <-- sp (lowest addr) | |
97 | * +---------------------+ | |
98 | * | |
99 | - * Note: if we get called through kernel_thread() then the memory | |
100 | + * Note: if we get called through arch_kernel_thread() then the memory | |
101 | * above "(highest addr)" is valid kernel stack memory that needs to | |
102 | * be copied as well. | |
103 | * | |
104 | @@ -469,7 +469,7 @@ ia64_set_personality (struct elf64_hdr * | |
105 | } | |
106 | ||
107 | pid_t | |
108 | -kernel_thread (int (*fn)(void *), void *arg, unsigned long flags) | |
109 | +arch_kernel_thread (int (*fn)(void *), void *arg, unsigned long flags) | |
110 | { | |
111 | struct task_struct *parent = current; | |
112 | int result, tid; | |
113 | diff -purN linux.orig/arch/m68k/kernel/process.c linux/arch/m68k/kernel/process.c | |
114 | --- linux.orig/arch/m68k/kernel/process.c Thu Mar 13 12:01:29 2003 | |
115 | +++ linux/arch/m68k/kernel/process.c Thu Mar 13 13:26:18 2003 | |
116 | @@ -124,7 +124,7 @@ void show_regs(struct pt_regs * regs) | |
117 | /* | |
118 | * Create a kernel thread | |
119 | */ | |
120 | -int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | |
121 | +int arch_kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | |
122 | { | |
123 | int pid; | |
124 | mm_segment_t fs; | |
125 | diff -purN linux.orig/arch/mips/kernel/process.c linux/arch/mips/kernel/process.c | |
126 | --- linux.orig/arch/mips/kernel/process.c Thu Mar 13 12:01:29 2003 | |
127 | +++ linux/arch/mips/kernel/process.c Thu Mar 13 13:26:28 2003 | |
128 | @@ -155,7 +155,7 @@ void dump_thread(struct pt_regs *regs, s | |
129 | /* | |
130 | * Create a kernel thread | |
131 | */ | |
132 | -int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | |
133 | +int arch_kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | |
134 | { | |
135 | long retval; | |
136 | ||
137 | diff -purN linux.orig/arch/mips64/kernel/process.c linux/arch/mips64/kernel/process.c | |
138 | --- linux.orig/arch/mips64/kernel/process.c Thu Mar 13 12:01:29 2003 | |
139 | +++ linux/arch/mips64/kernel/process.c Thu Mar 13 13:26:23 2003 | |
140 | @@ -152,7 +152,7 @@ void dump_thread(struct pt_regs *regs, s | |
141 | /* | |
142 | * Create a kernel thread | |
143 | */ | |
144 | -int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) | |
145 | +int arch_kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) | |
146 | { | |
147 | int retval; | |
148 | ||
149 | diff -purN linux.orig/arch/parisc/kernel/process.c linux/arch/parisc/kernel/process.c | |
150 | --- linux.orig/arch/parisc/kernel/process.c Fri Feb 9 14:29:44 2001 | |
151 | +++ linux/arch/parisc/kernel/process.c Thu Mar 13 13:26:36 2003 | |
152 | @@ -118,7 +118,7 @@ void machine_heartbeat(void) | |
153 | */ | |
154 | ||
155 | extern pid_t __kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); | |
156 | -pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) | |
157 | +pid_t arch_kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) | |
158 | { | |
159 | ||
160 | /* | |
161 | diff -purN linux.orig/arch/ppc/kernel/misc.S linux/arch/ppc/kernel/misc.S | |
162 | --- linux.orig/arch/ppc/kernel/misc.S Thu Mar 13 12:01:29 2003 | |
163 | +++ linux/arch/ppc/kernel/misc.S Thu Mar 13 13:32:21 2003 | |
164 | @@ -899,9 +899,9 @@ _GLOBAL(cvt_df) | |
165 | ||
166 | /* | |
167 | * Create a kernel thread | |
168 | - * kernel_thread(fn, arg, flags) | |
169 | + * arch_kernel_thread(fn, arg, flags) | |
170 | */ | |
171 | -_GLOBAL(kernel_thread) | |
172 | +_GLOBAL(arch_kernel_thread) | |
173 | mr r6,r3 /* function */ | |
174 | ori r3,r5,CLONE_VM /* flags */ | |
175 | li r0,__NR_clone | |
176 | diff -purN linux.orig/arch/ppc64/kernel/misc.S linux/arch/ppc64/kernel/misc.S | |
177 | --- linux.orig/arch/ppc64/kernel/misc.S Thu Mar 13 12:01:30 2003 | |
178 | +++ linux/arch/ppc64/kernel/misc.S Thu Mar 13 13:29:42 2003 | |
179 | @@ -493,9 +493,9 @@ _GLOBAL(cvt_df) | |
180 | ||
181 | /* | |
182 | * Create a kernel thread | |
183 | - * kernel_thread(fn, arg, flags) | |
184 | + * arch_kernel_thread(fn, arg, flags) | |
185 | */ | |
186 | -_GLOBAL(kernel_thread) | |
187 | +_GLOBAL(arch_kernel_thread) | |
188 | mr r6,r3 /* function */ | |
189 | ori r3,r5,CLONE_VM /* flags */ | |
190 | li r0,__NR_clone | |
191 | diff -purN linux.orig/arch/s390/kernel/process.c linux/arch/s390/kernel/process.c | |
192 | --- linux.orig/arch/s390/kernel/process.c Thu Mar 13 12:01:30 2003 | |
193 | +++ linux/arch/s390/kernel/process.c Thu Mar 13 13:26:43 2003 | |
194 | @@ -105,7 +105,7 @@ void show_regs(struct pt_regs *regs) | |
195 | show_trace((unsigned long *) regs->gprs[15]); | |
196 | } | |
197 | ||
198 | -int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | |
199 | +int arch_kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | |
200 | { | |
201 | int clone_arg = flags | CLONE_VM; | |
202 | int retval; | |
203 | diff -purN linux.orig/arch/s390x/kernel/process.c linux/arch/s390x/kernel/process.c | |
204 | --- linux.orig/arch/s390x/kernel/process.c Thu Mar 13 12:01:30 2003 | |
205 | +++ linux/arch/s390x/kernel/process.c Thu Mar 13 13:26:46 2003 | |
206 | @@ -102,7 +102,7 @@ void show_regs(struct pt_regs *regs) | |
207 | show_trace((unsigned long *) regs->gprs[15]); | |
208 | } | |
209 | ||
210 | -int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | |
211 | +int arch_kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | |
212 | { | |
213 | int clone_arg = flags | CLONE_VM; | |
214 | int retval; | |
215 | diff -purN linux.orig/arch/sh/kernel/process.c linux/arch/sh/kernel/process.c | |
216 | --- linux.orig/arch/sh/kernel/process.c Mon Oct 15 16:36:48 2001 | |
217 | +++ linux/arch/sh/kernel/process.c Thu Mar 13 13:26:49 2003 | |
218 | @@ -118,7 +118,7 @@ void free_task_struct(struct task_struct | |
219 | * This is the mechanism for creating a new kernel thread. | |
220 | * | |
221 | */ | |
222 | -int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | |
223 | +int arch_kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | |
224 | { /* Don't use this in BL=1(cli). Or else, CPU resets! */ | |
225 | register unsigned long __sc0 __asm__ ("r0"); | |
226 | register unsigned long __sc3 __asm__ ("r3") = __NR_clone; | |
227 | diff -purN linux.orig/arch/sparc/kernel/process.c linux/arch/sparc/kernel/process.c | |
228 | --- linux.orig/arch/sparc/kernel/process.c Thu Mar 13 12:01:30 2003 | |
229 | +++ linux/arch/sparc/kernel/process.c Thu Mar 13 13:26:58 2003 | |
230 | @@ -676,7 +676,7 @@ out: | |
231 | * a system call from a "real" process, but the process memory space will | |
232 | * not be free'd until both the parent and the child have exited. | |
233 | */ | |
234 | -pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | |
235 | +pid_t arch_kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | |
236 | { | |
237 | long retval; | |
238 | ||
239 | diff -purN linux.orig/arch/sparc64/kernel/process.c linux/arch/sparc64/kernel/process.c | |
240 | --- linux.orig/arch/sparc64/kernel/process.c Thu Mar 13 12:01:30 2003 | |
241 | +++ linux/arch/sparc64/kernel/process.c Thu Mar 13 13:26:54 2003 | |
242 | @@ -658,7 +658,7 @@ int copy_thread(int nr, unsigned long cl | |
243 | * a system call from a "real" process, but the process memory space will | |
244 | * not be free'd until both the parent and the child have exited. | |
245 | */ | |
246 | -pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | |
247 | +pid_t arch_kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | |
248 | { | |
249 | long retval; | |
250 | ||
251 | diff -purN linux.orig/arch/um/kernel/process_kern.c linux/arch/um/kernel/process_kern.c | |
252 | --- linux.orig/arch/um/kernel/process_kern.c Thu Mar 13 12:01:48 2003 | |
253 | +++ linux/arch/um/kernel/process_kern.c Thu Mar 13 13:27:37 2003 | |
254 | @@ -171,14 +171,14 @@ static int new_thread_proc(void *stack) | |
255 | os_usr1_process(os_getpid()); | |
256 | } | |
257 | ||
258 | -int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | |
259 | +int arch_kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | |
260 | { | |
261 | int pid; | |
262 | ||
263 | current->thread.request.u.thread.proc = fn; | |
264 | current->thread.request.u.thread.arg = arg; | |
265 | pid = do_fork(CLONE_VM | flags, 0, NULL, 0); | |
266 | - if(pid < 0) panic("do_fork failed in kernel_thread"); | |
267 | + if(pid < 0) panic("do_fork failed in arch_kernel_thread"); | |
268 | return(pid); | |
269 | } | |
270 | ||
271 | diff -purN linux.orig/fs/exec.c linux/fs/exec.c | |
272 | --- linux.orig/fs/exec.c Thu Mar 13 12:01:46 2003 | |
273 | +++ linux/fs/exec.c Thu Mar 13 14:19:08 2003 | |
274 | @@ -559,8 +559,10 @@ int flush_old_exec(struct linux_binprm * | |
275 | ||
276 | current->sas_ss_sp = current->sas_ss_size = 0; | |
277 | ||
278 | - if (current->euid == current->uid && current->egid == current->gid) | |
279 | + if (current->euid == current->uid && current->egid == current->gid) { | |
280 | current->mm->dumpable = 1; | |
281 | + current->task_dumpable = 1; | |
282 | + } | |
283 | name = bprm->filename; | |
284 | for (i=0; (ch = *(name++)) != '\0';) { | |
285 | if (ch == '/') | |
286 | @@ -952,7 +954,7 @@ int do_coredump(long signr, struct pt_re | |
287 | binfmt = current->binfmt; | |
288 | if (!binfmt || !binfmt->core_dump) | |
289 | goto fail; | |
290 | - if (!current->mm->dumpable) | |
291 | + if (!is_dumpable(current)) | |
292 | goto fail; | |
293 | current->mm->dumpable = 0; | |
294 | if (current->rlim[RLIMIT_CORE].rlim_cur < binfmt->min_coredump) | |
295 | diff -purN linux.orig/include/asm-alpha/processor.h linux/include/asm-alpha/processor.h | |
296 | --- linux.orig/include/asm-alpha/processor.h Fri Oct 5 15:11:05 2001 | |
297 | +++ linux/include/asm-alpha/processor.h Thu Mar 13 13:35:18 2003 | |
298 | @@ -119,7 +119,7 @@ struct task_struct; | |
299 | extern void release_thread(struct task_struct *); | |
300 | ||
301 | /* Create a kernel thread without removing it from tasklists. */ | |
302 | -extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); | |
303 | +extern long arch_kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); | |
304 | ||
305 | #define copy_segments(tsk, mm) do { } while (0) | |
306 | #define release_segments(mm) do { } while (0) | |
307 | diff -purN linux.orig/include/asm-arm/processor.h linux/include/asm-arm/processor.h | |
308 | --- linux.orig/include/asm-arm/processor.h Thu Mar 13 12:01:35 2003 | |
309 | +++ linux/include/asm-arm/processor.h Thu Mar 13 13:35:18 2003 | |
310 | @@ -117,7 +117,7 @@ extern void __free_task_struct(struct ta | |
311 | /* | |
312 | * Create a new kernel thread | |
313 | */ | |
314 | -extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); | |
315 | +extern int arch_kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); | |
316 | ||
317 | #endif | |
318 | ||
319 | diff -purN linux.orig/include/asm-cris/processor.h linux/include/asm-cris/processor.h | |
320 | --- linux.orig/include/asm-cris/processor.h Thu Mar 13 12:01:35 2003 | |
321 | +++ linux/include/asm-cris/processor.h Thu Mar 13 13:35:18 2003 | |
322 | @@ -81,7 +81,7 @@ struct thread_struct { | |
323 | #define INIT_THREAD { \ | |
324 | 0, 0, 0x20 } /* ccr = int enable, nothing else */ | |
325 | ||
326 | -extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | |
327 | +extern int arch_kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | |
328 | ||
329 | /* give the thread a program location | |
330 | * set user-mode (The 'U' flag (User mode flag) is CCR/DCCR bit 8) | |
331 | diff -purN linux.orig/include/asm-i386/processor.h linux/include/asm-i386/processor.h | |
332 | --- linux.orig/include/asm-i386/processor.h Thu Mar 13 12:01:57 2003 | |
333 | +++ linux/include/asm-i386/processor.h Thu Mar 13 13:51:02 2003 | |
334 | @@ -433,7 +433,7 @@ extern void release_thread(struct task_s | |
335 | /* | |
336 | * create a kernel thread without removing it from tasklists | |
337 | */ | |
338 | -extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | |
339 | +extern int arch_kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | |
340 | ||
341 | /* Copy and release all segment info associated with a VM */ | |
342 | extern void copy_segments(struct task_struct *p, struct mm_struct * mm); | |
343 | diff -purN linux.orig/include/asm-ia64/processor.h linux/include/asm-ia64/processor.h | |
344 | --- linux.orig/include/asm-ia64/processor.h Thu Mar 13 12:01:35 2003 | |
345 | +++ linux/include/asm-ia64/processor.h Thu Mar 13 13:35:18 2003 | |
346 | @@ -476,7 +476,7 @@ struct task_struct; | |
347 | * do_basic_setup() and the timing is such that free_initmem() has | |
348 | * been called already. | |
349 | */ | |
350 | -extern int kernel_thread (int (*fn)(void *), void *arg, unsigned long flags); | |
351 | +extern int arch_kernel_thread (int (*fn)(void *), void *arg, unsigned long flags); | |
352 | ||
353 | /* Copy and release all segment info associated with a VM */ | |
354 | #define copy_segments(tsk, mm) do { } while (0) | |
355 | diff -purN linux.orig/include/asm-m68k/processor.h linux/include/asm-m68k/processor.h | |
356 | --- linux.orig/include/asm-m68k/processor.h Fri Oct 5 15:11:05 2001 | |
357 | +++ linux/include/asm-m68k/processor.h Thu Mar 13 13:35:18 2003 | |
358 | @@ -105,7 +105,7 @@ static inline void release_thread(struct | |
359 | { | |
360 | } | |
361 | ||
362 | -extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | |
363 | +extern int arch_kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | |
364 | ||
365 | #define copy_segments(tsk, mm) do { } while (0) | |
366 | #define release_segments(mm) do { } while (0) | |
367 | diff -purN linux.orig/include/asm-mips/processor.h linux/include/asm-mips/processor.h | |
368 | --- linux.orig/include/asm-mips/processor.h Thu Mar 13 12:01:36 2003 | |
369 | +++ linux/include/asm-mips/processor.h Thu Mar 13 13:35:18 2003 | |
370 | @@ -186,7 +186,7 @@ struct thread_struct { | |
371 | /* Free all resources held by a thread. */ | |
372 | #define release_thread(thread) do { } while(0) | |
373 | ||
374 | -extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | |
375 | +extern int arch_kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | |
376 | ||
377 | /* Copy and release all segment info associated with a VM */ | |
378 | #define copy_segments(p, mm) do { } while(0) | |
379 | diff -purN linux.orig/include/asm-mips64/processor.h linux/include/asm-mips64/processor.h | |
380 | --- linux.orig/include/asm-mips64/processor.h Thu Mar 13 12:01:36 2003 | |
381 | +++ linux/include/asm-mips64/processor.h Thu Mar 13 13:35:18 2003 | |
382 | @@ -245,7 +245,7 @@ struct thread_struct { | |
383 | /* Free all resources held by a thread. */ | |
384 | #define release_thread(thread) do { } while(0) | |
385 | ||
386 | -extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | |
387 | +extern int arch_kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | |
388 | ||
389 | /* Copy and release all segment info associated with a VM */ | |
390 | #define copy_segments(p, mm) do { } while(0) | |
391 | diff -purN linux.orig/include/asm-parisc/processor.h linux/include/asm-parisc/processor.h | |
392 | --- linux.orig/include/asm-parisc/processor.h Fri Oct 5 15:11:05 2001 | |
393 | +++ linux/include/asm-parisc/processor.h Thu Mar 13 13:35:18 2003 | |
394 | @@ -305,7 +305,7 @@ struct task_struct; | |
395 | ||
396 | /* Free all resources held by a thread. */ | |
397 | extern void release_thread(struct task_struct *); | |
398 | -extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | |
399 | +extern int arch_kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | |
400 | ||
401 | #define copy_segments(tsk, mm) do { } while (0) | |
402 | #define release_segments(mm) do { } while (0) | |
403 | diff -purN linux.orig/include/asm-ppc/processor.h linux/include/asm-ppc/processor.h | |
404 | --- linux.orig/include/asm-ppc/processor.h Thu Mar 13 12:01:36 2003 | |
405 | +++ linux/include/asm-ppc/processor.h Thu Mar 13 13:35:18 2003 | |
406 | @@ -593,7 +593,7 @@ void release_thread(struct task_struct * | |
407 | /* | |
408 | * Create a new kernel thread. | |
409 | */ | |
410 | -extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); | |
411 | +extern long arch_kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); | |
412 | ||
413 | /* | |
414 | * Bus types | |
415 | diff -purN linux.orig/include/asm-ppc64/processor.h linux/include/asm-ppc64/processor.h | |
416 | --- linux.orig/include/asm-ppc64/processor.h Thu Mar 13 12:01:36 2003 | |
417 | +++ linux/include/asm-ppc64/processor.h Thu Mar 13 13:35:18 2003 | |
418 | @@ -609,7 +609,7 @@ void release_thread(struct task_struct * | |
419 | /* | |
420 | * Create a new kernel thread. | |
421 | */ | |
422 | -extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); | |
423 | +extern long arch_kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); | |
424 | ||
425 | /* | |
426 | * Bus types | |
427 | diff -purN linux.orig/include/asm-s390/processor.h linux/include/asm-s390/processor.h | |
428 | --- linux.orig/include/asm-s390/processor.h Thu Mar 13 12:01:36 2003 | |
429 | +++ linux/include/asm-s390/processor.h Thu Mar 13 13:35:18 2003 | |
430 | @@ -113,7 +113,7 @@ struct mm_struct; | |
431 | ||
432 | /* Free all resources held by a thread. */ | |
433 | extern void release_thread(struct task_struct *); | |
434 | -extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | |
435 | +extern int arch_kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | |
436 | ||
437 | /* Copy and release all segment info associated with a VM */ | |
438 | #define copy_segments(nr, mm) do { } while (0) | |
439 | diff -purN linux.orig/include/asm-s390x/processor.h linux/include/asm-s390x/processor.h | |
440 | --- linux.orig/include/asm-s390x/processor.h Thu Mar 13 12:01:36 2003 | |
441 | +++ linux/include/asm-s390x/processor.h Thu Mar 13 13:35:18 2003 | |
442 | @@ -127,7 +127,7 @@ struct mm_struct; | |
443 | ||
444 | /* Free all resources held by a thread. */ | |
445 | extern void release_thread(struct task_struct *); | |
446 | -extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | |
447 | +extern int arch_kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | |
448 | ||
449 | /* Copy and release all segment info associated with a VM */ | |
450 | #define copy_segments(nr, mm) do { } while (0) | |
451 | diff -purN linux.orig/include/asm-sh/processor.h linux/include/asm-sh/processor.h | |
452 | --- linux.orig/include/asm-sh/processor.h Fri Oct 5 15:11:05 2001 | |
453 | +++ linux/include/asm-sh/processor.h Thu Mar 13 13:35:18 2003 | |
454 | @@ -137,7 +137,7 @@ extern void release_thread(struct task_s | |
455 | /* | |
456 | * create a kernel thread without removing it from tasklists | |
457 | */ | |
458 | -extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | |
459 | +extern int arch_kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | |
460 | ||
461 | /* | |
462 | * Bus types | |
463 | diff -purN linux.orig/include/asm-sparc/processor.h linux/include/asm-sparc/processor.h | |
464 | --- linux.orig/include/asm-sparc/processor.h Thu Oct 11 02:42:47 2001 | |
465 | +++ linux/include/asm-sparc/processor.h Thu Mar 13 13:35:18 2003 | |
466 | @@ -146,7 +146,7 @@ extern __inline__ void start_thread(stru | |
467 | ||
468 | /* Free all resources held by a thread. */ | |
469 | #define release_thread(tsk) do { } while(0) | |
470 | -extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | |
471 | +extern pid_t arch_kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | |
472 | ||
473 | ||
474 | #define copy_segments(tsk, mm) do { } while (0) | |
475 | diff -purN linux.orig/include/asm-sparc64/processor.h linux/include/asm-sparc64/processor.h | |
476 | --- linux.orig/include/asm-sparc64/processor.h Thu Mar 13 12:01:36 2003 | |
477 | +++ linux/include/asm-sparc64/processor.h Thu Mar 13 13:35:18 2003 | |
478 | @@ -270,7 +270,7 @@ do { \ | |
479 | /* Free all resources held by a thread. */ | |
480 | #define release_thread(tsk) do { } while(0) | |
481 | ||
482 | -extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | |
483 | +extern pid_t arch_kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | |
484 | ||
485 | #define copy_segments(tsk, mm) do { } while (0) | |
486 | #define release_segments(mm) do { } while (0) | |
487 | diff -purN linux.orig/include/linux/sched.h linux/include/linux/sched.h | |
488 | --- linux.orig/include/linux/sched.h Thu Mar 13 12:01:57 2003 | |
489 | +++ linux/include/linux/sched.h Thu Mar 13 13:54:05 2003 | |
490 | @@ -362,6 +362,7 @@ struct task_struct { | |
491 | /* ??? */ | |
492 | unsigned long personality; | |
493 | int did_exec:1, in_page_fault:1; | |
494 | + unsigned task_dumpable:1; | |
495 | pid_t pid; | |
496 | pid_t pgrp; | |
497 | pid_t tty_old_pgrp; | |
498 | @@ -485,6 +486,8 @@ struct task_struct { | |
499 | #define PT_TRACESYSGOOD 0x00000008 | |
500 | #define PT_PTRACE_CAP 0x00000010 /* ptracer can follow suid-exec */ | |
501 | ||
502 | +#define is_dumpable(tsk) ((tsk)->task_dumpable && (tsk)->mm->dumpable) | |
503 | + | |
504 | /* | |
505 | * Limit the stack by to some sane default: root can always | |
506 | * increase this limit if needed.. 8MB seems reasonable. | |
507 | @@ -848,6 +851,8 @@ extern void FASTCALL(remove_wait_queue(w | |
508 | ||
509 | extern void wait_task_inactive(task_t * p); | |
510 | extern void kick_if_running(task_t * p); | |
511 | +extern long kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | |
512 | + | |
513 | ||
514 | #define __wait_event(wq, condition) \ | |
515 | do { \ | |
516 | diff -purN linux.orig/kernel/fork.c linux/kernel/fork.c | |
517 | --- linux.orig/kernel/fork.c Thu Mar 13 12:01:57 2003 | |
518 | +++ linux/kernel/fork.c Thu Mar 13 13:51:24 2003 | |
519 | @@ -28,6 +28,7 @@ | |
520 | #include <asm/pgalloc.h> | |
521 | #include <asm/uaccess.h> | |
522 | #include <asm/mmu_context.h> | |
523 | +#include <asm/processor.h> | |
524 | ||
525 | /* The idle threads do not count.. */ | |
526 | int nr_threads; | |
527 | @@ -575,6 +576,31 @@ static inline void copy_flags(unsigned l | |
528 | p->flags = new_flags; | |
529 | } | |
530 | ||
531 | +long kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | |
532 | +{ | |
533 | + struct task_struct *task = current; | |
534 | + unsigned old_task_dumpable; | |
535 | + long ret; | |
536 | + | |
537 | + /* lock out any potential ptracer */ | |
538 | + task_lock(task); | |
539 | + if (task->ptrace) { | |
540 | + task_unlock(task); | |
541 | + return -EPERM; | |
542 | + } | |
543 | + | |
544 | + old_task_dumpable = task->task_dumpable; | |
545 | + task->task_dumpable = 0; | |
546 | + task_unlock(task); | |
547 | + | |
548 | + ret = arch_kernel_thread(fn, arg, flags); | |
549 | + | |
550 | + /* never reached in child process, only in parent */ | |
551 | + current->task_dumpable = old_task_dumpable; | |
552 | + | |
553 | + return ret; | |
554 | +} | |
555 | + | |
556 | /* | |
557 | * Ok, this is the main fork-routine. It copies the system process | |
558 | * information (task[nr]) and sets up the necessary registers. It also | |
559 | diff -purN linux.orig/kernel/ptrace.c linux/kernel/ptrace.c | |
560 | --- linux.orig/kernel/ptrace.c Thu Mar 13 12:01:46 2003 | |
561 | +++ linux/kernel/ptrace.c Thu Mar 13 13:47:16 2003 | |
562 | @@ -21,6 +21,10 @@ | |
563 | */ | |
564 | int ptrace_check_attach(struct task_struct *child, int kill) | |
565 | { | |
566 | + mb(); | |
567 | + if (!is_dumpable(child)) | |
568 | + return -EPERM; | |
569 | + | |
570 | if (!(child->ptrace & PT_PTRACED)) | |
571 | return -ESRCH; | |
572 | ||
573 | @@ -57,7 +61,7 @@ int ptrace_attach(struct task_struct *ta | |
574 | (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE)) | |
575 | goto bad; | |
576 | rmb(); | |
577 | - if (!task->mm->dumpable && !capable(CAP_SYS_PTRACE)) | |
578 | + if (!is_dumpable(task) && !capable(CAP_SYS_PTRACE)) | |
579 | goto bad; | |
580 | /* the same process cannot be attached many times */ | |
581 | if (task->ptrace & PT_PTRACED) | |
582 | @@ -123,6 +127,8 @@ int access_process_vm(struct task_struct | |
583 | /* Worry about races with exit() */ | |
584 | task_lock(tsk); | |
585 | mm = tsk->mm; | |
586 | + if (!is_dumpable(tsk) || (&init_mm == mm)) | |
587 | + mm = NULL; | |
588 | if (mm) | |
589 | atomic_inc(&mm->mm_users); | |
590 | task_unlock(tsk); | |
591 | diff -purN linux.orig/kernel/sys.c linux/kernel/sys.c | |
592 | --- linux.orig/kernel/sys.c Thu Mar 13 12:01:57 2003 | |
593 | +++ linux/kernel/sys.c Thu Mar 13 13:41:25 2003 | |
594 | @@ -1286,7 +1286,7 @@ asmlinkage long sys_prctl(int option, un | |
595 | error = put_user(current->pdeath_signal, (int *)arg2); | |
596 | break; | |
597 | case PR_GET_DUMPABLE: | |
598 | - if (current->mm->dumpable) | |
599 | + if (is_dumpable(current)) | |
600 | error = 1; | |
601 | break; | |
602 | case PR_SET_DUMPABLE: | |
603 | @@ -1294,7 +1294,8 @@ asmlinkage long sys_prctl(int option, un | |
604 | error = -EINVAL; | |
605 | break; | |
606 | } | |
607 | - current->mm->dumpable = arg2; | |
608 | + if (is_dumpable(current)) | |
609 | + current->mm->dumpable = arg2; | |
610 | break; | |
611 | case PR_SET_UNALIGN: | |
612 | #ifdef SET_UNALIGN_CTL | |
613 | - | |
614 | To unsubscribe from this list: send the line "unsubscribe linux-kernel" in | |
615 | the body of a message to majordomo@vger.kernel.org | |
616 | More majordomo info at http://vger.kernel.org/majordomo-info.html | |
617 | Please read the FAQ at http://www.tux.org/lkml/ |