return ret;
}
+/* caps_down_fsetid - lower CAP_FSETID effective cap */
+static int caps_down_fsetid(void)
+{
+ bool fret = false;
+#ifdef HAVE_SYS_CAPABILITY_H
+ cap_t caps = NULL;
+ cap_value_t cap = CAP_FSETID;
+ int ret = -1;
+
+ caps = cap_get_proc();
+ if (!caps)
+ goto out;
+
+ ret = cap_set_flag(caps, CAP_EFFECTIVE, 1, &cap, 0);
+ if (ret)
+ goto out;
+
+ ret = cap_set_proc(caps);
+ if (ret)
+ goto out;
+
+ fret = true;
+
+out:
+ cap_free(caps);
+#endif
+ return fret;
+}
+
/* caps_down - lower all effective caps */
static int caps_down(void)
{
#endif /* HAVE_LIBURING_H */
/* The following tests are concerned with setgid inheritance. These can be
- * filesystem type specific. For xfs, if a new file or directory is created
- * within a setgid directory and irix_sgid_inhiert is set then inherit the
- * setgid bit if the caller is in the group of the directory.
+ * filesystem type specific. For xfs, if a new file or directory or node is
+ * created within a setgid directory and irix_sgid_inhiert is set then inherit
+ * the setgid bit if the caller is in the group of the directory.
*/
static int setgid_create(void)
{
if (!is_setgid(t_dir1_fd, DIR1, 0))
die("failure: is_setgid");
+ /* create a special file via mknodat() vfs_create */
+ if (mknodat(t_dir1_fd, FILE2, S_IFREG | S_ISGID | S_IXGRP, 0))
+ die("failure: mknodat");
+
+ if (!is_setgid(t_dir1_fd, FILE2, 0))
+ die("failure: is_setgid");
+
+ /* create a character device via mknodat() vfs_mknod */
+ if (mknodat(t_dir1_fd, CHRDEV1, S_IFCHR | S_ISGID | S_IXGRP, makedev(5, 1)))
+ die("failure: mknodat");
+
+ if (!is_setgid(t_dir1_fd, CHRDEV1, 0))
+ die("failure: is_setgid");
+
if (!expected_uid_gid(t_dir1_fd, FILE1, 0, 0, 0))
die("failure: check ownership");
if (!expected_uid_gid(t_dir1_fd, DIR1, 0, 0, 0))
die("failure: check ownership");
+ if (!expected_uid_gid(t_dir1_fd, FILE2, 0, 0, 0))
+ die("failure: check ownership");
+
+ if (!expected_uid_gid(t_dir1_fd, CHRDEV1, 0, 0, 0))
+ die("failure: check ownership");
+
if (unlinkat(t_dir1_fd, FILE1, 0))
die("failure: delete");
if (unlinkat(t_dir1_fd, DIR1, AT_REMOVEDIR))
die("failure: delete");
+ if (unlinkat(t_dir1_fd, FILE2, 0))
+ die("failure: delete");
+
+ if (unlinkat(t_dir1_fd, CHRDEV1, 0))
+ die("failure: delete");
+
exit(EXIT_SUCCESS);
}
if (wait_for_pid(pid))
if (!switch_ids(0, 10000))
die("failure: switch_ids");
- if (!caps_down())
- die("failure: caps_down");
+ if (!caps_down_fsetid())
+ die("failure: caps_down_fsetid");
/* create regular file via open() */
file1_fd = openat(t_dir1_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, S_IXGRP | S_ISGID);
die("failure: is_setgid");
}
+ /* create a special file via mknodat() vfs_create */
+ if (mknodat(t_dir1_fd, FILE2, S_IFREG | S_ISGID | S_IXGRP, 0))
+ die("failure: mknodat");
+
+ if (is_setgid(t_dir1_fd, FILE2, 0))
+ die("failure: is_setgid");
+
+ /* create a character device via mknodat() vfs_mknod */
+ if (mknodat(t_dir1_fd, CHRDEV1, S_IFCHR | S_ISGID | S_IXGRP, makedev(5, 1)))
+ die("failure: mknodat");
+
+ if (is_setgid(t_dir1_fd, CHRDEV1, 0))
+ die("failure: is_setgid");
/*
* In setgid directories newly created files always inherit the
* gid from the parent directory. Verify that the file is owned
if (!expected_uid_gid(t_dir1_fd, DIR1, 0, 0, 0))
die("failure: check ownership");
+ if (!expected_uid_gid(t_dir1_fd, FILE2, 0, 0, 0))
+ die("failure: check ownership");
+
+ if (!expected_uid_gid(t_dir1_fd, CHRDEV1, 0, 0, 0))
+ die("failure: check ownership");
+
+ if (unlinkat(t_dir1_fd, FILE1, 0))
+ die("failure: delete");
+
+ if (unlinkat(t_dir1_fd, DIR1, AT_REMOVEDIR))
+ die("failure: delete");
+
+ if (unlinkat(t_dir1_fd, FILE2, 0))
+ die("failure: delete");
+
+ if (unlinkat(t_dir1_fd, CHRDEV1, 0))
+ die("failure: delete");
+
exit(EXIT_SUCCESS);
}
if (wait_for_pid(pid))
die("failure: is_setgid");
}
+ /* create a special file via mknodat() vfs_create */
+ if (mknodat(open_tree_fd, FILE2, S_IFREG | S_ISGID | S_IXGRP, 0))
+ die("failure: mknodat");
+
+ if (is_setgid(open_tree_fd, FILE2, 0))
+ die("failure: is_setgid");
+
+ /* create a whiteout device via mknodat() vfs_mknod */
+ if (mknodat(open_tree_fd, CHRDEV1, S_IFCHR | S_ISGID | S_IXGRP, 0))
+ die("failure: mknodat");
+
+ if (is_setgid(open_tree_fd, CHRDEV1, 0))
+ die("failure: is_setgid");
+
/*
* In setgid directories newly created files always inherit the
* gid from the parent directory. Verify that the file is owned
if (!expected_uid_gid(open_tree_fd, DIR1, 0, 10000, 10000))
die("failure: check ownership");
+ if (!expected_uid_gid(open_tree_fd, FILE2, 0, 10000, 10000))
+ die("failure: check ownership");
+
+ if (!expected_uid_gid(open_tree_fd, CHRDEV1, 0, 10000, 10000))
+ die("failure: check ownership");
+
+ if (unlinkat(open_tree_fd, FILE1, 0))
+ die("failure: delete");
+
+ if (unlinkat(open_tree_fd, DIR1, AT_REMOVEDIR))
+ die("failure: delete");
+
+ if (unlinkat(open_tree_fd, FILE2, 0))
+ die("failure: delete");
+
+ if (unlinkat(open_tree_fd, CHRDEV1, 0))
+ die("failure: delete");
+
exit(EXIT_SUCCESS);
}
if (wait_for_pid(pid))
if (!is_setgid(open_tree_fd, DIR1, 0))
die("failure: is_setgid");
+ /* create a special file via mknodat() vfs_create */
+ if (mknodat(open_tree_fd, FILE2, S_IFREG | S_ISGID | S_IXGRP, 0))
+ die("failure: mknodat");
+
+ if (!is_setgid(open_tree_fd, FILE2, 0))
+ die("failure: is_setgid");
+
+ /* create a whiteout device via mknodat() vfs_mknod */
+ if (mknodat(open_tree_fd, CHRDEV1, S_IFCHR | S_ISGID | S_IXGRP, 0))
+ die("failure: mknodat");
+
+ if (!is_setgid(open_tree_fd, CHRDEV1, 0))
+ die("failure: is_setgid");
+
if (!expected_uid_gid(open_tree_fd, FILE1, 0, 0, 0))
die("failure: check ownership");
if (!expected_uid_gid(open_tree_fd, DIR1, 0, 0, 0))
die("failure: check ownership");
+ if (!expected_uid_gid(open_tree_fd, FILE2, 0, 0, 0))
+ die("failure: check ownership");
+
+ if (!expected_uid_gid(open_tree_fd, CHRDEV1, 0, 0, 0))
+ die("failure: check ownership");
+
if (unlinkat(open_tree_fd, FILE1, 0))
die("failure: delete");
if (unlinkat(open_tree_fd, DIR1, AT_REMOVEDIR))
die("failure: delete");
+ if (unlinkat(open_tree_fd, FILE2, 0))
+ die("failure: delete");
+
+ if (unlinkat(open_tree_fd, CHRDEV1, 0))
+ die("failure: delete");
+
exit(EXIT_SUCCESS);
}
if (wait_for_pid(pid))
exit(EXIT_SUCCESS);
}
- if (!switch_userns(attr.userns_fd, 0, 0, true))
+ if (!switch_userns(attr.userns_fd, 0, 0, false))
die("failure: switch_userns");
+ if (!caps_down_fsetid())
+ die("failure: caps_down_fsetid");
+
/* create regular file via open() */
file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, S_IXGRP | S_ISGID);
if (file1_fd < 0)
die("failure: is_setgid");
}
+ /* create a special file via mknodat() vfs_create */
+ if (mknodat(open_tree_fd, FILE2, S_IFREG | S_ISGID | S_IXGRP, 0))
+ die("failure: mknodat");
+
+ if (is_setgid(open_tree_fd, FILE2, 0))
+ die("failure: is_setgid");
+
+ /* create a whiteout device via mknodat() vfs_mknod */
+ if (mknodat(open_tree_fd, CHRDEV1, S_IFCHR | S_ISGID | S_IXGRP, 0))
+ die("failure: mknodat");
+
+ if (is_setgid(open_tree_fd, CHRDEV1, 0))
+ die("failure: is_setgid");
+
/*
* In setgid directories newly created files always inherit the
* gid from the parent directory. Verify that the file is owned
if (!expected_uid_gid(open_tree_fd, DIR1, 0, 0, 1000))
die("failure: check ownership");
+ if (!expected_uid_gid(open_tree_fd, FILE2, 0, 0, 1000))
+ die("failure: check ownership");
+
+ if (!expected_uid_gid(open_tree_fd, CHRDEV1, 0, 0, 1000))
+ die("failure: check ownership");
+
if (unlinkat(open_tree_fd, FILE1, 0))
die("failure: delete");
if (unlinkat(open_tree_fd, DIR1, AT_REMOVEDIR))
die("failure: delete");
+ if (unlinkat(open_tree_fd, FILE2, 0))
+ die("failure: delete");
+
+ if (unlinkat(open_tree_fd, CHRDEV1, 0))
+ die("failure: delete");
+
exit(EXIT_SUCCESS);
}
if (wait_for_pid(pid))
exit(EXIT_SUCCESS);
}
- if (!switch_userns(attr.userns_fd, 0, 1000, true))
+ if (!switch_userns(attr.userns_fd, 0, 1000, false))
die("failure: switch_userns");
+ if (!caps_down_fsetid())
+ die("failure: caps_down_fsetid");
+
/* create regular file via open() */
file1_fd = openat(open_tree_fd, FILE1, O_CREAT | O_EXCL | O_CLOEXEC, S_IXGRP | S_ISGID);
if (file1_fd < 0)
die("failure: is_setgid");
}
+ /* create a special file via mknodat() vfs_create */
+ if (mknodat(open_tree_fd, FILE2, S_IFREG | S_ISGID | S_IXGRP, 0))
+ die("failure: mknodat");
+
+ if (is_setgid(open_tree_fd, FILE2, 0))
+ die("failure: is_setgid");
+
+ /* create a whiteout device via mknodat() vfs_mknod */
+ if (mknodat(open_tree_fd, CHRDEV1, S_IFCHR | S_ISGID | S_IXGRP, 0))
+ die("failure: mknodat");
+
+ if (is_setgid(open_tree_fd, CHRDEV1, 0))
+ die("failure: is_setgid");
+
if (!expected_uid_gid(open_tree_fd, FILE1, 0, 0, 0))
die("failure: check ownership");
if (!expected_uid_gid(open_tree_fd, DIR1, 0, 0, 0))
die("failure: check ownership");
+ if (!expected_uid_gid(open_tree_fd, FILE2, 0, 0, 0))
+ die("failure: check ownership");
+
+ if (!expected_uid_gid(open_tree_fd, CHRDEV1, 0, 0, 0))
+ die("failure: check ownership");
+
+ if (unlinkat(open_tree_fd, FILE1, 0))
+ die("failure: delete");
+
+ if (unlinkat(open_tree_fd, DIR1, AT_REMOVEDIR))
+ die("failure: delete");
+
+ if (unlinkat(open_tree_fd, FILE2, 0))
+ die("failure: delete");
+
+ if (unlinkat(open_tree_fd, CHRDEV1, 0))
+ die("failure: delete");
+
exit(EXIT_SUCCESS);
}
if (wait_for_pid(pid))