@@ -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"
@@ -340,6 +341,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)
@@ -7844,7 +7863,9 @@ static int setgid_create(void)
{
int fret = -1;
int file1_fd = -EBADF;
+ int tmpfile_fd = -EBADF;
pid_t pid;
+ bool supported = false;
if (!caps_supported())
return 0;
@@ -7869,6 +7890,8 @@ static int setgid_create(void)
goto out;
}
+ supported = openat_tmpfile_supported(t_dir1_fd);
+
pid = fork();
if (pid < 0) {
log_stderr("failure: fork");
@@ -7932,6 +7955,24 @@ 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 */
+ if (linkat(tmpfile_fd, "", t_dir1_fd, FILE3, AT_EMPTY_PATH))
+ die("failure: linkat");
+ if (close(tmpfile_fd))
+ die("failure: close");
+ if (!is_setgid(t_dir1_fd, FILE3, 0))
+ die("failure: is_setgid");
+ if (!expected_uid_gid(t_dir1_fd, FILE3, 0, 0, 0))
+ die("failure: check ownership");
+ if (unlinkat(t_dir1_fd, FILE3, 0))
+ die("failure: delete");
+ }
+
exit(EXIT_SUCCESS);
}
if (wait_for_pid(pid))
@@ -8021,6 +8062,24 @@ 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 */
+ if (linkat(tmpfile_fd, "", t_dir1_fd, FILE3, AT_EMPTY_PATH))
+ die("failure: linkat");
+ if (close(tmpfile_fd))
+ die("failure: close");
+ if (is_setgid(t_dir1_fd, FILE3, 0))
+ die("failure: is_setgid");
+ if (!expected_uid_gid(t_dir1_fd, FILE3, 0, 0, 0))
+ die("failure: check ownership");
+ if (unlinkat(t_dir1_fd, FILE3, 0))
+ die("failure: delete");
+ }
+
exit(EXIT_SUCCESS);
}
if (wait_for_pid(pid))
@@ -8042,6 +8101,8 @@ static int setgid_create_idmapped(void)
.attr_set = MOUNT_ATTR_IDMAP,
};
pid_t pid;
+ int tmpfile_fd = -EBADF;
+ bool supported = false;
if (!caps_supported())
return 0;
@@ -8089,6 +8150,8 @@ static int setgid_create_idmapped(void)
goto out;
}
+ supported = openat_tmpfile_supported(open_tree_fd);
+
pid = fork();
if (pid < 0) {
log_stderr("failure: fork");
@@ -8171,6 +8234,24 @@ static int setgid_create_idmapped(void)
if (unlinkat(open_tree_fd, CHRDEV1, 0))
die("failure: delete");
+ /* create tmpfile via filesystem tmpfile api */
+ if (supported) {
+ tmpfile_fd = openat(open_tree_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 */
+ if (linkat(tmpfile_fd, "", t_dir1_fd, FILE3, AT_EMPTY_PATH))
+ die("failure: linkat");
+ if (close(tmpfile_fd))
+ die("failure: close");
+ if (is_setgid(open_tree_fd, FILE3, 0))
+ die("failure: is_setgid");
+ if (!expected_uid_gid(open_tree_fd, FILE3, 0, 10000, 10000))
+ die("failure: check ownership");
+ if (unlinkat(open_tree_fd, FILE3, 0))
+ die("failure: delete");
+ }
+
exit(EXIT_SUCCESS);
}
if (wait_for_pid(pid))
@@ -8194,6 +8275,8 @@ static int setgid_create_idmapped_in_userns(void)
.attr_set = MOUNT_ATTR_IDMAP,
};
pid_t pid;
+ int tmpfile_fd = -EBADF;
+ bool supported = false;
if (!caps_supported())
return 0;
@@ -8241,6 +8324,8 @@ static int setgid_create_idmapped_in_userns(void)
goto out;
}
+ supported = openat_tmpfile_supported(open_tree_fd);
+
pid = fork();
if (pid < 0) {
log_stderr("failure: fork");
@@ -8307,6 +8392,24 @@ static int setgid_create_idmapped_in_userns(void)
if (unlinkat(open_tree_fd, CHRDEV1, 0))
die("failure: delete");
+ /* create tmpfile via filesystem tmpfile api */
+ if (supported) {
+ tmpfile_fd = openat(open_tree_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 */
+ if (linkat(tmpfile_fd, "", t_dir1_fd, FILE3, AT_EMPTY_PATH))
+ die("failure: linkat");
+ if (close(tmpfile_fd))
+ die("failure: close");
+ if (!is_setgid(open_tree_fd, FILE3, 0))
+ die("failure: is_setgid");
+ if (!expected_uid_gid(open_tree_fd, FILE3, 0, 0, 0))
+ die("failure: check ownership");
+ if (unlinkat(open_tree_fd, FILE3, 0))
+ die("failure: delete");
+ }
+
exit(EXIT_SUCCESS);
}
if (wait_for_pid(pid))
@@ -8415,6 +8518,24 @@ static int setgid_create_idmapped_in_userns(void)
if (unlinkat(open_tree_fd, CHRDEV1, 0))
die("failure: delete");
+ /* create tmpfile via filesystem tmpfile api */
+ if (supported) {
+ tmpfile_fd = openat(open_tree_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 */
+ if (linkat(tmpfile_fd, "", t_dir1_fd, FILE3, AT_EMPTY_PATH))
+ die("failure: linkat");
+ if (close(tmpfile_fd))
+ die("failure: close");
+ if (is_setgid(open_tree_fd, FILE3, 0))
+ die("failure: is_setgid");
+ if (!expected_uid_gid(open_tree_fd, FILE3, 0, 0, 1000))
+ die("failure: check ownership");
+ if (unlinkat(open_tree_fd, FILE3, 0))
+ die("failure: delete");
+ }
+
exit(EXIT_SUCCESS);
}
if (wait_for_pid(pid))
@@ -8511,6 +8632,24 @@ static int setgid_create_idmapped_in_userns(void)
if (unlinkat(open_tree_fd, CHRDEV1, 0))
die("failure: delete");
+ /* create tmpfile via filesystem tmpfile api */
+ if (supported) {
+ tmpfile_fd = openat(open_tree_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 */
+ if (linkat(tmpfile_fd, "", t_dir1_fd, FILE3, AT_EMPTY_PATH))
+ die("failure: linkat");
+ if (close(tmpfile_fd))
+ die("failure: close");
+ if (is_setgid(open_tree_fd, FILE3, 0))
+ die("failure: is_setgid");
+ if (!expected_uid_gid(open_tree_fd, FILE3, 0, 0, 0))
+ die("failure: check ownership");
+ if (unlinkat(open_tree_fd, FILE3, 0))
+ die("failure: delete");
+ }
+
exit(EXIT_SUCCESS);
}
if (wait_for_pid(pid))