1 /*
2  * Copyright (c) 2015-2017 Dmitry V. Levin <ldv@altlinux.org>
3  * Copyright (c) 2015-2018 The strace developers.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include "tests.h"
30 #include <asm/unistd.h>
31 
32 #if defined __NR_sched_getattr && defined __NR_sched_setattr
33 
34 # include <inttypes.h>
35 # include <stdio.h>
36 # include <sched.h>
37 # include <unistd.h>
38 # include "sched_attr.h"
39 # include "xlat.h"
40 # include "xlat/schedulers.h"
41 
42 static const char *errstr;
43 
44 static long
sys_sched_getattr(kernel_ulong_t pid,kernel_ulong_t attr,kernel_ulong_t size,kernel_ulong_t flags)45 sys_sched_getattr(kernel_ulong_t pid, kernel_ulong_t attr,
46 		  kernel_ulong_t size, kernel_ulong_t flags)
47 {
48 	long rc = syscall(__NR_sched_getattr, pid, attr, size, flags);
49 	errstr = sprintrc(rc);
50 	return rc;
51 }
52 
53 static long
sys_sched_setattr(kernel_ulong_t pid,kernel_ulong_t attr,kernel_ulong_t flags)54 sys_sched_setattr(kernel_ulong_t pid, kernel_ulong_t attr, kernel_ulong_t flags)
55 {
56 	long rc = syscall(__NR_sched_setattr, pid, attr, flags);
57 	errstr = sprintrc(rc);
58 	return rc;
59 }
60 
61 int
main(void)62 main(void)
63 {
64 	static const kernel_ulong_t bogus_pid =
65 		(kernel_ulong_t) 0xdefacedfacefeedULL;
66 	static const kernel_ulong_t bogus_size =
67 		(kernel_ulong_t) 0xdefacedcafef00dULL;
68 	static const kernel_ulong_t bogus_flags =
69 		(kernel_ulong_t) 0xdefaceddeadc0deULL;
70 
71 	TAIL_ALLOC_OBJECT_CONST_PTR(struct sched_attr, attr);
72 	TAIL_ALLOC_OBJECT_CONST_PTR(unsigned int, psize);
73 	void *const efault = attr + 1;
74 
75 	sys_sched_getattr(0, 0, 0, 0);
76 	printf("sched_getattr(0, NULL, 0, 0) = %s\n", errstr);
77 
78 	sys_sched_getattr(0, (unsigned long) attr, 0, 0);
79 	printf("sched_getattr(0, %p, 0, 0) = %s\n", attr, errstr);
80 
81 	sys_sched_getattr(bogus_pid, 0, 0, 0);
82 	printf("sched_getattr(%d, NULL, 0, 0) = %s\n", (int) bogus_pid, errstr);
83 
84 	sys_sched_getattr(-1U, (unsigned long) attr, bogus_size, bogus_flags);
85 	printf("sched_getattr(-1, %p, %s%u, %u) = %s\n",
86 	       attr,
87 # if defined __arm64__ || defined __aarch64__
88 	       "0xdefaced<<32|",
89 # else
90 	       "",
91 # endif
92 	       (unsigned) bogus_size, (unsigned) bogus_flags, errstr);
93 
94 	sys_sched_getattr(0, (unsigned long) efault, sizeof(*attr), 0);
95 	printf("sched_getattr(0, %p, %u, 0) = %s\n",
96 	       efault, (unsigned) sizeof(*attr), errstr);
97 
98 	if (sys_sched_getattr(0, (unsigned long) attr, sizeof(*attr), 0))
99 		perror_msg_and_skip("sched_getattr");
100 	printf("sched_getattr(0, {size=%u, sched_policy=", attr->size);
101 	printxval(schedulers, attr->sched_policy, NULL);
102 	printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u"
103 	       ", sched_runtime=%" PRIu64 ", sched_deadline=%" PRIu64
104 	       ", sched_period=%" PRIu64 "}, %u, 0) = 0\n",
105 	       attr->sched_flags ? "SCHED_FLAG_RESET_ON_FORK" : "0",
106 	       attr->sched_nice,
107 	       attr->sched_priority,
108 	       attr->sched_runtime,
109 	       attr->sched_deadline,
110 	       attr->sched_period,
111 	       (unsigned) sizeof(*attr));
112 
113 # if defined __arm64__ || defined __aarch64__
114 	long rc =
115 # endif
116 	sys_sched_getattr(F8ILL_KULONG_MASK, (unsigned long) attr,
117 			  F8ILL_KULONG_MASK | sizeof(*attr), F8ILL_KULONG_MASK);
118 # if defined __arm64__ || defined __aarch64__
119 	if (rc) {
120 		printf("sched_getattr(0, %p, 0xffffffff<<32|%u, 0) = %s\n",
121 		       attr, (unsigned) sizeof(*attr), errstr);
122 	} else
123 # endif
124 	{
125 		printf("sched_getattr(0, {size=%u, sched_policy=", attr->size);
126 		printxval(schedulers, attr->sched_policy, NULL);
127 		printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u"
128 		       ", sched_runtime=%" PRIu64 ", sched_deadline=%" PRIu64
129 		       ", sched_period=%" PRIu64 "}, %u, 0) = 0\n",
130 		       attr->sched_flags ? "SCHED_FLAG_RESET_ON_FORK" : "0",
131 		       attr->sched_nice,
132 		       attr->sched_priority,
133 		       attr->sched_runtime,
134 		       attr->sched_deadline,
135 		       attr->sched_period,
136 		       (unsigned) sizeof(*attr));
137 	}
138 
139 	sys_sched_setattr(bogus_pid, 0, 0);
140 	printf("sched_setattr(%d, NULL, 0) = %s\n", (int) bogus_pid, errstr);
141 
142 	attr->sched_flags |= 1;
143 
144 	if (sys_sched_setattr(0, (unsigned long) attr, 0))
145 		perror_msg_and_skip("sched_setattr");
146 	printf("sched_setattr(0, {size=%u, sched_policy=", attr->size);
147 	printxval(schedulers, attr->sched_policy, NULL);
148 	printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u"
149 	       ", sched_runtime=%" PRIu64 ", sched_deadline=%" PRIu64
150 	       ", sched_period=%" PRIu64 "}, 0) = 0\n",
151 	       "SCHED_FLAG_RESET_ON_FORK",
152 	       attr->sched_nice,
153 	       attr->sched_priority,
154 	       attr->sched_runtime,
155 	       attr->sched_deadline,
156 	       attr->sched_period);
157 
158 	sys_sched_setattr(F8ILL_KULONG_MASK, (unsigned long) attr,
159 			  F8ILL_KULONG_MASK);
160 	printf("sched_setattr(0, {size=%u, sched_policy=", attr->size);
161 	printxval(schedulers, attr->sched_policy, NULL);
162 	printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u"
163 	       ", sched_runtime=%" PRIu64 ", sched_deadline=%" PRIu64
164 	       ", sched_period=%" PRIu64 "}, 0) = 0\n",
165 	       "SCHED_FLAG_RESET_ON_FORK",
166 	       attr->sched_nice,
167 	       attr->sched_priority,
168 	       attr->sched_runtime,
169 	       attr->sched_deadline,
170 	       attr->sched_period);
171 
172 	*psize = attr->size;
173 
174 	sys_sched_setattr(0, (unsigned long) psize, 0);
175 	printf("sched_setattr(0, %p, 0) = %s\n", psize, errstr);
176 
177 	attr->size = 0;
178 
179 	sys_sched_setattr(0, (unsigned long) attr, 0);
180 	printf("sched_setattr(0, {size=%u, sched_policy=", attr->size);
181 	printxval(schedulers, attr->sched_policy, NULL);
182 	printf(", sched_flags=%s, sched_nice=%d, sched_priority=%u"
183 	       ", sched_runtime=%" PRIu64 ", sched_deadline=%" PRIu64
184 	       ", sched_period=%" PRIu64 "}, 0) = 0\n",
185 	       "SCHED_FLAG_RESET_ON_FORK",
186 	       attr->sched_nice,
187 	       attr->sched_priority,
188 	       attr->sched_runtime,
189 	       attr->sched_deadline,
190 	       attr->sched_period);
191 
192 	attr->size = 1;
193 
194 	sys_sched_setattr(0, (unsigned long) attr, 0);
195 	printf("sched_setattr(0, {size=%u} => {size=%u}, 0) = %s\n",
196 	       1, attr->size, errstr);
197 
198 	attr->size = SCHED_ATTR_MIN_SIZE - 1;
199 
200 	sys_sched_setattr(0, (unsigned long) attr, 0);
201 	printf("sched_setattr(0, {size=%u} => {size=%u}, 0) = %s\n",
202 	       SCHED_ATTR_MIN_SIZE - 1, attr->size, errstr);
203 
204 	attr->size = 0x90807060;
205 	attr->sched_policy = 0xca7faced;
206 	attr->sched_flags = 0xbadc0ded1057da78ULL;
207 	attr->sched_nice = 0xafbfcfdf;
208 	attr->sched_priority = 0xb8c8d8e8;
209 	attr->sched_runtime = 0xbadcaffedeadf157ULL;
210 	attr->sched_deadline = 0xc0de70a57badac75ULL;
211 	attr->sched_period = 0xded1ca7edda7aca7ULL;
212 
213 	sys_sched_setattr(bogus_pid, (unsigned long) attr, bogus_flags);
214 	printf("sched_setattr(%d, {size=%u, sched_policy=%#x /* SCHED_??? */, "
215 	       "sched_flags=%#" PRIx64 " /* SCHED_FLAG_??? */, "
216 	       "sched_nice=%d, sched_priority=%u, sched_runtime=%" PRIu64 ", "
217 	       "sched_deadline=%" PRIu64 ", sched_period=%" PRIu64 ", ...}, %u)"
218 	       " = %s\n",
219 	       (int) bogus_pid,
220 	       attr->size,
221 	       attr->sched_policy,
222 	       attr->sched_flags,
223 	       attr->sched_nice,
224 	       attr->sched_priority,
225 	       attr->sched_runtime,
226 	       attr->sched_deadline,
227 	       attr->sched_period,
228 	       (unsigned) bogus_flags, errstr);
229 
230 	if (F8ILL_KULONG_SUPPORTED) {
231 		const kernel_ulong_t ill = f8ill_ptr_to_kulong(attr);
232 
233 		sys_sched_getattr(0, ill, sizeof(*attr), 0);
234 		printf("sched_getattr(0, %#llx, %u, 0) = %s\n",
235 		       (unsigned long long) ill, (unsigned) sizeof(*attr),
236 		       errstr);
237 
238 		sys_sched_setattr(0, ill, 0);
239 		printf("sched_setattr(0, %#llx, 0) = %s\n",
240 		       (unsigned long long) ill, errstr);
241 	}
242 
243 
244 	attr->size = 0x90807060;
245 	attr->sched_policy = 0xca7faced;
246 	attr->sched_flags = 0xfULL;
247 	attr->sched_nice = 0xafbfcfdf;
248 	attr->sched_priority = 0xb8c8d8e8;
249 	attr->sched_runtime = 0xbadcaffedeadf157ULL;
250 	attr->sched_deadline = 0xc0de70a57badac75ULL;
251 	attr->sched_period = 0xded1ca7edda7aca7ULL;
252 
253 	sys_sched_setattr(bogus_pid, (unsigned long) attr, bogus_flags);
254 	printf("sched_setattr(%d, {size=%u, sched_policy=%#x /* SCHED_??? */, "
255 	       "sched_flags=SCHED_FLAG_RESET_ON_FORK|SCHED_FLAG_RECLAIM|"
256 	       "SCHED_FLAG_DL_OVERRUN|0x8, "
257 	       "sched_nice=%d, sched_priority=%u, sched_runtime=%" PRIu64 ", "
258 	       "sched_deadline=%" PRIu64 ", sched_period=%" PRIu64 ", ...}, %u)"
259 	       " = %s\n",
260 	       (int) bogus_pid,
261 	       attr->size,
262 	       attr->sched_policy,
263 	       attr->sched_nice,
264 	       attr->sched_priority,
265 	       attr->sched_runtime,
266 	       attr->sched_deadline,
267 	       attr->sched_period,
268 	       (unsigned) bogus_flags, errstr);
269 
270 	if (F8ILL_KULONG_SUPPORTED) {
271 		const kernel_ulong_t ill = f8ill_ptr_to_kulong(attr);
272 
273 		sys_sched_getattr(0, ill, sizeof(*attr), 0);
274 		printf("sched_getattr(0, %#llx, %u, 0) = %s\n",
275 		       (unsigned long long) ill, (unsigned) sizeof(*attr),
276 		       errstr);
277 
278 		sys_sched_setattr(0, ill, 0);
279 		printf("sched_setattr(0, %#llx, 0) = %s\n",
280 		       (unsigned long long) ill, errstr);
281 	}
282 
283 	puts("+++ exited with 0 +++");
284 	return 0;
285 }
286 
287 #else
288 
289 SKIP_MAIN_UNDEFINED("__NR_sched_getattr && __NR_sched_setattr")
290 
291 #endif
292