[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <bf4a737a-0c5b-4349-886d-4013683818ce@molgen.mpg.de>
Date: Sat, 4 May 2024 22:38:59 +0200
From: Donald Buczek <buczek@...gen.mpg.de>
To: Stas Sergeev <stsp2@...dex.ru>, linux-kernel@...r.kernel.org
Cc: Stefan Metzmacher <metze@...ba.org>,
Eric Biederman <ebiederm@...ssion.com>,
Alexander Viro <viro@...iv.linux.org.uk>, Andy Lutomirski <luto@...nel.org>,
Christian Brauner <brauner@...nel.org>, Jan Kara <jack@...e.cz>,
Jeff Layton <jlayton@...nel.org>, Chuck Lever <chuck.lever@...cle.com>,
Alexander Aring <alex.aring@...il.com>,
David Laight <David.Laight@...LAB.COM>, linux-fsdevel@...r.kernel.org,
linux-api@...r.kernel.org, Paolo Bonzini <pbonzini@...hat.com>,
Christian Göttsche <cgzones@...glemail.com>
Subject: Re: [PATCH v6 3/3] openat2: add OA2_CRED_INHERIT flag
On 4/27/24 13:24, Stas Sergeev wrote:
> This flag performs the open operation with the fs credentials
> (fsuid, fsgid, group_info) that were in effect when dir_fd was opened.
> dir_fd must be opened with O_CRED_ALLOW, or EPERM is returned.
>
> Selftests are added to check for these properties as well as for
> the invalid flag combinations.
>
> This allows the process to pre-open some directories and then
> change eUID (and all other UIDs/GIDs) to a less-privileged user,
> retaining the ability to open/create files within these directories.
>
> Design goal:
> The idea is to provide a very light-weight sandboxing, where the
> process, without the use of any heavy-weight techniques like chroot
> within namespaces, can restrict the access to the set of pre-opened
> directories.
> This patch is just a first step to such sandboxing. If things go
> well, in the future the same extension can be added to more syscalls.
> These should include at least unlinkat(), renameat2() and the
> not-yet-upstreamed setxattrat().
>
> Security considerations:
> - Only the bare minimal set of credentials is overridden:
> fsuid, fsgid and group_info. The rest, for example capabilities,
> are not overridden to avoid unneeded security risks.
> - To avoid sandboxing escape, this patch makes sure the restricted
> lookup modes are used. Namely, RESOLVE_BENEATH or RESOLVE_IN_ROOT.
> - Magic /proc symlinks are discarded, as suggested by
> Andy Lutomirski <luto@...nel.org>> - O_CRED_ALLOW fds cannot be passed via unix socket and are always
> closed on exec() to prevent "unsuspecting userspace" from not being
> able to fully drop privs.
What about hard links?
== snip ==
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <stdarg.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/openat2.h>
#define O_CRED_ALLOW 0x2000000
#define OA2_CRED_INHERIT (1UL << 28)
#define SYS_openat2 437
long openat2(int dirfd, const char *pathname, struct open_how *how, size_t size) {
return syscall(SYS_openat2, dirfd, pathname, how, size);
}
__attribute__ ((noreturn, format(printf, 1, 2)))
static void die(const char *restrict fmt, ...) {
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
_exit(1);
}
int main() {
unlink("/tmp/d/test.dat");
unlink("/tmp/d/hostname");
if (rmdir("/tmp/d") != 0 && errno != ENOENT)
die("/tmp/d: %m\n");
umask(0);
if (mkdir("/tmp/d", 0777) != 0)
die("/tmp/d: %m\n");
int dirfd = open("/tmp/d", O_RDONLY + O_CRED_ALLOW);
if (dirfd == -1)
die("/tmp/d: %m\n");
if (setuid(1000) != 0)
die("setuid: %m\n");
if (link("/etc/hostname", "/tmp/d/hostname") == -1)
die ("/etc/hostname: %m\n");
if(openat(dirfd, "hostname", O_RDWR) != -1)
die("/tmp/d/hostname could be opened by uid 1000");
{ struct open_how how = { .flags = O_RDWR + OA2_CRED_INHERIT, .resolve = RESOLVE_BENEATH };
if (openat2(dirfd, "hostname", &how, sizeof(how)) == -1)
die("hostname: %m\n");
printf("able to open /etc/hostname RDWR \n");
}
}
== snip ==
buczek@...e:~$ gcc -O0 -Wall -Wextra -Werror -g -o test test.c
buczek@...e:~$ sudo ./test
able to open /etc/hostname RDWR
buczek@...e:~$
--
Donald Buczek
buczek@...gen.mpg.de
Tel: +49 30 8413 1433
Powered by blists - more mailing lists