History

selftests: cgroup: Test open-time credential usage for migration checks

When a task is writing to an fd opened by a different task, the perm check should use the credentials of the latter task. Add a test for it.

Tejun Heo committed 4 years ago

Commit 613e0401 parent b09c2ba1 file · +68 −0Browse files

Unified · Split

tools/testing/selftests/cgroup/test_core.c+68−0
@@ -674,6 +674,73 @@ cleanup: · 673 unmodified lines
674674 return ret;
675675 }
676676
677+/*
678+ * cgroup migration permission check should be performed based on the
679+ * credentials at the time of open instead of write.
680+ */
681+static int test_cgcore_lesser_euid_open(const char *root)
682+{
683+ const uid_t test_euid = 65534; /* usually nobody, any !root is fine */
684+ int ret = KSFT_FAIL;
685+ char *cg_test_a = NULL, *cg_test_b = NULL;
686+ char *cg_test_a_procs = NULL, *cg_test_b_procs = NULL;
687+ int cg_test_b_procs_fd = -1;
688+ uid_t saved_uid;
689+
690+ cg_test_a = cg_name(root, "cg_test_a");
691+ cg_test_b = cg_name(root, "cg_test_b");
692+
693+ if (!cg_test_a || !cg_test_b)
694+ goto cleanup;
695+
696+ cg_test_a_procs = cg_name(cg_test_a, "cgroup.procs");
697+ cg_test_b_procs = cg_name(cg_test_b, "cgroup.procs");
698+
699+ if (!cg_test_a_procs || !cg_test_b_procs)
700+ goto cleanup;
701+
702+ if (cg_create(cg_test_a) || cg_create(cg_test_b))
703+ goto cleanup;
704+
705+ if (cg_enter_current(cg_test_a))
706+ goto cleanup;
707+
708+ if (chown(cg_test_a_procs, test_euid, -1) ||
709+ chown(cg_test_b_procs, test_euid, -1))
710+ goto cleanup;
711+
712+ saved_uid = geteuid();
713+ if (seteuid(test_euid))
714+ goto cleanup;
715+
716+ cg_test_b_procs_fd = open(cg_test_b_procs, O_RDWR);
717+
718+ if (seteuid(saved_uid))
719+ goto cleanup;
720+
721+ if (cg_test_b_procs_fd < 0)
722+ goto cleanup;
723+
724+ if (write(cg_test_b_procs_fd, "0", 1) >= 0 || errno != EACCES)
725+ goto cleanup;
726+
727+ ret = KSFT_PASS;
728+
729+cleanup:
730+ cg_enter_current(root);
731+ if (cg_test_b_procs_fd >= 0)
732+ close(cg_test_b_procs_fd);
733+ if (cg_test_b)
734+ cg_destroy(cg_test_b);
735+ if (cg_test_a)
736+ cg_destroy(cg_test_a);
737+ free(cg_test_b_procs);
738+ free(cg_test_a_procs);
739+ free(cg_test_b);
740+ free(cg_test_a);
741+ return ret;
742+}
743+
677744 #define T(x) { x, #x }
678745 struct corecg_test {
679746 int (*fn)(const char *root);
@@ -689,6 +756,7 @@ struct corecg_test { · 9 unmodified lines
689756 T(test_cgcore_proc_migration),
690757 T(test_cgcore_thread_migration),
691758 T(test_cgcore_destroy),
759+ T(test_cgcore_lesser_euid_open),
692760 };
693761 #undef T
694762