From owner-freebsd-hackers@FreeBSD.ORG Thu Jul 23 05:44:39 2009 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id DF574106564A for ; Thu, 23 Jul 2009 05:44:39 +0000 (UTC) (envelope-from perryh@pluto.rain.com) Received: from agora.rdrop.com (unknown [IPv6:2607:f678:1010::34]) by mx1.freebsd.org (Postfix) with ESMTP id B819D8FC16 for ; Thu, 23 Jul 2009 05:44:39 +0000 (UTC) (envelope-from perryh@pluto.rain.com) Received: from agora.rdrop.com (66@localhost [127.0.0.1]) by agora.rdrop.com (8.13.1/8.12.7) with ESMTP id n6N5D49a070717 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NOT); Wed, 22 Jul 2009 22:13:04 -0700 (PDT) (envelope-from perryh@pluto.rain.com) Received: (from uucp@localhost) by agora.rdrop.com (8.13.1/8.12.9/Submit) with UUCP id n6N5D49n070716; Wed, 22 Jul 2009 22:13:04 -0700 (PDT) Received: from fbsd61 by pluto.rain.com (4.1/SMI-4.1-pluto-M2060407) id AA00869; Wed, 22 Jul 09 22:03:47 PDT Date: Wed, 22 Jul 2009 22:00:58 -0700 From: perryh@pluto.rain.com To: freebsd-hackers@freebsd.org Message-Id: <4a67ee8a.wIGNpBr1/a3vNK2S%perryh@pluto.rain.com> References: <19939654343.20090722214221@mail.ru> <4A6795E7.7020700@darkbsd.org> In-Reply-To: <4A6795E7.7020700@darkbsd.org> User-Agent: nail 11.25 7/29/05 Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Cc: darksoul@darkbsd.org Subject: Re: SGID/SUID on scripts X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 23 Jul 2009 05:44:40 -0000 DarkSoul wrote: > Anthony Pankov wrote: > > SGID/SUID bits don't work with shell scripts, do they? > > They don't. > > ... if they were applied, the following would occur : > - execve() syscall reads your script's shebang line, and > the script interpreter is executed, receiving the specified > arguments along with the script name. > - The interpreter then open()s the script file to read it, > and run the code. > > The problem you then are faced with, is that you have a time > frame defined by the moment between the aforementioned execve() > and open(), during which it could be possible to unlink/move/ > whatever the shell script the interpreter is going to open. > > You guess where this is going, you have no absolute way of > guaranteeing you are executing the file you initially planned > on opening because execution/opening/reading is not, and can't > be done atomically for shell scripts. In principle, it should be possible to fix this exposure by improving the interface between execve() and the interpreter: The execve() syscall already has the script file open to read the shebang line. Leave it open, and ensure that the interpreter receives the open descriptor as fd#3 just as 0, 1, and 2 are already used for stdin, stdout, and stderr. An interpreter supporting this approach would check whether stdscr (fd#3) is already open, and if so read from it instead of open()ing the script file. This should ensure that the script which gets executed is the same inode on which execve() saw the SGID/SUID bits set, even if the filesystem has been changed by the time the interpreter has gotten started. It would be the responsibility of whomever decided to set the SGID/SUID bits on a particular script to ensure that the interpreter involved supports the mechanism. I vaguely recall having seen a similar (or even identical) approach suggested some years ago. It may even have been implemented in some variant of Un*x.