1 /* Acquire root privileges.
2 Copyright (C) 2016-2023 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <https://www.gnu.org/licenses/>. */
19 #include <support/namespace.h>
26 #include <support/check.h>
27 #include <support/xunistd.h>
31 /* The necessary steps to allow file creation in user namespaces. */
33 setup_uid_gid_mapping (uid_t original_uid
, gid_t original_gid
)
35 int fd
= open64 ("/proc/self/uid_map", O_WRONLY
);
38 printf ("warning: could not open /proc/self/uid_map: %m\n"
39 "warning: file creation may not be possible\n");
43 /* We map our original UID to the same UID in the container so we
44 own our own files normally. Without that, file creation could
45 fail with EOVERFLOW (sic!). */
47 int ret
= snprintf (buf
, sizeof (buf
), "%llu %llu 1\n",
48 (unsigned long long) original_uid
,
49 (unsigned long long) original_uid
);
50 TEST_VERIFY_EXIT (ret
< sizeof (buf
));
51 xwrite (fd
, buf
, ret
);
54 /* Linux 3.19 introduced the setgroups file. We need write "deny" to this
55 file otherwise writing to gid_map will fail with EPERM. */
56 fd
= open64 ("/proc/self/setgroups", O_WRONLY
, 0);
60 FAIL_EXIT1 ("open64 (\"/proc/self/setgroups\", 0x%x, 0%o): %m",
62 /* This kernel doesn't expose the setgroups file so simply move on. */
66 xwrite (fd
, "deny\n", strlen ("deny\n"));
70 /* Now map our own GID, like we did for the user ID. */
71 fd
= xopen ("/proc/self/gid_map", O_WRONLY
, 0);
72 ret
= snprintf (buf
, sizeof (buf
), "%llu %llu 1\n",
73 (unsigned long long) original_gid
,
74 (unsigned long long) original_gid
);
75 TEST_VERIFY_EXIT (ret
< sizeof (buf
));
76 xwrite (fd
, buf
, ret
);
79 #endif /* CLONE_NEWUSER */
82 support_become_root (void)
85 uid_t original_uid
= getuid ();
86 gid_t original_gid
= getgid ();
88 if (unshare (CLONE_NEWUSER
| CLONE_NEWNS
) == 0)
90 setup_uid_gid_mapping (original_uid
, original_gid
);
91 /* Even if we do not have UID zero, we have extended privileges at
98 printf ("warning: could not become root outside namespace (%m)\n");