1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) 2017 Fujitsu Ltd.
4 * Ported: Guangwen Feng <fenggw-fnst@cn.fujitsu.com>
5 */
6
7 /*
8 * This is a regression test about the race in autogroup, this test
9 * can crash the buggy kernel, and the bug has been fixed in:
10 *
11 * commit 18f649ef344127ef6de23a5a4272dbe2fdb73dde
12 * Author: Oleg Nesterov <oleg@redhat.com>
13 * Date: Mon Nov 14 19:46:09 2016 +0100
14 *
15 * sched/autogroup: Fix autogroup_move_group() to never skip sched_move_task()
16 */
17
18 #include <sys/types.h>
19 #include <unistd.h>
20 #include <stdlib.h>
21 #include "tst_test.h"
22
23 #define LOOPS 1000
24 #define PATH_AUTOGROUP "/proc/sys/kernel/sched_autogroup_enabled"
25
26 static int orig_autogroup = -1;
27
do_test(void)28 static void do_test(void)
29 {
30 int i;
31
32 if (!SAFE_FORK()) {
33 SAFE_FILE_PRINTF(PATH_AUTOGROUP, "%d", 1);
34 SAFE_SETSID();
35
36 if (SAFE_FORK())
37 pause();
38
39 SAFE_KILL(getppid(), SIGKILL);
40 usleep(1000);
41
42 // The child has gone, the grandchild runs with kref == 1
43 SAFE_FILE_PRINTF(PATH_AUTOGROUP, "%d", 0);
44 SAFE_SETSID();
45
46 // runs with the freed ag/tg
47 for (i = 0; i < LOOPS; i++)
48 usleep(10);
49
50 TST_CHECKPOINT_WAKE(0);
51
52 exit(0);
53 }
54
55 SAFE_WAIT(NULL); // destroy the child's ag/tg
56
57 TST_CHECKPOINT_WAIT(0);
58
59 tst_res(TPASS, "Bug not reproduced");
60 }
61
setup(void)62 static void setup(void)
63 {
64 if (access(PATH_AUTOGROUP, F_OK))
65 tst_brk(TCONF, "autogroup not supported");
66
67 SAFE_FILE_SCANF(PATH_AUTOGROUP, "%d", &orig_autogroup);
68 }
69
cleanup(void)70 static void cleanup(void)
71 {
72 if (orig_autogroup != -1)
73 SAFE_FILE_PRINTF(PATH_AUTOGROUP, "%d", orig_autogroup);
74 }
75
76 static struct tst_test test = {
77 .forks_child = 1,
78 .needs_root = 1,
79 .needs_checkpoints = 1,
80 .setup = setup,
81 .cleanup = cleanup,
82 .test_all = do_test,
83 .tags = (const struct tst_tag[]) {
84 {"linux-git", "18f649ef3441"},
85 {}
86 }
87 };
88