From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Stefan Monnier Newsgroups: gmane.emacs.bugs Subject: bug#45198: 28.0.50; Sandbox mode Date: Mon, 14 Dec 2020 09:44:30 -0500 Message-ID: References: Mime-Version: 1.0 Content-Type: text/plain Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="4301"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/28.0.50 (gnu/linux) Cc: Bastien , 45198@debbugs.gnu.org, =?UTF-8?Q?Jo=C3=A3o_?= =?UTF-8?Q?T=C3=A1vora?= To: Philipp Stephani Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Mon Dec 14 15:45:52 2020 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1kop6l-0000z6-Dr for geb-bug-gnu-emacs@m.gmane-mx.org; Mon, 14 Dec 2020 15:45:51 +0100 Original-Received: from localhost ([::1]:46736 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kop6k-00005W-DC for geb-bug-gnu-emacs@m.gmane-mx.org; Mon, 14 Dec 2020 09:45:50 -0500 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:45302) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kop5y-0007rZ-Dd for bug-gnu-emacs@gnu.org; Mon, 14 Dec 2020 09:45:02 -0500 Original-Received: from debbugs.gnu.org ([209.51.188.43]:40134) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1kop5y-00009R-4W for bug-gnu-emacs@gnu.org; Mon, 14 Dec 2020 09:45:02 -0500 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1kop5y-0001Ku-1F for bug-gnu-emacs@gnu.org; Mon, 14 Dec 2020 09:45:02 -0500 X-Loop: help-debbugs@gnu.org Resent-From: Stefan Monnier Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Mon, 14 Dec 2020 14:45:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 45198 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch Original-Received: via spool by 45198-submit@debbugs.gnu.org id=B45198.16079570825091 (code B ref 45198); Mon, 14 Dec 2020 14:45:01 +0000 Original-Received: (at 45198) by debbugs.gnu.org; 14 Dec 2020 14:44:42 +0000 Original-Received: from localhost ([127.0.0.1]:51680 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1kop5d-0001K2-Gq for submit@debbugs.gnu.org; Mon, 14 Dec 2020 09:44:41 -0500 Original-Received: from mailscanner.iro.umontreal.ca ([132.204.25.50]:9514) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1kop5b-0001Jq-LQ for 45198@debbugs.gnu.org; Mon, 14 Dec 2020 09:44:40 -0500 Original-Received: from pmg2.iro.umontreal.ca (localhost.localdomain [127.0.0.1]) by pmg2.iro.umontreal.ca (Proxmox) with ESMTP id EC8F68090B; Mon, 14 Dec 2020 09:44:33 -0500 (EST) Original-Received: from mail01.iro.umontreal.ca (unknown [172.31.2.1]) by pmg2.iro.umontreal.ca (Proxmox) with ESMTP id 0460680085; Mon, 14 Dec 2020 09:44:32 -0500 (EST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=iro.umontreal.ca; s=mail; t=1607957072; bh=aZ5BxGEzROpTuBb7t+uhCXQSxYPcNQcxWwozLgGass8=; h=From:To:Cc:Subject:References:Date:In-Reply-To:From; b=fG+kutwutPNzN6ZONzFA9h4X1Vba6wG3nxCPQC/qRjA5IwRgA56k+i6RxCNFhqQeJ j687HMSVnnHiIclCa0bqf9+DKP5yTVcTKi8nxKJdHQZtONcWiX0MFQKANzIzrZuh1K uf/nsXOLxcsI/9Bd50Ltt60bbJUg+trOhc7hDTJIN2Q9c5pS2Z1235tnBOtAWCB7pw fgpNUQZCEO3npUaBcRtILCkdSLiRLAww2eOpH4+eEOKN8BkavfZAontD0JT4ODOYX5 Q2npyCuuXN46lrnuILKsFX78zFk0YLseYyPrc6MuPfortGliUMxUqwUNSYyyZvD7iC BRShrwvMsg59A== Original-Received: from alfajor (69-165-136-52.dsl.teksavvy.com [69.165.136.52]) by mail01.iro.umontreal.ca (Postfix) with ESMTPSA id BE1C11203AB; Mon, 14 Dec 2020 09:44:31 -0500 (EST) In-Reply-To: (Philipp Stephani's message of "Mon, 14 Dec 2020 12:05:09 +0100") X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.io gmane.emacs.bugs:196047 Archived-At: > In some way certainly, but it's not necessarily through stdout. I tend > to write potential output into a file whose filename is passed on the > command line. That's more robust than stdout (which often contains > spurious messages about loading files etc). Hmm... but that requires write access to some part of the file system, so it requires a finer granularity of control. I'd much rather limit the output to something equivalent to a pipe (the implementation of the sandboxing doesn't have to use stdout for that if that's a problem). >> Also, I think the async option is the most important one. How 'bout: >> (sandbox-start FUNCTION) >> Lunch a sandboxed Emacs subprocess running FUNCTION. > Passing a function here might be confusing because e.g. lexical > closures won't work. What makes you think they don't? > It might be preferable to pass a form and state > that both dynamic and lexical bindings are ignored. If closures turn out to be a problem I'd rather use FUNCTION + VALUES than FORM (using FORM implies the use of `eval`, and you have to think of all those kitten that'll suffer if we do that). >> Returns a process object. > Depending how much we care about forward compatibility, it might be > better to return an opaque sandbox object (which will initially wrap a > process object). We always use process objects to represent file-descriptors, so I can't find any good reason why this one should be different or why an implementation might find it difficult to expose a process object. >> FUNCTION is called with no arguments and it can use `sandbox-read` >> to read the data sent to the process object via `process-send-string`, >> and `sandbox-reply` to send back a reply to the parent process >> (which will receive it via its `process-filter`). > That is, sandbox-read and sandbox-reply just read/write stdin/stdout? While it may use stdin/stdout internally, I can imagine good reasons why we'd want to use some other file descriptors. > That would certainly work, but (a) it doesn't really have anything to > do with sandboxing, so these functions should rather be called > stdin-read and stdout-write or similar, I think "the right thing" would be to represent the parent as a process object inside the child. I proposed dedicated functions only because but when it uses stdin/stdout, providing a process object seems awkward to implement. >> The sandboxed process has read access to all the local files >> but no write access to them, nor any access to the network or >> the display. > This might be a bit too specific. I'd imagine we'd want to restrict > reading files to the absolute minimum (files that Emacs itself needs > plus a fixed set of input files/directories known in advance), but > often allow writing some output files. I'm trying to design an API which can be made to work in as many circumstances as possible without imposing too high a maintenance burden. So while I agree that it'd be better to limit the set of files that can be read and to allow writing to some files, I think I'd rather start with something more crude. We can refine it later if/when we have more experience with how it's used, and how it's implemented in the various OSes. >> >> - I suspect we'll still want to use the extra "manual" checks I put in >> >> my code (so as to get clean ELisp errors when bumping against the >> >> walls of the sandbox, and because of the added in-depth security). >> > That's reasonable, though I'm worried that it will give users a false >> > sense of security. >> That would only be the case if we don't additionally use process-level >> isolation, right? > My worry is that people see a function like enter-sandbox and then > assume that Emacs will be secure after calling it, without actually > verifying the security implications. This seems universally true and hence suggests we should just forget about this idea of providing a sandbox functionality. IOW I'm not sure what this has to do with the `ensure_no_sandbox` calls I'm suggesting we keep. > I've looked into this, and what I'd suggest for now is: > 1. Add a --seccomp=FILE command-line option that loads seccomp filters > from FILE and applies them directly after startup (first thing in > main). Why do this in Emacs? Because that's the easiest way to prevent > execve. When installing a seccomp filter in a separate process, execve > needs to be allowed because otherwise there'd be no way to execute the > Emacs binary. While there are workarounds (ptrace, LD_PRELOAD), it's > easiest to install the seccomp filter directly in the Emacs process. > 2. Generate appropriate seccomp filters using libseccomp or similar. > 3. In the sandboxing functions, start Emacs with bwrap to set up > namespaces and invoke Emacs with the new --seccomp flag. Sounds OK, tho I must say I don't understand why we care particularly about disallowing execve inside the bwrap jail. AFAIK anything that an external process can do can also be done directly by Emacs since ELisp is a fairly fully-featured language (since there's nothing like setuid inside a bwrap jail). I mean, I agree that we want to disallow running subprocesses, but can't think of a good reason why we would need this to be 100%, so we could rely on `ensure_no_sandbox` for that. Stefan