Skip to content

Commit b25e6b6

Browse files
committed
io/linux/UserNamespace: pass /proc/PID FileDescriptor to all functions
This allows merging redundant OpenProcPid() calls.
1 parent e5867f9 commit b25e6b6

4 files changed

Lines changed: 30 additions & 26 deletions

File tree

src/io/linux/UserNamespace.cxx

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
// author: Max Kellermann <max.kellermann@ionos.com>
44

55
#include "UserNamespace.hxx"
6-
#include "ProcPid.hxx"
76
#include "lib/fmt/SystemError.hxx"
87
#include "io/FileAt.hxx"
98
#include "io/WriteFile.hxx"
@@ -17,9 +16,9 @@
1716
using std::string_view_literals::operator""sv;
1817

1918
void
20-
DenySetGroups(unsigned pid) noexcept
19+
DenySetGroups(FileDescriptor proc_pid) noexcept
2120
try {
22-
TryWriteExistingFile({OpenProcPid(pid), "setgroups"}, "deny");
21+
TryWriteExistingFile({proc_pid, "setgroups"}, "deny");
2322
} catch (...) {
2423
// silently ignore errors
2524
}
@@ -69,39 +68,39 @@ WriteFileOrThrow(FileDescriptor directory, const char *path, std::string_view da
6968
}
7069

7170
void
72-
SetupUidMap(unsigned pid, const IdMap &map)
71+
SetupUidMap(FileDescriptor proc_pid, const IdMap &map)
7372
{
7473
char buffer[256];
7574
char *end = FormatIdMap(buffer, map);
7675

77-
WriteFileOrThrow(OpenProcPid(pid), "uid_map", {buffer, end});
76+
WriteFileOrThrow(proc_pid, "uid_map", {buffer, end});
7877
}
7978

8079
void
81-
SetupUidMap(unsigned pid, unsigned uid)
80+
SetupUidMap(FileDescriptor proc_pid, unsigned uid)
8281
{
8382
char buffer[256];
8483
char *end = FormatIdMap(buffer, uid);
8584

86-
WriteFileOrThrow(OpenProcPid(pid), "uid_map", {buffer, end});
85+
WriteFileOrThrow(proc_pid, "uid_map", {buffer, end});
8786
}
8887

8988
void
90-
SetupGidMap(unsigned pid, unsigned gid)
89+
SetupGidMap(FileDescriptor proc_pid, unsigned gid)
9190
{
9291
char buffer[256];
9392
char *end = FormatIdMap(buffer, gid);
9493

95-
WriteFileOrThrow(OpenProcPid(pid), "gid_map", {buffer, end});
94+
WriteFileOrThrow(proc_pid, "gid_map", {buffer, end});
9695
}
9796

9897
void
99-
SetupGidMap(unsigned pid, const std::set<unsigned> &gids)
98+
SetupGidMap(FileDescriptor proc_pid, const std::set<unsigned> &gids)
10099
{
101100
assert(!gids.empty());
102101

103102
char buffer[1024];
104103
char *end = FormatIdMap(buffer, gids);
105104

106-
WriteFileOrThrow(OpenProcPid(pid), "gid_map", {buffer, end});
105+
WriteFileOrThrow(proc_pid, "gid_map", {buffer, end});
107106
}

src/io/linux/UserNamespace.hxx

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
#include <set>
88

9+
class FileDescriptor;
10+
911
/**
1012
* Write "deny" to /proc/self/setgroups which is necessary for
1113
* unprivileged processes to set up a gid_map. See Linux commits
@@ -14,7 +16,7 @@
1416
* Errors are ignored silently.
1517
*/
1618
void
17-
DenySetGroups(unsigned pid) noexcept;
19+
DenySetGroups(FileDescriptor proc_pid) noexcept;
1820

1921
/**
2022
* Uid/gid mapping for Linux user namespaces.
@@ -65,35 +67,32 @@ FormatIdMap(char *dest, const std::set<unsigned> &ids) noexcept;
6567
*
6668
* Throws on error.
6769
*
68-
* @param pid the process id whose user namespace shall be modified; 0
69-
* for current process
70+
* @param proc_pid a /proc/PID O_PATH file descriptor
7071
*/
7172
void
72-
SetupUidMap(unsigned pid, const IdMap &map);
73+
SetupUidMap(FileDescriptor proc_pid, const IdMap &map);
7374

7475
void
75-
SetupUidMap(unsigned pid, unsigned uid);
76+
SetupUidMap(FileDescriptor proc_pid, unsigned uid);
7677

7778
/**
7879
* Set up a gid mapping for a user namespace.
7980
*
8081
* Throws on error.
8182
*
82-
* @param pid the process id whose user namespace shall be modified; 0
83-
* for current process
83+
* @param proc_pid a /proc/PID O_PATH file descriptor
8484
* @param gid the group id to be mapped inside the user namespace
8585
*/
8686
void
87-
SetupGidMap(unsigned pid, unsigned gid);
87+
SetupGidMap(FileDescriptor proc_pid, unsigned gid);
8888

8989
/**
9090
* Set up a gid mapping for a user namespace.
9191
*
9292
* Throws on error.
9393
*
94-
* @param pid the process id whose user namespace shall be modified; 0
95-
* for current process
94+
* @param proc_pid a /proc/PID O_PATH file descriptor
9695
* @param gids the group ids to be mapped inside the user namespace
9796
*/
9897
void
99-
SetupGidMap(unsigned pid, const std::set<unsigned> &gids);
98+
SetupGidMap(FileDescriptor proc_pid, const std::set<unsigned> &gids);

src/spawn/Direct.cxx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "io/Pipe.hxx"
1818
#include "io/ScopeUmask.hxx"
1919
#include "io/WriteFile.hxx"
20+
#include "io/linux/ProcPid.hxx"
2021
#include "io/linux/UserNamespace.hxx"
2122
#include "system/linux/clone3.h"
2223
#include "system/linux/CoreScheduling.hxx"
@@ -687,7 +688,7 @@ SpawnChildProcess(EventLoop &event_loop,
687688
it, we can't call setgroups() in the new
688689
child process because of this
689690
self-inflicted restriction */
690-
DenySetGroups(pid);
691+
DenySetGroups(OpenProcPid(pid));
691692

692693
params.ns.SetupUidGidMap(params.uid_gid, pid);
693694

src/spawn/NamespaceOptions.cxx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
#include "UidGid.hxx"
99
#include "AllocatorPtr.hxx"
1010
#include "system/Error.hxx"
11+
#include "io/UniqueFileDescriptor.hxx"
12+
#include "io/linux/ProcPid.hxx"
1113
#include "io/linux/UserNamespace.hxx"
1214

1315
#include <fmt/core.h>
@@ -126,8 +128,10 @@ NamespaceOptions::SetupUidGidMap(const UidGid &uid_gid, unsigned _pid) const
126128
for (unsigned i = 0; uid_gid.supplementary_groups[i] != UidGid::UNSET_GID; ++i)
127129
gids.emplace(uid_gid.supplementary_groups[i]);
128130

131+
const auto proc_pid = OpenProcPid(_pid);
132+
129133
if (!gids.empty())
130-
SetupGidMap(_pid, gids);
134+
SetupGidMap(proc_pid, gids);
131135

132136
const IdMap map{
133137
.first = {
@@ -140,7 +144,7 @@ NamespaceOptions::SetupUidGidMap(const UidGid &uid_gid, unsigned _pid) const
140144
},
141145
};
142146

143-
SetupUidMap(_pid, map);
147+
SetupUidMap(proc_pid, map);
144148
}
145149

146150
void
@@ -155,7 +159,8 @@ void
155159
NamespaceOptions::Apply(const UidGid &uid_gid) const
156160
{
157161
if (enable_user || user_namespace.IsDefined())
158-
DenySetGroups(0);
162+
// TODO eliminate this OpenProcPid() call
163+
DenySetGroups(OpenProcPid(0));
159164

160165
/* set up UID/GID mapping in the old /proc */
161166
if (enable_user)

0 commit comments

Comments
 (0)