On Tue, Apr 12, 2022 at 07:33:44PM +0800, Yang Xu wrote: > Since we can create temp file by using O_TMPFILE flag and filesystem driver also > has this api, we should also check this operation whether strip S_ISGID. > > Reviewed-by: Christian Brauner (Microsoft) <brauner@xxxxxxxxxx> > Signed-off-by: Yang Xu <xuyang2018.jy@xxxxxxxxxxx> > --- > src/idmapped-mounts/idmapped-mounts.c | 148 ++++++++++++++++++++++++++ > 1 file changed, 148 insertions(+) > > diff --git a/src/idmapped-mounts/idmapped-mounts.c b/src/idmapped-mounts/idmapped-mounts.c > index 617f56e0..02f91558 100644 > --- a/src/idmapped-mounts/idmapped-mounts.c > +++ b/src/idmapped-mounts/idmapped-mounts.c > @@ -51,6 +51,7 @@ > #define FILE1_RENAME "file1_rename" > #define FILE2 "file2" > #define FILE2_RENAME "file2_rename" > +#define FILE3 "file3" > #define DIR1 "dir1" > #define DIR2 "dir2" > #define DIR3 "dir3" > @@ -337,6 +338,24 @@ out: > return fret; > } > > +static bool openat_tmpfile_supported(int dirfd) > +{ > + int fd = -1; > + > + fd = openat(dirfd, ".", O_TMPFILE | O_RDWR, S_IXGRP | S_ISGID); > + if (fd == -1) { > + if (errno == ENOTSUP) > + return false; > + else > + return log_errno(false, "failure: create"); > + } > + > + if (close(fd)) > + log_stderr("failure: close"); > + > + return true; > +} > + > /* __expected_uid_gid - check whether file is owned by the provided uid and gid */ > static bool __expected_uid_gid(int dfd, const char *path, int flags, > uid_t expected_uid, gid_t expected_gid, bool log) > @@ -7841,7 +7860,10 @@ static int setgid_create(void) > { > int fret = -1; > int file1_fd = -EBADF; > + int tmpfile_fd = -EBADF; > pid_t pid; > + bool supported = false; > + char path[PATH_MAX]; > > if (!caps_supported()) > return 0; > @@ -7866,6 +7888,8 @@ static int setgid_create(void) > goto out; > } > > + supported = openat_tmpfile_supported(t_dir1_fd); > + > pid = fork(); > if (pid < 0) { > log_stderr("failure: fork"); > @@ -7929,6 +7953,25 @@ static int setgid_create(void) > if (unlinkat(t_dir1_fd, CHRDEV1, 0)) > die("failure: delete"); > > + /* create tmpfile via filesystem tmpfile api */ > + if (supported) { > + tmpfile_fd = openat(t_dir1_fd, ".", O_TMPFILE | O_RDWR, S_IXGRP | S_ISGID); > + if (tmpfile_fd < 0) > + die("failure: create"); > + /* link the temporary file into the filesystem, making it permanent */ > + snprintf(path, PATH_MAX, "/proc/self/fd/%d", tmpfile_fd); > + if (linkat(AT_FDCWD, path, t_dir1_fd, FILE3, AT_SYMLINK_FOLLOW)) > + die("failure: linkat"); Fwiw, I don't think you need that snprintf() dance as you should be able to use AT_EMPTY_PATH: if (linkat(fd, "", t_dir1_fd, FILE3, AT_EMPTY_PATH)) for this.