tests: fix userns setns opening pipe order

setns tests part of the userns could fail if the parent process opened
the child pipe to write it was done before the child opened the pipe
with read permissions.

From the fifo(7) man page:

A process can open a FIFO in nonblocking mode.  In this case, opening
for read‐only succeeds even if no one has opened on the write side yet
and opening for write‐only fails with ENXIO (no such device or
address) unless the other end has already been opened.

Signed-off-by: Georgia Garcia <georgia.garcia@canonical.com>
This commit is contained in:
Georgia Garcia 2023-08-21 12:04:51 -03:00
parent 1758b66c9d
commit 24806f6f61
3 changed files with 33 additions and 7 deletions

View file

@ -58,6 +58,7 @@ int userns_setns(char *client, char *pipename)
{
int userns, exit_status, ret;
char *parentpipe = NULL, *childpipe = NULL;
int parentpipefd;
if (get_pipes(pipename, &parentpipe, &childpipe) == -1) {
fprintf(stderr, "FAIL - failed to allocate pipes\n");
@ -81,7 +82,14 @@ int userns_setns(char *client, char *pipename)
goto out;
}
if (read_from_pipe(parentpipe) == -1) { // wait for child to unshare
parentpipefd = open_read_pipe(parentpipe);
if (parentpipefd == -1) {
fprintf(stderr, "FAIL - couldn't open parent pipe\n");
ret = EXIT_FAILURE;
goto out;
}
if (read_from_pipe(parentpipefd) == -1) { // wait for child to unshare
fprintf(stderr, "FAIL - parent could not read from pipe\n");
ret = EXIT_FAILURE;
goto out;

View file

@ -15,16 +15,26 @@ int get_pipes(const char *pipename, char **parentpipe, char **childpipe)
return 0;
}
int read_from_pipe(char *pipename)
int open_read_pipe(char *pipename)
{
int fd, ret;
int fd;
fd = open(pipename, O_RDONLY | O_NONBLOCK);
if (fd == -1) {
perror("FAIL - open read pipe");
return EXIT_FAILURE;
}
return fd;
}
int read_from_pipe(int fd)
{
int ret;
char buf;
fd_set set;
struct timeval timeout;
fd = open(pipename, O_RDONLY | O_NONBLOCK);
if (fd == -1) {
perror("FAIL - open read pipe");
fprintf(stderr, "FAIL - invalid read fd\n");
return EXIT_FAILURE;
}
@ -59,7 +69,7 @@ int write_to_pipe(char *pipename)
fd = open(pipename, O_WRONLY | O_NONBLOCK);
if (fd == -1) {
perror("FAIL - open write pipe");
fprintf(stderr, "FAIL - open write pipe %s - %m\n", pipename);
return EXIT_FAILURE;
}
close(fd);

View file

@ -13,6 +13,7 @@ int main(int argc, char *argv[])
int ret;
char *pipename = "/tmp/userns_pipe";
char *parentpipe = NULL, *childpipe = NULL;
int childpipefd;
if (argc > 1)
pipename = argv[1];
@ -26,6 +27,13 @@ int main(int argc, char *argv[])
if (mkfifo(childpipe, 0666) == -1)
perror("FAIL - setns child mkfifo");
childpipefd = open_read_pipe(childpipe);
if (childpipefd == -1) {
fprintf(stderr, "FAIL - couldn't open child pipe\n");
ret = EXIT_FAILURE;
goto out;
}
if (unshare(CLONE_NEWUSER) == -1) {
perror("FAIL - unshare");
ret = EXIT_FAILURE;
@ -37,7 +45,7 @@ int main(int argc, char *argv[])
ret = EXIT_FAILURE;
goto out;
}
if (read_from_pipe(childpipe) == -1) { // wait for parent tell child can finish
if (read_from_pipe(childpipefd) == -1) { // wait for parent tell child can finish
fprintf(stderr, "FAIL - child could not read from pipe\n");
ret = EXIT_FAILURE;
goto out;