From owner-freebsd-hackers@FreeBSD.ORG Sat Oct 2 08:19:37 2004 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 4151016A4CE for ; Sat, 2 Oct 2004 08:19:37 +0000 (GMT) Received: from kane.otenet.gr (kane.otenet.gr [195.170.0.27]) by mx1.FreeBSD.org (Postfix) with ESMTP id 8D61B43D3F for ; Sat, 2 Oct 2004 08:19:36 +0000 (GMT) (envelope-from keramida@FreeBSD.org) Received: from gothmog.gr (patr530-a020.otenet.gr [212.205.215.20]) i928JWsS012207 for ; Sat, 2 Oct 2004 11:19:33 +0300 Received: from gothmog.gr (gothmog [127.0.0.1]) by gothmog.gr (8.13.1/8.13.1) with ESMTP id i928JTbK031590 for ; Sat, 2 Oct 2004 11:19:29 +0300 (EEST) (envelope-from keramida@FreeBSD.org) Received: (from giorgos@localhost) by gothmog.gr (8.13.1/8.13.1/Submit) id i928JSHu031585 for freebsd-hackers@freebsd.org; Sat, 2 Oct 2004 11:19:28 +0300 (EEST) (envelope-from keramida@FreeBSD.org) Date: Sat, 2 Oct 2004 11:19:28 +0300 From: Giorgos Keramidas To: freebsd-hackers@FreeBSD.org Message-ID: <20041002081928.GA21439@gothmog.gr> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Subject: Protection from the dreaded "rm -fr /" X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 02 Oct 2004 08:19:37 -0000 John Beck, who works for Sun, has posted an entry in his blog yesterday about "rm -fr /" protection, which I liked a lot: http://blogs.sun.com/roller/page/jbeck/20041001#rm_rf_protection His idea was remarkably simple, so I went ahead and wrote this patch for rm(1) of FreeBSD: %%% Index: rm.c =================================================================== RCS file: /home/ncvs/src/bin/rm/rm.c,v retrieving revision 1.47 diff -u -r1.47 rm.c --- rm.c 6 Apr 2004 20:06:50 -0000 1.47 +++ rm.c 2 Oct 2004 08:06:21 -0000 @@ -157,6 +157,7 @@ void rm_tree(char **argv) { + char **argv_tmp; FTS *fts; FTSENT *p; int needstat; @@ -164,6 +165,17 @@ int rval; /* + * If one of the members of argv[] is the root directory abort the + * entire operation. + */ + argv_tmp = argv; + while (*argv_tmp != NULL) { + if (strcmp(*argv_tmp, "/") == 0) + errx(1, "rm of / is not allowed"); + argv_tmp++; + } + + /* * Remove a file hierarchy. If forcing removal (-f), or interactive * (-i) or can't ask anyway (stdin_ok), don't stat the file. */ %%% To test it, I used a minimal chroot with /bin, /lib and /libexec copied over from my real / partition: # mkdir -p /tmp/chroot/bin ; cp -Rp /lib /libexec /tmp/chroot # cp /bin/sh /bin/ls /tmp/chroot/bin # cp /a/freebsd/src/bin/rm/rm /tmp/chroot/bin # env PS1='chroot# ' chroot /tmp/chroot /bin/sh chroot# rm -fr / rm: recursive rm of / is not allowed chroot# exit # It seems to work nicely here. I'm not sure if the overhead of traversing argv[] twice is a bug price to pay for the protection this adds, but if a lot of people like it I'll commit it when I get the approval of src-committers :-) - Giorgos