diff options
author | Giuseppe Scrivano <gscrivan@redhat.com> | 2019-12-04 10:25:54 +0100 |
---|---|---|
committer | Giuseppe Scrivano <gscrivan@redhat.com> | 2019-12-04 10:30:40 +0100 |
commit | a94e625868c4188dfd3a522f2b24ff9ca3905b64 (patch) | |
tree | d9ee3411747bfc12239b3799f1cdf05775e92087 | |
parent | 5c3af009c6027429d60f6e73bf3ade346ec3d410 (diff) | |
download | podman-a94e625868c4188dfd3a522f2b24ff9ca3905b64.tar.gz podman-a94e625868c4188dfd3a522f2b24ff9ca3905b64.tar.bz2 podman-a94e625868c4188dfd3a522f2b24ff9ca3905b64.zip |
rootless: add fallback for renameat2 at runtime
the renameat2 syscall might be defined in the C library but lacking
support in the kernel.
In such case, let it fallback to open(O_CREAT)+rename as it does on
systems lacking the definition for renameat2.
Closes: https://github.com/containers/libpod/issues/4570
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
-rw-r--r-- | pkg/rootless/rootless_linux.c | 33 |
1 files changed, 20 insertions, 13 deletions
diff --git a/pkg/rootless/rootless_linux.c b/pkg/rootless/rootless_linux.c index 9604de638..193c788c0 100644 --- a/pkg/rootless/rootless_linux.c +++ b/pkg/rootless/rootless_linux.c @@ -19,24 +19,31 @@ #include <sys/select.h> #include <stdio.h> -#ifndef RENAME_NOREPLACE -# define RENAME_NOREPLACE (1 << 0) - -int renameat2 (int olddirfd, const char *oldpath, int newdirfd, const char *newpath, unsigned int flags) +int rename_noreplace (int olddirfd, const char *oldpath, int newdirfd, const char *newpath) { + int ret; + # ifdef SYS_renameat2 - return (int) syscall (SYS_renameat2, olddirfd, oldpath, newdirfd, newpath, flags); -# else +# ifndef RENAME_NOREPLACE +# define RENAME_NOREPLACE (1 << 0) +# endif + + ret = (int) syscall (SYS_renameat2, olddirfd, oldpath, newdirfd, newpath, RENAME_NOREPLACE); + if (ret == 0 || errno != EINVAL) + return ret; + + /* Fallback in case of errno==EINVAL. */ +# endif + /* This might be an issue if another process is trying to read the file while it is empty. */ - int fd = open (newpath, O_EXCL|O_CREAT, 0700); - if (fd < 0) - return fd; - close (fd); + ret = open (newpath, O_EXCL|O_CREAT, 0700); + if (ret < 0) + return ret; + close (ret); + /* We are sure we created the file, let's overwrite it. */ return rename (oldpath, newpath); -# endif } -#endif #ifndef TEMP_FAILURE_RETRY #define TEMP_FAILURE_RETRY(expression) \ @@ -453,7 +460,7 @@ create_pause_process (const char *pause_pid_file_path, char **argv) /* There can be another process at this point trying to configure the user namespace and the pause process, do not override the pid file if it already exists. */ - if (renameat2 (AT_FDCWD, tmp_file_path, AT_FDCWD, pause_pid_file_path, RENAME_NOREPLACE) < 0) + if (rename_noreplace (AT_FDCWD, tmp_file_path, AT_FDCWD, pause_pid_file_path) < 0) { unlink (tmp_file_path); kill (pid, SIGKILL); |