hi all I have a similar problem after compiling a new kernel with kernel-source-2.4.20_2.4.20-3woody.3_all.deb
The output of ps has change and doesn't output the full-path of a prozess anymore. like this: sid 2.4.20 build with source from kernel.org (ptrace bug unpatch) or any other woody 2.4.17-19 (all build from kernel-source.deb) I looked at : --------------------------------------------- ps faux | grep apache root 16960 0.0 0.9 141232 4812 ? S 14:45 0:00 /usr/sbin/apache www-data 16964 0.0 1.1 142156 5328 ? S 14:45 0:00 \_ /usr/sbin/apache woody 2.4.20 build with kernel-source-2.4.20_2.4.20-3woody.3_all.deb: --------------------------------------------- ps faux | grep apache root 695 0.0 1.3 71420 1784 ? S Mar21 0:02 /usr/sbin/apache www-data 27165 0.0 1.5 71480 2016 ? S 06:26 0:00 \_ [apache] in my case "mailscanner" from woody is broken since it does a pid=`/bin/ps axww | /bin/grep /usr/sbin/mailscanner but there are very likly others Is this just me doing something wrong? tks and greeting pascal Am Thu, Mar 20, 2003 at 10:43:05AM +1200, Matthew Grant sagte: > Hi There! > > Sorry about making a racket, but I am posting this for the edification > of all, as there is a work around without breaking your server for this > one. > > As you can read below, I have found that the patch on 2.4.x also BREAKS > kill() 2 when executed for signal 0 on a process ID that the user is not > the owner of, except for root of course. > > This has all sorts of interesting effects for processing .pid files, and > probably dot locking..... Makes the patch as it stands unacceptable for > 2.4.21, and vendor kernels I would say... (See below for effects on > Debian netsaint...) > > I have been just digging harder, and the vulnerability is only > exploitable if you are using the kernel auto module loader, so compile > your kernel with out auto module loader enabled, or echo some garbage > into /proc/sys/kernel/modprobe after loading all your modules. It has > to be an invalid executable name in there as any executable file will > open the bug to exploit. > > Here are the effects on a netsaint box I look after: > > bucket: -foo- [~] > $ ls -l /var/run/netsaint/netsaint.pid > -rw-r--r-- 1 root root 5 Mar 19 16:32 > /var/run/netsaint/netsaint.pid > > bucket: -foo- [~] > $ cat !$ > cat /var/run/netsaint/netsaint.pid > 4276 > > bucket: -foo- [~] > $ kill -0 4276 > bash: kill: (4276) - Operation not permitted > > and the netsaint Web front end can't find the process alive that it > wants to talk to via a unix pipe so that it can start and stop > notifications etc.... > > Could I please say this to the kernel developers, please fix it > properly! > > Thanks heaps, > > Matthew Grant > > On Thu, 2003-03-20 at 09:34, Matthew Grant wrote: > Dear All, > > The patch also breaks kill(2) on a process with signal number 0 - This > is used by a lot of monitoring programs running as one user ID to make > sure a process with another user ID is running. > > This causes trouble with packages like nagios and netsaint, as well as > other stuff. > > Alan, don't want to bash you around, but isn't there another fix > possible that doesn't break this function call and UML skas mode? > > Cheers, > > Matthew Grantal > > On Thu, 2003-03-20 at 08:09, Matthew Grant wrote: > Mistyped linux-kernel address %-< > > -----Forwarded Message----- > > From: Matthew Grant <[EMAIL PROTECTED]> > To: Alan Cox <[EMAIL PROTECTED]> > Cc: Jeff Dike <[EMAIL PROTECTED]>, [EMAIL PROTECTED] > Subject: Re: Ptrace hole / Linux 2.2.25 > Date: 20 Mar 2003 07:55:45 +1200 > > Alan, > > This patch really breaks UML using the skas mode of thread tracing skas3 > patch on quite a significant amount of machines out there. The skas mode > is a lot more secure than the traditional UML tt mode. I guess this is > related to the below... > > I am running a UML site that a lot of hospitals ad clinics in Bangldesh > depend on for there email. It allows them to work around the corruption > and agrandidement of the ISPs over there. The skas3 mode patch is > needed for the site to run securely. Tracing thread mode does not cut > it. > > There are also a large number of other telehoused ISP virtual hosting > machines that use this stuff, and it is actually proving to be quite > reliable. > > I have attached the skas3 patch that Jeff Dike is currently using, and > the patch that you have produced. Could you please look into the clash > between them, and get it fixed. > > Thank you - there are lots out there who will appreciate this. > > Cheers, > > Matthew Grant > > On Mon, 2003-03-17 at 18:39, Ben Pfaff wrote: > > I am concerned about this change because it will break sandboxing > > software that I have written, which uses prctl() to turn > > dumpability back on so that it can open a file, setuid(), and > > then execve() through the open file via /proc/self/fd/#. Without > > calling prctl(), the ownership of /proc/self/fd/* becomes root, > > so the process cannot exec it after it drops privileges. It uses > > prctl() in other places to get the same effect in /proc, but > > that's one of the most critical. > > The dumpability is per mm, which means that you have to consider > all the cases of a thread being created in parallel to dumpability > being enabled. > > So consider a three threaded process. Thread one triggers kernel thread > creation, thread two turns dumpability back on, thread three ptraces > the new kernel thread. > > Proving that is safe is non trivial so the current patch chooses not > to attempt it. For 2.4.21 proper someone can sit down and do the needed > verification if they wish > > -- > > =============================================================================== > Matthew Grant /\ ^/\^ [EMAIL PROTECTED] /~~~~\ > A Linux Network Guy /~~\^/~~\_/~~~~~\_______/~~~~~~~~~~\____/******\ > ===GPG KeyID: 2EE20270 FingerPrint: > 8C2535E1A11DF3EA5EA19125BA4E790E2EE20270== > > ________________________________________________________________________ > > diff -Naur host/arch/i386/config.in host-ptrace/arch/i386/config.in > --- host/arch/i386/config.in Fri Aug 9 15:57:14 2002 > +++ host-ptrace/arch/i386/config.in Sun Nov 10 18:40:09 2002 > @@ -291,6 +291,8 @@ > bool ' Use real mode APM BIOS call to power off' > CONFIG_APM_REAL_MODE_POWER_OFF > fi > > +bool '/proc/mm' CONFIG_PROC_MM > + > endmenu > > source drivers/mtd/Config.in > diff -Naur host/arch/i386/kernel/ldt.c host-ptrace/arch/i386/kernel/ldt.c > --- host/arch/i386/kernel/ldt.c Fri Oct 26 00:01:41 2001 > +++ host-ptrace/arch/i386/kernel/ldt.c Sun Nov 3 18:37:48 2002 > @@ -24,11 +24,12 @@ > * assured by user-space anyway. Writes are atomic, to protect > * the security checks done on new descriptors. > */ > -static int read_ldt(void * ptr, unsigned long bytecount) > +static int read_ldt(struct task_struct *task, void * ptr, > + unsigned long bytecount) > { > int err; > unsigned long size; > - struct mm_struct * mm = current->mm; > + struct mm_struct * mm = task->mm; > > err = 0; > if (!mm->context.segments) > @@ -64,9 +65,10 @@ > return err; > } > > -static int write_ldt(void * ptr, unsigned long bytecount, int oldmode) > +static int write_ldt(struct task_struct *task, void * ptr, > + unsigned long bytecount, int oldmode) > { > - struct mm_struct * mm = current->mm; > + struct mm_struct * mm = task->mm; > __u32 entry_1, entry_2, *lp; > int error; > struct modify_ldt_ldt_s ldt_info; > @@ -148,23 +150,29 @@ > return error; > } > > -asmlinkage int sys_modify_ldt(int func, void *ptr, unsigned long bytecount) > +int modify_ldt(struct task_struct *task, int func, void *ptr, > + unsigned long bytecount) > { > int ret = -ENOSYS; > > switch (func) { > case 0: > - ret = read_ldt(ptr, bytecount); > + ret = read_ldt(task, ptr, bytecount); > break; > case 1: > - ret = write_ldt(ptr, bytecount, 1); > + ret = write_ldt(task, ptr, bytecount, 1); > break; > case 2: > ret = read_default_ldt(ptr, bytecount); > break; > case 0x11: > - ret = write_ldt(ptr, bytecount, 0); > + ret = write_ldt(task, ptr, bytecount, 0); > break; > } > return ret; > +} > + > +asmlinkage int sys_modify_ldt(int func, void *ptr, unsigned long bytecount) > +{ > + return(modify_ldt(current, func, ptr, bytecount)); > } > diff -Naur host/arch/i386/kernel/process.c > host-ptrace/arch/i386/kernel/process.c > --- host/arch/i386/kernel/process.c Fri Aug 9 15:57:14 2002 > +++ host-ptrace/arch/i386/kernel/process.c Wed Nov 6 22:12:45 2002 > @@ -551,13 +551,11 @@ > * we do not have to muck with descriptors here, that is > * done in switch_mm() as needed. > */ > -void copy_segments(struct task_struct *p, struct mm_struct *new_mm) > +void mm_copy_segments(struct mm_struct *old_mm, struct mm_struct *new_mm) > { > - struct mm_struct * old_mm; > void *old_ldt, *ldt; > > ldt = NULL; > - old_mm = current->mm; > if (old_mm && (old_ldt = old_mm->context.segments) != NULL) { > /* > * Completely new LDT, we initialize it from the parent: > @@ -570,6 +568,16 @@ > } > new_mm->context.segments = ldt; > new_mm->context.cpuvalid = ~0UL; /* valid on all CPU's - they > can't have stale data */ > +} > + > +void copy_segments(struct task_struct *p, struct mm_struct *new_mm) > +{ > + mm_copy_segments(current->mm, new_mm); > +} > + > +void copy_task_segments(struct task_struct *from, struct mm_struct *new_mm) > +{ > + mm_copy_segments(from->mm, new_mm); > } > > /* > diff -Naur host/arch/i386/kernel/ptrace.c > host-ptrace/arch/i386/kernel/ptrace.c > --- host/arch/i386/kernel/ptrace.c Fri Aug 9 15:57:14 2002 > +++ host-ptrace/arch/i386/kernel/ptrace.c Mon Nov 11 19:03:38 2002 > @@ -147,6 +147,11 @@ > put_stack_long(child, EFL_OFFSET, tmp); > } > > +extern int modify_ldt(struct task_struct *task, int func, void *ptr, > + unsigned long bytecount); > + > +extern struct mm_struct *proc_mm_get_mm(int fd); > + > asmlinkage int sys_ptrace(long request, long pid, long addr, long data) > { > struct task_struct *child; > @@ -415,6 +420,53 @@ > child->ptrace |= PT_TRACESYSGOOD; > else > child->ptrace &= ~PT_TRACESYSGOOD; > + ret = 0; > + break; > + } > + > + case PTRACE_FAULTINFO: { > + struct ptrace_faultinfo fault; > + > + fault = ((struct ptrace_faultinfo) > + { .is_write = child->thread.error_code, > + .addr = child->thread.cr2 }); > + ret = copy_to_user((unsigned long *) data, &fault, > + sizeof(fault)); > + if(ret) > + break; > + break; > + } > + case PTRACE_SIGPENDING: > + ret = copy_to_user((unsigned long *) data, > + &child->pending.signal, > + sizeof(child->pending.signal)); > + break; > + > + case PTRACE_LDT: { > + struct ptrace_ldt ldt; > + > + if(copy_from_user(&ldt, (unsigned long *) data, > + sizeof(ldt))){ > + ret = -EIO; > + break; > + } > + ret = modify_ldt(child, ldt.func, ldt.ptr, ldt.bytecount); > + break; > + } > + > + case PTRACE_SWITCH_MM: { > + struct mm_struct *old = child->mm; > + struct mm_struct *new = proc_mm_get_mm(data); > + > + if(IS_ERR(new)){ > + ret = PTR_ERR(new); > + break; > + } > + > + atomic_inc(&new->mm_users); > + child->mm = new; > + child->active_mm = new; > + mmput(old); > ret = 0; > break; > } > diff -Naur host/arch/i386/kernel/sys_i386.c > host-ptrace/arch/i386/kernel/sys_i386.c > --- host/arch/i386/kernel/sys_i386.c Mon Mar 19 15:35:09 2001 > +++ host-ptrace/arch/i386/kernel/sys_i386.c Mon Nov 11 17:23:25 2002 > @@ -40,7 +40,7 @@ > } > > /* common code for old and new mmaps */ > -static inline long do_mmap2( > +long do_mmap2(struct mm_struct *mm, > unsigned long addr, unsigned long len, > unsigned long prot, unsigned long flags, > unsigned long fd, unsigned long pgoff) > @@ -55,9 +55,9 @@ > goto out; > } > > - down_write(¤t->mm->mmap_sem); > - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); > - up_write(¤t->mm->mmap_sem); > + down_write(&mm->mmap_sem); > + error = do_mmap_pgoff(mm, file, addr, len, prot, flags, pgoff); > + up_write(&mm->mmap_sem); > > if (file) > fput(file); > @@ -69,7 +69,7 @@ > unsigned long prot, unsigned long flags, > unsigned long fd, unsigned long pgoff) > { > - return do_mmap2(addr, len, prot, flags, fd, pgoff); > + return do_mmap2(current->mm, addr, len, prot, flags, fd, pgoff); > } > > /* > @@ -100,7 +100,7 @@ > if (a.offset & ~PAGE_MASK) > goto out; > > - err = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> > PAGE_SHIFT); > + err = do_mmap2(current->mm, a.addr, a.len, a.prot, a.flags, a.fd, > a.offset >> PAGE_SHIFT); > out: > return err; > } > diff -Naur host/include/asm-i386/processor.h > host-ptrace/include/asm-i386/processor.h > --- host/include/asm-i386/processor.h Sun Nov 10 18:47:37 2002 > +++ host-ptrace/include/asm-i386/processor.h Mon Nov 11 17:33:30 2002 > @@ -436,6 +436,8 @@ > extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long > flags); > > /* Copy and release all segment info associated with a VM */ > +extern void mm_copy_segments(struct mm_struct *old_mm, > + struct mm_struct *new_mm); > extern void copy_segments(struct task_struct *p, struct mm_struct * mm); > extern void release_segments(struct mm_struct * mm); > > diff -Naur host/include/asm-i386/ptrace.h > host-ptrace/include/asm-i386/ptrace.h > --- host/include/asm-i386/ptrace.h Sun Sep 23 19:20:51 2001 > +++ host-ptrace/include/asm-i386/ptrace.h Sun Nov 10 18:36:22 2002 > @@ -51,6 +51,22 @@ > > #define PTRACE_SETOPTIONS 21 > > +struct ptrace_faultinfo { > + int is_write; > + unsigned long addr; > +}; > + > +struct ptrace_ldt { > + int func; > + void *ptr; > + unsigned long bytecount; > +}; > + > +#define PTRACE_FAULTINFO 52 > +#define PTRACE_SIGPENDING 53 > +#define PTRACE_LDT 54 > +#define PTRACE_SWITCH_MM 55 > + > /* options set using PTRACE_SETOPTIONS */ > #define PTRACE_O_TRACESYSGOOD 0x00000001 > > diff -Naur host/include/linux/mm.h host-ptrace/include/linux/mm.h > --- host/include/linux/mm.h Fri Aug 30 15:03:44 2002 > +++ host-ptrace/include/linux/mm.h Mon Nov 11 19:08:53 2002 > @@ -492,6 +492,9 @@ > int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, unsigned > long start, > int len, int write, int force, struct page **pages, struct > vm_area_struct **vmas); > > +extern long do_mprotect(struct mm_struct *mm, unsigned long start, > + size_t len, unsigned long prot); > + > /* > * On a two-level page table, this ends up being trivial. Thus the > * inlining and the symmetry break with pte_alloc() that does all > @@ -539,9 +542,10 @@ > > extern unsigned long get_unmapped_area(struct file *, unsigned long, > unsigned long, unsigned long, unsigned long); > > -extern unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, > - unsigned long len, unsigned long prot, > - unsigned long flag, unsigned long pgoff); > +extern unsigned long do_mmap_pgoff(struct mm_struct *mm, > + struct file *file, unsigned long addr, > + unsigned long len, unsigned long prot, > + unsigned long flag, unsigned long pgoff); > > static inline unsigned long do_mmap(struct file *file, unsigned long addr, > unsigned long len, unsigned long prot, > @@ -551,7 +555,7 @@ > if ((offset + PAGE_ALIGN(len)) < offset) > goto out; > if (!(offset & ~PAGE_MASK)) > - ret = do_mmap_pgoff(file, addr, len, prot, flag, offset >> > PAGE_SHIFT); > + ret = do_mmap_pgoff(current->mm, file, addr, len, prot, flag, > offset >> PAGE_SHIFT); > out: > return ret; > } > diff -Naur host/include/linux/proc_mm.h host-ptrace/include/linux/proc_mm.h > --- host/include/linux/proc_mm.h Wed Dec 31 19:00:00 1969 > +++ host-ptrace/include/linux/proc_mm.h Mon Nov 11 17:41:09 2002 > @@ -0,0 +1,44 @@ > +/* > + * Copyright (C) 2002 Jeff Dike ([EMAIL PROTECTED]) > + * Licensed under the GPL > + */ > + > +#ifndef __PROC_MM_H > +#define __PROC_MM_H > + > +#define MM_MMAP 54 > +#define MM_MUNMAP 55 > +#define MM_MPROTECT 56 > +#define MM_COPY_SEGMENTS 57 > + > +struct mm_mmap { > + unsigned long addr; > + unsigned long len; > + unsigned long prot; > + unsigned long flags; > + unsigned long fd; > + unsigned long offset; > +}; > + > +struct mm_munmap { > + unsigned long addr; > + unsigned long len; > +}; > + > +struct mm_mprotect { > + unsigned long addr; > + unsigned long len; > + unsigned int prot; > +}; > + > +struct proc_mm_op { > + int op; > + union { > + struct mm_mmap mmap; > + struct mm_munmap munmap; > + struct mm_mprotect mprotect; > + int copy_segments; > + } u; > +}; > + > +#endif > diff -Naur host/mm/Makefile host-ptrace/mm/Makefile > --- host/mm/Makefile Fri Aug 9 15:57:31 2002 > +++ host-ptrace/mm/Makefile Sun Nov 10 18:37:33 2002 > @@ -17,5 +17,6 @@ > shmem.o > > obj-$(CONFIG_HIGHMEM) += highmem.o > +obj-$(CONFIG_PROC_MM) += proc_mm.o > > include $(TOPDIR)/Rules.make > diff -Naur host/mm/mmap.c host-ptrace/mm/mmap.c > --- host/mm/mmap.c Fri Aug 9 15:57:31 2002 > +++ host-ptrace/mm/mmap.c Mon Nov 11 17:24:18 2002 > @@ -390,10 +390,11 @@ > return 0; > } > > -unsigned long do_mmap_pgoff(struct file * file, unsigned long addr, > unsigned long len, > - unsigned long prot, unsigned long flags, unsigned long pgoff) > +unsigned long do_mmap_pgoff(struct mm_struct *mm, struct file * file, > + unsigned long addr, unsigned long len, > + unsigned long prot, unsigned long flags, > + unsigned long pgoff) > { > - struct mm_struct * mm = current->mm; > struct vm_area_struct * vma, * prev; > unsigned int vm_flags; > int correct_wcount = 0; > diff -Naur host/mm/mprotect.c host-ptrace/mm/mprotect.c > --- host/mm/mprotect.c Fri Aug 9 15:57:31 2002 > +++ host-ptrace/mm/mprotect.c Mon Nov 11 17:47:58 2002 > @@ -264,7 +264,8 @@ > return 0; > } > > -asmlinkage long sys_mprotect(unsigned long start, size_t len, unsigned long > prot) > +long do_mprotect(struct mm_struct *mm, unsigned long start, size_t len, > + unsigned long prot) > { > unsigned long nstart, end, tmp; > struct vm_area_struct * vma, * next, * prev; > @@ -281,9 +282,9 @@ > if (end == start) > return 0; > > - down_write(¤t->mm->mmap_sem); > + down_write(&mm->mmap_sem); > > - vma = find_vma_prev(current->mm, start, &prev); > + vma = find_vma_prev(mm, start, &prev); > error = -ENOMEM; > if (!vma || vma->vm_start > start) > goto out; > @@ -332,6 +333,11 @@ > prev->vm_mm->map_count--; > } > out: > - up_write(¤t->mm->mmap_sem); > + up_write(&mm->mmap_sem); > return error; > +} > + > +asmlinkage long sys_mprotect(unsigned long start, size_t len, unsigned long > prot) > +{ > + return(do_mprotect(current->mm, start, len, prot)); > } > diff -Naur host/mm/proc_mm.c host-ptrace/mm/proc_mm.c > --- host/mm/proc_mm.c Wed Dec 31 19:00:00 1969 > +++ host-ptrace/mm/proc_mm.c Mon Nov 11 19:07:52 2002 > @@ -0,0 +1,173 @@ > +/* > + * Copyright (C) 2002 Jeff Dike ([EMAIL PROTECTED]) > + * Licensed under the GPL > + */ > + > +#include "linux/proc_fs.h" > +#include "linux/proc_mm.h" > +#include "linux/file.h" > +#include "asm/uaccess.h" > +#include "asm/mmu_context.h" > + > +static struct file_operations proc_mm_fops; > + > +struct mm_struct *proc_mm_get_mm(int fd) > +{ > + struct mm_struct *ret = ERR_PTR(-EBADF); > + struct file *file; > + > + file = fget(fd); > + if (!file) > + goto out; > + > + ret = ERR_PTR(-EINVAL); > + if(file->f_op != &proc_mm_fops) > + goto out_fput; > + > + ret = file->private_data; > + > + out_fput: > + fput(file); > + out: > + return(ret); > +} > + > +extern long do_mmap2(struct mm_struct *mm, unsigned long addr, > + unsigned long len, unsigned long prot, > + unsigned long flags, unsigned long fd, > + unsigned long pgoff); > + > +static ssize_t write_proc_mm(struct file *file, const char *buffer, > + size_t count, loff_t *ppos) > +{ > + struct mm_struct *mm = file->private_data; > + struct proc_mm_op req; > + int n, ret; > + > + if(count > sizeof(req)) > + return(-EINVAL); > + > + n = copy_from_user(&req, buffer, count); > + if(n != 0) > + return(-EFAULT); > + > + ret = count; > + switch(req.op){ > + case MM_MMAP: { > + struct mm_mmap *map = &req.u.mmap; > + > + ret = do_mmap2(mm, map->addr, map->len, map->prot, > + map->flags, map->fd, map->offset >> PAGE_SHIFT); > + if((ret & ~PAGE_MASK) == 0) > + ret = count; > + > + break; > + } > + case MM_MUNMAP: { > + struct mm_munmap *unmap = &req.u.munmap; > + > + down_write(&mm->mmap_sem); > + ret = do_munmap(mm, unmap->addr, unmap->len); > + up_write(&mm->mmap_sem); > + > + if(ret == 0) > + ret = count; > + break; > + } > + case MM_MPROTECT: { > + struct mm_mprotect *protect = &req.u.mprotect; > + > + ret = do_mprotect(mm, protect->addr, protect->len, > + protect->prot); > + if(ret == 0) > + ret = count; > + break; > + } > + > + case MM_COPY_SEGMENTS: { > + struct mm_struct *from = proc_mm_get_mm(req.u.copy_segments); > + > + if(IS_ERR(from)){ > + ret = PTR_ERR(from); > + break; > + } > + > + mm_copy_segments(from, mm); > + break; > + } > + default: > + ret = -EINVAL; > + break; > + } > + > + return(ret); > +} > + > +static int open_proc_mm(struct inode *inode, struct file *file) > +{ > + struct mm_struct *mm = mm_alloc(); > + int ret; > + > + ret = -ENOMEM; > + if(mm == NULL) > + goto out_mem; > + > + ret = init_new_context(current, mm); > + if(ret) > + goto out_free; > + > + spin_lock(&mmlist_lock); > + list_add(&mm->mmlist, ¤t->mm->mmlist); > + mmlist_nr++; > + spin_unlock(&mmlist_lock); > + > + file->private_data = mm; > + > + return(0); > + > + out_free: > + mmput(mm); > + out_mem: > + return(ret); > +} > + > +static int release_proc_mm(struct inode *inode, struct file *file) > +{ > + struct mm_struct *mm = file->private_data; > + > + mmput(mm); > + return(0); > +} > + > +static struct file_operations proc_mm_fops = { > + .open = open_proc_mm, > + .release = release_proc_mm, > + .write = write_proc_mm, > +}; > + > +static int make_proc_mm(void) > +{ > + struct proc_dir_entry *ent; > + > + ent = create_proc_entry("mm", 0222, &proc_root); > + if(ent == NULL){ > + printk("make_proc_mm : Failed to register /proc/mm\n"); > + return(0); > + } > + ent->proc_fops = &proc_mm_fops; > + > + return(0); > +} > + > +__initcall(make_proc_mm); > + > +/* > + * Overrides for Emacs so that we follow Linus's tabbing style. > + * Emacs will notice this stuff at the end of the file and automatically > + * adjust the settings for this buffer only. This must remain at the end > + * of the file. > + * > --------------------------------------------------------------------------- > + * Local variables: > + * c-file-style: "linux" > + * End: > + */ > > ________________________________________________________________________ > > LWN.net Logo > > > Sponsored > Link > > TrustCommerce > > E-Commerce & credit card processing - the Open Source way! > > ___________________________________________________________________________________________________________________________________ > > You are not logged in > Log in now > Create an account > Subscribe to LWN > > Recent Features > > LWN.net Weekly Edition for March 13, 2003 > > A look at the SCO complaint > > LWN.net Weekly Edition for March 6, 2003 > > LWN.net Weekly Edition for February 27, 2003 > > LWN.net Weekly Edition for February 20, 2003 > > Printable page > > > Home Weekly edition Archives Security Calendar > Distributions Penguin Gallery Kernel patches Search Old site > LWN.net FAQ Subscriptions Advertise Headlines Privacy > > Ptrace vulnerability in 2.2 and 2.4 kernels > > From: Alan Cox <[EMAIL PROTECTED]> > To: [EMAIL PROTECTED], [EMAIL PROTECTED], [EMAIL PROTECTED], [EMAIL > PROTECTED], [EMAIL PROTECTED], [EMAIL PROTECTED], > [EMAIL PROTECTED], [EMAIL PROTECTED], [EMAIL PROTECTED], [EMAIL PROTECTED] > Subject: Ptrace vulnerability in Linux 2.2/2.4 > Date: Mon, 17 Mar 2003 11:00:16 -0500 (EST) > > Vulnerability: CAN-2003-0127 > > The Linux 2.2 and Linux 2.4 kernels have a flaw in ptrace. This hole allows > local users to obtain full privileges. Remote exploitation of this hole is > not possible. Linux 2.5 is not believed to be vulnerable. > > Linux 2.2.25 has been released to correct Linux 2.2. It contains no other > changes. The bug fixes that would have been in 2.2.5pre1 will now appear in > 2.2.26pre1. The patch will apply directly to most older 2.2 releases. > > A patch for Linux 2.4.20/Linux 2.4.21pre is attached. The patch also > subtly changes the PR_SET_DUMPABLE prctl. We believe this is neccessary and > that it will not affect any software. The functionality change is specific > to unusual debugging situations. > > We would like to thank Andrzej Szombierski who found the problem, and > wrote an initial patch. Seth Arnold cleaned up the 2.2 change. Arjan van > de Ven and Ben LaHaise identified additional problems with the original > fix. > > Alan > > diff -purN linux.orig/arch/alpha/kernel/entry.S > linux/arch/alpha/kernel/entry.S > --- linux.orig/arch/alpha/kernel/entry.S Thu Mar 13 12:01:46 2003 > +++ linux/arch/alpha/kernel/entry.S Thu Mar 13 13:28:49 2003 > @@ -231,12 +231,12 @@ kernel_clone: > .end kernel_clone > > /* > - * kernel_thread(fn, arg, clone_flags) > + * arch_kernel_thread(fn, arg, clone_flags) > */ > .align 3 > .globl kernel_thread > .ent kernel_thread > -kernel_thread: > +arch_kernel_thread: > ldgp $29,0($27) /* we can be called from a module */ > .frame $30, 4*8, $26 > subq $30,4*8,$30 > diff -purN linux.orig/arch/arm/kernel/process.c > linux/arch/arm/kernel/process.c > --- linux.orig/arch/arm/kernel/process.c Thu Mar 13 12:01:29 2003 > +++ linux/arch/arm/kernel/process.c Thu Mar 13 13:25:56 2003 > @@ -366,7 +366,7 @@ void dump_thread(struct pt_regs * regs, > * a system call from a "real" process, but the process memory space will > * not be free'd until both the parent and the child have exited. > */ > -pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) > +pid_t arch_kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) > { > pid_t __ret; > > diff -purN linux.orig/arch/cris/kernel/entry.S linux/arch/cris/kernel/entry.S > --- linux.orig/arch/cris/kernel/entry.S Thu Mar 13 12:01:29 2003 > +++ linux/arch/cris/kernel/entry.S Thu Mar 13 13:30:30 2003 > @@ -736,12 +736,12 @@ hw_bp_trig_ptr: > * the grosser the code, at least with the gcc version in cris-dist-1.13. > */ > > -/* int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) */ > +/* int arch_kernel_thread(int (*fn)(void *), void * arg, unsigned long > flags) */ > /* r10 r11 r12 */ > > .text > - .global kernel_thread > -kernel_thread: > + .global arch_kernel_thread > +arch_kernel_thread: > > /* Save ARG for later. */ > move.d $r11, $r13 > diff -purN linux.orig/arch/i386/kernel/process.c > linux/arch/i386/kernel/process.c > --- linux.orig/arch/i386/kernel/process.c Thu Mar 13 12:01:57 2003 > +++ linux/arch/i386/kernel/process.c Thu Mar 13 13:26:08 2003 > @@ -495,7 +495,7 @@ void release_segments(struct mm_struct * > /* > * Create a kernel thread > */ > -int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) > +int arch_kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) > { > long retval, d0; > > @@ -518,6 +518,7 @@ int kernel_thread(int (*fn)(void *), voi > "r" (arg), "r" (fn), > "b" (flags | CLONE_VM) > : "memory"); > + > return retval; > } > > diff -purN linux.orig/arch/ia64/kernel/process.c > linux/arch/ia64/kernel/process.c > --- linux.orig/arch/ia64/kernel/process.c Thu Mar 13 12:01:29 2003 > +++ linux/arch/ia64/kernel/process.c Thu Mar 13 13:26:15 2003 > @@ -220,7 +220,7 @@ ia64_load_extra (struct task_struct *tas > * | | <-- sp (lowest addr) > * +---------------------+ > * > - * Note: if we get called through kernel_thread() then the memory > + * Note: if we get called through arch_kernel_thread() then the memory > * above "(highest addr)" is valid kernel stack memory that needs to > * be copied as well. > * > @@ -469,7 +469,7 @@ ia64_set_personality (struct elf64_hdr * > } > > pid_t > -kernel_thread (int (*fn)(void *), void *arg, unsigned long flags) > +arch_kernel_thread (int (*fn)(void *), void *arg, unsigned long flags) > { > struct task_struct *parent = current; > int result, tid; > diff -purN linux.orig/arch/m68k/kernel/process.c > linux/arch/m68k/kernel/process.c > --- linux.orig/arch/m68k/kernel/process.c Thu Mar 13 12:01:29 2003 > +++ linux/arch/m68k/kernel/process.c Thu Mar 13 13:26:18 2003 > @@ -124,7 +124,7 @@ void show_regs(struct pt_regs * regs) > /* > * Create a kernel thread > */ > -int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) > +int arch_kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) > { > int pid; > mm_segment_t fs; > diff -purN linux.orig/arch/mips/kernel/process.c > linux/arch/mips/kernel/process.c > --- linux.orig/arch/mips/kernel/process.c Thu Mar 13 12:01:29 2003 > +++ linux/arch/mips/kernel/process.c Thu Mar 13 13:26:28 2003 > @@ -155,7 +155,7 @@ void dump_thread(struct pt_regs *regs, s > /* > * Create a kernel thread > */ > -int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) > +int arch_kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) > { > long retval; > > diff -purN linux.orig/arch/mips64/kernel/process.c > linux/arch/mips64/kernel/process.c > --- linux.orig/arch/mips64/kernel/process.c Thu Mar 13 12:01:29 2003 > +++ linux/arch/mips64/kernel/process.c Thu Mar 13 13:26:23 2003 > @@ -152,7 +152,7 @@ void dump_thread(struct pt_regs *regs, s > /* > * Create a kernel thread > */ > -int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) > +int arch_kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) > { > int retval; > > diff -purN linux.orig/arch/parisc/kernel/process.c > linux/arch/parisc/kernel/process.c > --- linux.orig/arch/parisc/kernel/process.c Fri Feb 9 14:29:44 2001 > +++ linux/arch/parisc/kernel/process.c Thu Mar 13 13:26:36 2003 > @@ -118,7 +118,7 @@ void machine_heartbeat(void) > */ > > extern pid_t __kernel_thread(int (*fn)(void *), void *arg, unsigned long > flags); > -pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) > +pid_t arch_kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) > { > > /* > diff -purN linux.orig/arch/ppc/kernel/misc.S linux/arch/ppc/kernel/misc.S > --- linux.orig/arch/ppc/kernel/misc.S Thu Mar 13 12:01:29 2003 > +++ linux/arch/ppc/kernel/misc.S Thu Mar 13 13:32:21 2003 > @@ -899,9 +899,9 @@ _GLOBAL(cvt_df) > > /* > * Create a kernel thread > - * kernel_thread(fn, arg, flags) > + * arch_kernel_thread(fn, arg, flags) > */ > -_GLOBAL(kernel_thread) > +_GLOBAL(arch_kernel_thread) > mr r6,r3 /* function */ > ori r3,r5,CLONE_VM /* flags */ > li r0,__NR_clone > diff -purN linux.orig/arch/ppc64/kernel/misc.S linux/arch/ppc64/kernel/misc.S > --- linux.orig/arch/ppc64/kernel/misc.S Thu Mar 13 12:01:30 2003 > +++ linux/arch/ppc64/kernel/misc.S Thu Mar 13 13:29:42 2003 > @@ -493,9 +493,9 @@ _GLOBAL(cvt_df) > > /* > * Create a kernel thread > - * kernel_thread(fn, arg, flags) > + * arch_kernel_thread(fn, arg, flags) > */ > -_GLOBAL(kernel_thread) > +_GLOBAL(arch_kernel_thread) > mr r6,r3 /* function */ > ori r3,r5,CLONE_VM /* flags */ > li r0,__NR_clone > diff -purN linux.orig/arch/s390/kernel/process.c > linux/arch/s390/kernel/process.c > --- linux.orig/arch/s390/kernel/process.c Thu Mar 13 12:01:30 2003 > +++ linux/arch/s390/kernel/process.c Thu Mar 13 13:26:43 2003 > @@ -105,7 +105,7 @@ void show_regs(struct pt_regs *regs) > show_trace((unsigned long *) regs->gprs[15]); > } > > -int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) > +int arch_kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) > { > int clone_arg = flags | CLONE_VM; > int retval; > diff -purN linux.orig/arch/s390x/kernel/process.c > linux/arch/s390x/kernel/process.c > --- linux.orig/arch/s390x/kernel/process.c Thu Mar 13 12:01:30 2003 > +++ linux/arch/s390x/kernel/process.c Thu Mar 13 13:26:46 2003 > @@ -102,7 +102,7 @@ void show_regs(struct pt_regs *regs) > show_trace((unsigned long *) regs->gprs[15]); > } > > -int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) > +int arch_kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) > { > int clone_arg = flags | CLONE_VM; > int retval; > diff -purN linux.orig/arch/sh/kernel/process.c linux/arch/sh/kernel/process.c > --- linux.orig/arch/sh/kernel/process.c Mon Oct 15 16:36:48 2001 > +++ linux/arch/sh/kernel/process.c Thu Mar 13 13:26:49 2003 > @@ -118,7 +118,7 @@ void free_task_struct(struct task_struct > * This is the mechanism for creating a new kernel thread. > * > */ > -int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) > +int arch_kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) > { /* Don't use this in BL=1(cli). Or else, CPU resets! */ > register unsigned long __sc0 __asm__ ("r0"); > register unsigned long __sc3 __asm__ ("r3") = __NR_clone; > diff -purN linux.orig/arch/sparc/kernel/process.c > linux/arch/sparc/kernel/process.c > --- linux.orig/arch/sparc/kernel/process.c Thu Mar 13 12:01:30 2003 > +++ linux/arch/sparc/kernel/process.c Thu Mar 13 13:26:58 2003 > @@ -676,7 +676,7 @@ out: > * a system call from a "real" process, but the process memory space will > * not be free'd until both the parent and the child have exited. > */ > -pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) > +pid_t arch_kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) > { > long retval; > > diff -purN linux.orig/arch/sparc64/kernel/process.c > linux/arch/sparc64/kernel/process.c > --- linux.orig/arch/sparc64/kernel/process.c Thu Mar 13 12:01:30 2003 > +++ linux/arch/sparc64/kernel/process.c Thu Mar 13 13:26:54 2003 > @@ -658,7 +658,7 @@ int copy_thread(int nr, unsigned long cl > * a system call from a "real" process, but the process memory space will > * not be free'd until both the parent and the child have exited. > */ > -pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) > +pid_t arch_kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) > { > long retval; > > diff -purN linux.orig/arch/um/kernel/process_kern.c > linux/arch/um/kernel/process_kern.c > --- linux.orig/arch/um/kernel/process_kern.c Thu Mar 13 12:01:48 2003 > +++ linux/arch/um/kernel/process_kern.c Thu Mar 13 13:27:37 2003 > @@ -171,14 +171,14 @@ static int new_thread_proc(void *stack) > os_usr1_process(os_getpid()); > } > > -int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) > +int arch_kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) > { > int pid; > > current->thread.request.u.thread.proc = fn; > current->thread.request.u.thread.arg = arg; > pid = do_fork(CLONE_VM | flags, 0, NULL, 0); > - if(pid < 0) panic("do_fork failed in kernel_thread"); > + if(pid < 0) panic("do_fork failed in arch_kernel_thread"); > return(pid); > } > > diff -purN linux.orig/fs/exec.c linux/fs/exec.c > --- linux.orig/fs/exec.c Thu Mar 13 12:01:46 2003 > +++ linux/fs/exec.c Thu Mar 13 14:19:08 2003 > @@ -559,8 +559,10 @@ int flush_old_exec(struct linux_binprm * > > current->sas_ss_sp = current->sas_ss_size = 0; > > - if (current->euid == current->uid && current->egid == current->gid) > + if (current->euid == current->uid && current->egid == current->gid) { > current->mm->dumpable = 1; > + current->task_dumpable = 1; > + } > name = bprm->filename; > for (i=0; (ch = *(name++)) != '\0';) { > if (ch == '/') > @@ -952,7 +954,7 @@ int do_coredump(long signr, struct pt_re > binfmt = current->binfmt; > if (!binfmt || !binfmt->core_dump) > goto fail; > - if (!current->mm->dumpable) > + if (!is_dumpable(current)) > goto fail; > current->mm->dumpable = 0; > if (current->rlim[RLIMIT_CORE].rlim_cur < binfmt->min_coredump) > diff -purN linux.orig/include/asm-alpha/processor.h > linux/include/asm-alpha/processor.h > --- linux.orig/include/asm-alpha/processor.h Fri Oct 5 15:11:05 2001 > +++ linux/include/asm-alpha/processor.h Thu Mar 13 13:35:18 2003 > @@ -119,7 +119,7 @@ struct task_struct; > extern void release_thread(struct task_struct *); > > /* Create a kernel thread without removing it from tasklists. */ > -extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long > flags); > +extern long arch_kernel_thread(int (*fn)(void *), void *arg, unsigned long > flags); > > #define copy_segments(tsk, mm) do { } while (0) > #define release_segments(mm) do { } while (0) > diff -purN linux.orig/include/asm-arm/processor.h > linux/include/asm-arm/processor.h > --- linux.orig/include/asm-arm/processor.h Thu Mar 13 12:01:35 2003 > +++ linux/include/asm-arm/processor.h Thu Mar 13 13:35:18 2003 > @@ -117,7 +117,7 @@ extern void __free_task_struct(struct ta > /* > * Create a new kernel thread > */ > -extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); > +extern int arch_kernel_thread(int (*fn)(void *), void *arg, unsigned long > flags); > > #endif > > diff -purN linux.orig/include/asm-cris/processor.h > linux/include/asm-cris/processor.h > --- linux.orig/include/asm-cris/processor.h Thu Mar 13 12:01:35 2003 > +++ linux/include/asm-cris/processor.h Thu Mar 13 13:35:18 2003 > @@ -81,7 +81,7 @@ struct thread_struct { > #define INIT_THREAD { \ > 0, 0, 0x20 } /* ccr = int enable, nothing else */ > > -extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long > flags); > +extern int arch_kernel_thread(int (*fn)(void *), void * arg, unsigned long > flags); > > /* give the thread a program location > * set user-mode (The 'U' flag (User mode flag) is CCR/DCCR bit 8) > diff -purN linux.orig/include/asm-i386/processor.h > linux/include/asm-i386/processor.h > --- linux.orig/include/asm-i386/processor.h Thu Mar 13 12:01:57 2003 > +++ linux/include/asm-i386/processor.h Thu Mar 13 13:51:02 2003 > @@ -433,7 +433,7 @@ extern void release_thread(struct task_s > /* > * create a kernel thread without removing it from tasklists > */ > -extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long > flags); > +extern int arch_kernel_thread(int (*fn)(void *), void * arg, unsigned long > flags); > > /* Copy and release all segment info associated with a VM */ > extern void copy_segments(struct task_struct *p, struct mm_struct * mm); > diff -purN linux.orig/include/asm-ia64/processor.h > linux/include/asm-ia64/processor.h > --- linux.orig/include/asm-ia64/processor.h Thu Mar 13 12:01:35 2003 > +++ linux/include/asm-ia64/processor.h Thu Mar 13 13:35:18 2003 > @@ -476,7 +476,7 @@ struct task_struct; > * do_basic_setup() and the timing is such that free_initmem() has > * been called already. > */ > -extern int kernel_thread (int (*fn)(void *), void *arg, unsigned long > flags); > +extern int arch_kernel_thread (int (*fn)(void *), void *arg, unsigned long > flags); > > /* Copy and release all segment info associated with a VM */ > #define copy_segments(tsk, mm) do { } while (0) > diff -purN linux.orig/include/asm-m68k/processor.h > linux/include/asm-m68k/processor.h > --- linux.orig/include/asm-m68k/processor.h Fri Oct 5 15:11:05 2001 > +++ linux/include/asm-m68k/processor.h Thu Mar 13 13:35:18 2003 > @@ -105,7 +105,7 @@ static inline void release_thread(struct > { > } > > -extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long > flags); > +extern int arch_kernel_thread(int (*fn)(void *), void * arg, unsigned long > flags); > > #define copy_segments(tsk, mm) do { } while (0) > #define release_segments(mm) do { } while (0) > diff -purN linux.orig/include/asm-mips/processor.h > linux/include/asm-mips/processor.h > --- linux.orig/include/asm-mips/processor.h Thu Mar 13 12:01:36 2003 > +++ linux/include/asm-mips/processor.h Thu Mar 13 13:35:18 2003 > @@ -186,7 +186,7 @@ struct thread_struct { > /* Free all resources held by a thread. */ > #define release_thread(thread) do { } while(0) > > -extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long > flags); > +extern int arch_kernel_thread(int (*fn)(void *), void * arg, unsigned long > flags); > > /* Copy and release all segment info associated with a VM */ > #define copy_segments(p, mm) do { } while(0) > diff -purN linux.orig/include/asm-mips64/processor.h > linux/include/asm-mips64/processor.h > --- linux.orig/include/asm-mips64/processor.h Thu Mar 13 12:01:36 2003 > +++ linux/include/asm-mips64/processor.h Thu Mar 13 13:35:18 2003 > @@ -245,7 +245,7 @@ struct thread_struct { > /* Free all resources held by a thread. */ > #define release_thread(thread) do { } while(0) > > -extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long > flags); > +extern int arch_kernel_thread(int (*fn)(void *), void * arg, unsigned long > flags); > > /* Copy and release all segment info associated with a VM */ > #define copy_segments(p, mm) do { } while(0) > diff -purN linux.orig/include/asm-parisc/processor.h > linux/include/asm-parisc/processor.h > --- linux.orig/include/asm-parisc/processor.h Fri Oct 5 15:11:05 2001 > +++ linux/include/asm-parisc/processor.h Thu Mar 13 13:35:18 2003 > @@ -305,7 +305,7 @@ struct task_struct; > > /* Free all resources held by a thread. */ > extern void release_thread(struct task_struct *); > -extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long > flags); > +extern int arch_kernel_thread(int (*fn)(void *), void * arg, unsigned long > flags); > > #define copy_segments(tsk, mm) do { } while (0) > #define release_segments(mm) do { } while (0) > diff -purN linux.orig/include/asm-ppc/processor.h > linux/include/asm-ppc/processor.h > --- linux.orig/include/asm-ppc/processor.h Thu Mar 13 12:01:36 2003 > +++ linux/include/asm-ppc/processor.h Thu Mar 13 13:35:18 2003 > @@ -593,7 +593,7 @@ void release_thread(struct task_struct * > /* > * Create a new kernel thread. > */ > -extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long > flags); > +extern long arch_kernel_thread(int (*fn)(void *), void *arg, unsigned long > flags); > > /* > * Bus types > diff -purN linux.orig/include/asm-ppc64/processor.h > linux/include/asm-ppc64/processor.h > --- linux.orig/include/asm-ppc64/processor.h Thu Mar 13 12:01:36 2003 > +++ linux/include/asm-ppc64/processor.h Thu Mar 13 13:35:18 2003 > @@ -609,7 +609,7 @@ void release_thread(struct task_struct * > /* > * Create a new kernel thread. > */ > -extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long > flags); > +extern long arch_kernel_thread(int (*fn)(void *), void *arg, unsigned long > flags); > > /* > * Bus types > diff -purN linux.orig/include/asm-s390/processor.h > linux/include/asm-s390/processor.h > --- linux.orig/include/asm-s390/processor.h Thu Mar 13 12:01:36 2003 > +++ linux/include/asm-s390/processor.h Thu Mar 13 13:35:18 2003 > @@ -113,7 +113,7 @@ struct mm_struct; > > /* Free all resources held by a thread. */ > extern void release_thread(struct task_struct *); > -extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long > flags); > +extern int arch_kernel_thread(int (*fn)(void *), void * arg, unsigned long > flags); > > /* Copy and release all segment info associated with a VM */ > #define copy_segments(nr, mm) do { } while (0) > diff -purN linux.orig/include/asm-s390x/processor.h > linux/include/asm-s390x/processor.h > --- linux.orig/include/asm-s390x/processor.h Thu Mar 13 12:01:36 2003 > +++ linux/include/asm-s390x/processor.h Thu Mar 13 13:35:18 2003 > @@ -127,7 +127,7 @@ struct mm_struct; > > /* Free all resources held by a thread. */ > extern void release_thread(struct task_struct *); > -extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long > flags); > +extern int arch_kernel_thread(int (*fn)(void *), void * arg, unsigned long > flags); > > /* Copy and release all segment info associated with a VM */ > #define copy_segments(nr, mm) do { } while (0) > diff -purN linux.orig/include/asm-sh/processor.h > linux/include/asm-sh/processor.h > --- linux.orig/include/asm-sh/processor.h Fri Oct 5 15:11:05 2001 > +++ linux/include/asm-sh/processor.h Thu Mar 13 13:35:18 2003 > @@ -137,7 +137,7 @@ extern void release_thread(struct task_s > /* > * create a kernel thread without removing it from tasklists > */ > -extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long > flags); > +extern int arch_kernel_thread(int (*fn)(void *), void * arg, unsigned long > flags); > > /* > * Bus types > diff -purN linux.orig/include/asm-sparc/processor.h > linux/include/asm-sparc/processor.h > --- linux.orig/include/asm-sparc/processor.h Thu Oct 11 02:42:47 2001 > +++ linux/include/asm-sparc/processor.h Thu Mar 13 13:35:18 2003 > @@ -146,7 +146,7 @@ extern __inline__ void start_thread(stru > > /* Free all resources held by a thread. */ > #define release_thread(tsk) do { } while(0) > -extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long > flags); > +extern pid_t arch_kernel_thread(int (*fn)(void *), void * arg, unsigned > long flags); > > > #define copy_segments(tsk, mm) do { } while (0) > diff -purN linux.orig/include/asm-sparc64/processor.h > linux/include/asm-sparc64/processor.h > --- linux.orig/include/asm-sparc64/processor.h Thu Mar 13 12:01:36 2003 > +++ linux/include/asm-sparc64/processor.h Thu Mar 13 13:35:18 2003 > @@ -270,7 +270,7 @@ do { \ > /* Free all resources held by a thread. */ > #define release_thread(tsk) do { } while(0) > > -extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long > flags); > +extern pid_t arch_kernel_thread(int (*fn)(void *), void * arg, unsigned > long flags); > > #define copy_segments(tsk, mm) do { } while (0) > #define release_segments(mm) do { } while (0) > diff -purN linux.orig/include/linux/sched.h linux/include/linux/sched.h > --- linux.orig/include/linux/sched.h Thu Mar 13 12:01:57 2003 > +++ linux/include/linux/sched.h Thu Mar 13 13:54:05 2003 > @@ -362,6 +362,7 @@ struct task_struct { > /* ??? */ > unsigned long personality; > int did_exec:1; > + unsigned task_dumpable:1; > pid_t pid; > pid_t pgrp; > pid_t tty_old_pgrp; > @@ -485,6 +486,8 @@ struct task_struct { > #define PT_TRACESYSGOOD 0x00000008 > #define PT_PTRACE_CAP 0x00000010 /* ptracer can follow suid-exec */ > > +#define is_dumpable(tsk) ((tsk)->task_dumpable && (tsk)->mm->dumpable) > + > /* > * Limit the stack by to some sane default: root can always > * increase this limit if needed.. 8MB seems reasonable. > @@ -848,6 +851,8 @@ extern void FASTCALL(remove_wait_queue(w > > extern void wait_task_inactive(task_t * p); > extern void kick_if_running(task_t * p); > +extern long kernel_thread(int (*fn)(void *), void * arg, unsigned long > flags); > + > > #define __wait_event(wq, condition) \ > do { \ > diff -purN linux.orig/kernel/fork.c linux/kernel/fork.c > --- linux.orig/kernel/fork.c Thu Mar 13 12:01:57 2003 > +++ linux/kernel/fork.c Thu Mar 13 13:51:24 2003 > @@ -28,6 +28,7 @@ > #include <asm/pgalloc.h> > #include <asm/uaccess.h> > #include <asm/mmu_context.h> > +#include <asm/processor.h> > > /* The idle threads do not count.. */ > int nr_threads; > @@ -575,6 +576,31 @@ static inline void copy_flags(unsigned l > p->flags = new_flags; > } > > +long kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) > +{ > + struct task_struct *task = current; > + unsigned old_task_dumpable; > + long ret; > + > + /* lock out any potential ptracer */ > + task_lock(task); > + if (task->ptrace) { > + task_unlock(task); > + return -EPERM; > + } > + > + old_task_dumpable = task->task_dumpable; > + task->task_dumpable = 0; > + task_unlock(task); > + > + ret = arch_kernel_thread(fn, arg, flags); > + > + /* never reached in child process, only in parent */ > + current->task_dumpable = old_task_dumpable; > + > + return ret; > +} > + > /* > * Ok, this is the main fork-routine. It copies the system process > * information (task[nr]) and sets up the necessary registers. It also > diff -purN linux.orig/kernel/ptrace.c linux/kernel/ptrace.c > --- linux.orig/kernel/ptrace.c Thu Mar 13 12:01:46 2003 > +++ linux/kernel/ptrace.c Thu Mar 13 13:47:16 2003 > @@ -21,6 +21,10 @@ > */ > int ptrace_check_attach(struct task_struct *child, int kill) > { > + mb(); > + if (!is_dumpable(child)) > + return -EPERM; > + > if (!(child->ptrace & PT_PTRACED)) > return -ESRCH; > > @@ -57,7 +61,7 @@ int ptrace_attach(struct task_struct *ta > (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE)) > goto bad; > rmb(); > - if (!task->mm->dumpable && !capable(CAP_SYS_PTRACE)) > + if (!is_dumpable(task) && !capable(CAP_SYS_PTRACE)) > goto bad; > /* the same process cannot be attached many times */ > if (task->ptrace & PT_PTRACED) > @@ -123,6 +127,8 @@ int access_process_vm(struct task_struct > /* Worry about races with exit() */ > task_lock(tsk); > mm = tsk->mm; > + if (!is_dumpable(tsk) || (&init_mm == mm)) > + mm = NULL; > if (mm) > atomic_inc(&mm->mm_users); > task_unlock(tsk); > diff -purN linux.orig/kernel/sys.c linux/kernel/sys.c > --- linux.orig/kernel/sys.c Thu Mar 13 12:01:57 2003 > +++ linux/kernel/sys.c Thu Mar 13 13:41:25 2003 > @@ -1286,7 +1286,7 @@ asmlinkage long sys_prctl(int option, un > error = put_user(current->pdeath_signal, (int > *)arg2); > break; > case PR_GET_DUMPABLE: > - if (current->mm->dumpable) > + if (is_dumpable(current)) > error = 1; > break; > case PR_SET_DUMPABLE: > @@ -1294,7 +1294,8 @@ asmlinkage long sys_prctl(int option, un > error = -EINVAL; > break; > } > - current->mm->dumpable = arg2; > + if (is_dumpable(current)) > + current->mm->dumpable = arg2; > break; > case PR_SET_UNALIGN: > #ifdef SET_UNALIGN_CTL > > _________________________________________________________________________________ > > No comments have been posted. Log in to post comments. > > Copyright (©) 2003, > Eklektix, Inc. > Linux (®) is a registered > trademark of Linus Torvalds > Web hosting provided by > Rackspace.com. > -- > > =============================================================================== > Matthew Grant /\ ^/\^ [EMAIL PROTECTED] /~~~~\ > A Linux Network Guy /~~\^/~~\_/~~~~~\_______/~~~~~~~~~~\____/******\ > ===GPG KeyID: 2EE20270 FingerPrint: > 8C2535E1A11DF3EA5EA19125BA4E790E2EE20270== > > > > -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]