Skip to content

Commit 6840ecb

Browse files
authored
Merge pull request #32945 from bluca/lxc_network_test
Fix tests and services with PrivateNetwork=yes running under LXC with AppArmor
2 parents 25d505c + 6ab21f2 commit 6840ecb

File tree

2 files changed

+33
-10
lines changed

2 files changed

+33
-10
lines changed

src/basic/lock-util.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,14 @@ static int fcntl_lock(int fd, int operation, bool ofd) {
139139
.l_len = 0,
140140
}));
141141

142-
if (r == -EACCES) /* Treat EACCESS/EAGAIN the same as per man page. */
142+
/* If we are doing non-blocking operations, treat EACCES/EAGAIN the same as per man page. But if
143+
* not, propagate EACCES back, as it will likely be due to an LSM denying the operation (for example
144+
* LXC with AppArmor when running on kernel < 6.2), and in some cases we want to gracefully
145+
* fallback (e.g.: PrivateNetwork=yes). As per documentation, it's only the non-blocking operation
146+
* F_SETLK that might return EACCES on some platforms (although the Linux implementation doesn't
147+
* seem to), as F_SETLKW and F_OFD_SETLKW block so this is not an issue, and F_OFD_SETLK is documented
148+
* to only return EAGAIN if the lock is already held. */
149+
if ((operation & LOCK_NB) && r == -EACCES)
143150
r = -EAGAIN;
144151

145152
return r;

src/test/test-namespace.c

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/* SPDX-License-Identifier: LGPL-2.1-or-later */
22

33
#include <fcntl.h>
4+
#include <sysexits.h>
45
#include <sys/socket.h>
56
#include <sys/stat.h>
67

@@ -84,6 +85,7 @@ TEST(tmpdir) {
8485

8586
static void test_shareable_ns(unsigned long nsflag) {
8687
_cleanup_close_pair_ int s[2] = EBADF_PAIR;
88+
bool permission_denied = false;
8789
pid_t pid1, pid2, pid3;
8890
int r, n = 0;
8991
siginfo_t si;
@@ -100,42 +102,56 @@ static void test_shareable_ns(unsigned long nsflag) {
100102

101103
if (pid1 == 0) {
102104
r = setup_shareable_ns(s, nsflag);
103-
assert_se(r >= 0);
104-
_exit(r);
105+
assert_se(r >= 0 || ERRNO_IS_NEG_PRIVILEGE(r));
106+
_exit(r >= 0 ? r : EX_NOPERM);
105107
}
106108

107109
pid2 = fork();
108110
assert_se(pid2 >= 0);
109111

110112
if (pid2 == 0) {
111113
r = setup_shareable_ns(s, nsflag);
112-
assert_se(r >= 0);
113-
exit(r);
114+
assert_se(r >= 0 || ERRNO_IS_NEG_PRIVILEGE(r));
115+
_exit(r >= 0 ? r : EX_NOPERM);
114116
}
115117

116118
pid3 = fork();
117119
assert_se(pid3 >= 0);
118120

119121
if (pid3 == 0) {
120122
r = setup_shareable_ns(s, nsflag);
121-
assert_se(r >= 0);
122-
exit(r);
123+
assert_se(r >= 0 || ERRNO_IS_NEG_PRIVILEGE(r));
124+
_exit(r >= 0 ? r : EX_NOPERM);
123125
}
124126

125127
r = wait_for_terminate(pid1, &si);
126128
assert_se(r >= 0);
127129
assert_se(si.si_code == CLD_EXITED);
128-
n += si.si_status;
130+
if (si.si_status == EX_NOPERM)
131+
permission_denied = true;
132+
else
133+
n += si.si_status;
129134

130135
r = wait_for_terminate(pid2, &si);
131136
assert_se(r >= 0);
132137
assert_se(si.si_code == CLD_EXITED);
133-
n += si.si_status;
138+
if (si.si_status == EX_NOPERM)
139+
permission_denied = true;
140+
else
141+
n += si.si_status;
134142

135143
r = wait_for_terminate(pid3, &si);
136144
assert_se(r >= 0);
137145
assert_se(si.si_code == CLD_EXITED);
138-
n += si.si_status;
146+
if (si.si_status == EX_NOPERM)
147+
permission_denied = true;
148+
else
149+
n += si.si_status;
150+
151+
/* LSMs can cause setup_shareable_ns() to fail with permission denied, do not fail the test in that
152+
* case (e.g.: LXC with AppArmor on kernel < v6.2). */
153+
if (permission_denied)
154+
return (void) log_tests_skipped("insufficient privileges");
139155

140156
assert_se(n == 1);
141157
}

0 commit comments

Comments
 (0)