1#
2# Copyright (C) 2020 The Android Open Source Project
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#      http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15#
16
17import math
18
19import target_file_utils
20
21from parse import with_pattern
22from proc_tests import KernelProcFileTestBase
23from vts.utils.python.android import api
24
25
26# Test for /proc/sys/kernel/*.
27class ProcCorePattern(KernelProcFileTestBase.KernelProcFileTestBase):
28    '''/proc/sys/kernel/core_pattern is used to specify a core dumpfile pattern
29    name.
30    '''
31
32    def parse_contents(self, contents):
33        pass
34
35    def get_path(self):
36        return "/proc/sys/kernel/core_pattern"
37
38    def get_permission_checker(self):
39        return target_file_utils.IsReadWrite
40
41
42class ProcCorePipeLimit(KernelProcFileTestBase.KernelProcFileTestBase):
43    '''/proc/sys/kernel/core_pipe_limit defines how many concurrent crashing
44    processes may be piped to user space applications in parallel.
45    '''
46
47    def parse_contents(self, contents):
48        return self.parse_line("{:d}\n", contents)[0]
49
50    def get_path(self):
51        return "/proc/sys/kernel/core_pipe_limit"
52
53    def get_permission_checker(self):
54        return target_file_utils.IsReadWrite
55
56
57class ProcDmesgRestrict(KernelProcFileTestBase.KernelProcFileTestBase):
58    '''/proc/sys/kernel/dmesg_restrict indicates whether unprivileged users are
59    prevented from using dmesg.
60    '''
61
62    def parse_contents(self, contents):
63        return self.parse_line("{:d}\n", contents)[0]
64
65    def result_correct(self, result):
66        return result in [0, 1]
67
68    def get_path(self):
69        return "/proc/sys/kernel/dmesg_restrict"
70
71    def get_permission_checker(self):
72        return target_file_utils.IsReadWrite
73
74
75class ProcDomainname(KernelProcFileTestBase.KernelProcFileTestBase):
76    '''/proc/sys/kernel/domainname determines YP/NIS domain name of the system.'''
77
78    def parse_contents(self, contents):
79        pass
80
81    def get_path(self):
82        return "/proc/sys/kernel/domainname"
83
84    def get_permission_checker(self):
85        return target_file_utils.IsReadWrite
86
87
88class ProcHostname(KernelProcFileTestBase.KernelProcFileTestBase):
89    '''/proc/sys/kernel/hostname determines the system's host name.'''
90
91    def parse_contents(self, contents):
92        pass
93
94    def get_path(self):
95        return "/proc/sys/kernel/hostname"
96
97    def get_permission_checker(self):
98        return target_file_utils.IsReadWrite
99
100
101class ProcHungTaskTimeoutSecs(KernelProcFileTestBase.KernelProcFileTestBase):
102    '''/proc/sys/kernel/hung_task_timeout_secs controls the default timeout
103    (in seconds) used to determine when a task has become non-responsive and
104    should be considered hung.
105    '''
106
107    def parse_contents(self, contents):
108        return self.parse_line("{:d}\n", contents)[0]
109
110    def get_path(self):
111        return "/proc/sys/kernel/hung_task_timeout_secs"
112
113    def get_permission_checker(self):
114        return target_file_utils.IsReadWrite
115
116    def file_optional(self, shell=None, dut=None):
117        return True
118
119class ProcKptrRestrictTest(KernelProcFileTestBase.KernelProcFileTestBase):
120    '''/proc/sys/kernel/kptr_restrict determines whether kernel pointers are printed
121    in proc files.
122    '''
123
124    def parse_contents(self, contents):
125        return self.parse_line("{:d}\n", contents)[0]
126
127    def result_correct(self, result):
128        return result >= 0 and result <= 4
129
130    def get_path(self):
131        return "/proc/sys/kernel/kptr_restrict"
132
133    def get_permission_checker(self):
134        """Get r/w file permission checker.
135        """
136        return target_file_utils.IsReadWrite
137
138
139class ProcModulesDisabled(KernelProcFileTestBase.KernelProcFileTestBase):
140    '''/proc/sys/kernel/modules_disabled indicates if modules are allowed to be
141    loaded.
142    '''
143
144    def parse_contents(self, contents):
145        return self.parse_line("{:d}\n", contents)[0]
146
147    def result_correct(self, result):
148        return result in [0, 1]
149
150    def get_path(self):
151        return "/proc/sys/kernel/modules_disabled"
152
153    def get_permission_checker(self):
154        return target_file_utils.IsReadWrite
155
156
157class ProcPanicOnOops(KernelProcFileTestBase.KernelProcFileTestBase):
158    '''/proc/sys/kernel/panic_on_oops controls kernel's behaviour on oops.'''
159
160    def parse_contents(self, contents):
161        return self.parse_line("{:d}\n", contents)[0]
162
163    def result_correct(self, result):
164        return result in [0, 1]
165
166    def get_path(self):
167        return "/proc/sys/kernel/panic_on_oops"
168
169    def get_permission_checker(self):
170        return target_file_utils.IsReadWrite
171
172
173class ProcPerfEventMaxSampleRate(KernelProcFileTestBase.KernelProcFileTestBase):
174    '''/proc/sys/kernel/perf_event_max_sample_rate sets the maximum sample rate
175    of performance events.
176    '''
177
178    def parse_contents(self, contents):
179        return self.parse_line("{:d}\n", contents)[0]
180
181    def get_path(self):
182        return "/proc/sys/kernel/perf_event_max_sample_rate"
183
184    def get_permission_checker(self):
185        return target_file_utils.IsReadWrite
186
187
188class ProcPerfEventParanoid(KernelProcFileTestBase.KernelProcFileTestBase):
189    '''/proc/sys/kernel/perf_event_paranoid controls use of the performance
190    events system by unprivileged users.
191    '''
192
193    def parse_contents(self, contents):
194        return self.parse_line("{:d}\n", contents)[0]
195
196    def get_path(self):
197        return "/proc/sys/kernel/perf_event_paranoid"
198
199    def get_permission_checker(self):
200        return target_file_utils.IsReadWrite
201
202
203class ProcPidMax(KernelProcFileTestBase.KernelProcFileTestBase):
204    '''/proc/sys/kernel/pid_max is the pid allocation wrap value.'''
205
206    def parse_contents(self, contents):
207        return self.parse_line("{:d}\n", contents)[0]
208
209    def get_path(self):
210        return "/proc/sys/kernel/pid_max"
211
212    def get_permission_checker(self):
213        return target_file_utils.IsReadWrite
214
215
216@with_pattern(
217    r"^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
218)
219def token_uuid(text):
220    return text
221
222class ProcSysKernelRandomBootId(KernelProcFileTestBase.KernelProcFileTestBase):
223    '''/proc/sys/kernel/random/boot_id generates a random ID each boot.'''
224
225    def parse_contents(self, contents):
226        return self.parse_line("{:uuid}", contents, dict(uuid=token_uuid))[0]
227
228    def get_path(self):
229        return "/proc/sys/kernel/random/boot_id"
230
231    def get_permission_checker(self):
232        return target_file_utils.IsReadOnly
233
234
235class ProcRandomizeVaSpaceTest(KernelProcFileTestBase.KernelProcFileTestBase):
236    '''/proc/sys/kernel/randomize_va_space determines the address layout randomization
237    policy for the system.
238    '''
239
240    def parse_contents(self, contents):
241        return self.parse_line("{:d}\n", contents)[0]
242
243    def result_correct(self, result):
244        return result >= 0 and result <= 2
245
246    def get_path(self):
247        return "/proc/sys/kernel/randomize_va_space"
248
249    def get_permission_checker(self):
250        """Get r/w file permission checker.
251        """
252        return target_file_utils.IsReadWrite
253
254
255class ProcSchedChildRunsFirst(KernelProcFileTestBase.KernelProcFileTestBase):
256    '''/proc/sys/kernel/sched_child_runs_first causes newly forked tasks to
257    be favored in scheduling over their parents.
258    '''
259
260    def parse_contents(self, contents):
261        return self.parse_line("{:d}\n", contents)[0]
262
263    def get_path(self):
264        return "/proc/sys/kernel/sched_child_runs_first"
265
266    def get_permission_checker(self):
267        return target_file_utils.IsReadWrite
268
269
270class ProcSchedLatencyNS(KernelProcFileTestBase.KernelProcFileTestBase):
271    '''/proc/sys/kernel/sched_latency_ns is the maximum latency in nanoseconds a
272    task may incur prior to being scheduled.
273    '''
274
275    def parse_contents(self, contents):
276        return self.parse_line("{:d}\n", contents)[0]
277
278    def result_correct(self, result):
279        return result >= 100000 and result <= 1000000000
280
281    def get_path(self):
282        return "/proc/sys/kernel/sched_latency_ns"
283
284    def get_permission_checker(self):
285        return target_file_utils.IsReadWrite
286
287
288class ProcSchedRTPeriodUS(KernelProcFileTestBase.KernelProcFileTestBase):
289    '''/proc/sys/kernel/sched_rt_period_us defines the period length used by the
290    system-wide RT execution limit in microseconds.
291    '''
292
293    def parse_contents(self, contents):
294        return self.parse_line("{:d}\n", contents)[0]
295
296    def result_correct(self, result):
297        return result >= 1 and result <= math.pow(2,31)
298
299    def get_path(self):
300        return "/proc/sys/kernel/sched_rt_period_us"
301
302    def get_permission_checker(self):
303        return target_file_utils.IsReadWrite
304
305
306class ProcSchedRTRuntimeUS(KernelProcFileTestBase.KernelProcFileTestBase):
307    '''/proc/sys/kernel/sched_rt_runtime_us defines the amount of time in
308    microseconds relative to sched_rt_period_us that the system may execute RT
309    tasks.
310    '''
311
312    def parse_contents(self, contents):
313        return self.parse_line("{:d}\n", contents)[0]
314
315    def result_correct(self, result):
316        return result >= -1 and result <= (math.pow(2,31) - 1)
317
318    def get_path(self):
319        return "/proc/sys/kernel/sched_rt_runtime_us"
320
321    def get_permission_checker(self):
322        return target_file_utils.IsReadWrite
323
324
325class ProcSchedTunableScaling(KernelProcFileTestBase.KernelProcFileTestBase):
326    '''/proc/sys/kernel/sched_tunable_scaling determines whether
327    sched_latency_ns should be automatically adjusted by the scheduler based on
328    the number of CPUs.
329    '''
330
331    def parse_contents(self, contents):
332        return self.parse_line("{:d}\n", contents)[0]
333
334    def result_correct(self, result):
335        return result >= 0 and result <= 2
336
337    def get_path(self):
338        return "/proc/sys/kernel/sched_tunable_scaling"
339
340    def get_permission_checker(self):
341        return target_file_utils.IsReadWrite
342
343
344class ProcSchedWakeupGranularityNS(
345    KernelProcFileTestBase.KernelProcFileTestBase):
346    '''/proc/sys/kernel/sched_wakeup_granularity_ns defines how much more
347    virtual runtime task A must have than task B in nanoseconds in order for
348    task B to preempt it.
349    '''
350
351    def parse_contents(self, contents):
352        return self.parse_line("{:d}\n", contents)[0]
353
354    def result_correct(self, result):
355        return result >= 0 and result <= 1000000000
356
357    def get_path(self):
358        return "/proc/sys/kernel/sched_wakeup_granularity_ns"
359
360    def get_permission_checker(self):
361        return target_file_utils.IsReadWrite
362
363
364class ProcSysRqTest(KernelProcFileTestBase.KernelProcFileTestBase):
365    '''/proc/sys/kernel/sysrq controls the functions allowed to be invoked
366    via the SysRq key.'''
367
368    def parse_contents(self, contents):
369        return self.parse_line("{:d}\n", contents)[0]
370
371    def result_correct(self, result):
372        return result >= 0 and result <= 511
373
374    def get_path(self):
375        return "/proc/sys/kernel/sysrq"
376
377    def get_permission_checker(self):
378        return target_file_utils.IsReadWrite
379
380
381# Tests for /proc/sys/vm/*.
382
383class ProcDirtyBackgroundBytes(KernelProcFileTestBase.KernelProcFileTestBase):
384    '''/proc/sys/vm/dirty_background_bytes contains the amount of dirty memory
385    at which the background kernel flusher threads will start writeback.
386    '''
387
388    def parse_contents(self, contents):
389        return self.parse_line("{:d}\n", contents)[0]
390
391    def get_path(self):
392        return "/proc/sys/vm/dirty_background_bytes"
393
394    def get_permission_checker(self):
395        return target_file_utils.IsReadWrite
396
397
398class ProcDirtyBackgroundRatio(KernelProcFileTestBase.KernelProcFileTestBase):
399    '''/proc/sys/vm/dirty_background_ratio contains, as a percentage of total
400    available memory that contains free pages and reclaimable pages, the number
401    of pages at which the background kernel flusher threads will start writing
402    out dirty data.
403    '''
404
405    def parse_contents(self, contents):
406        return self.parse_line("{:d}\n", contents)[0]
407
408    def result_correct(self, result):
409        return result >= 0 and result <= 100
410
411    def get_path(self):
412        return "/proc/sys/vm/dirty_background_ratio"
413
414    def get_permission_checker(self):
415        return target_file_utils.IsReadWrite
416
417
418class ProcDirtyExpireCentisecs(KernelProcFileTestBase.KernelProcFileTestBase):
419    '''/proc/sys/vm/dirty_expire_centisecs is used to define when dirty data is
420    old enough to be eligible for writeout by the kernel flusher threads.
421    '''
422
423    def parse_contents(self, contents):
424        return self.parse_line("{:d}\n", contents)[0]
425
426    def get_path(self):
427        return "/proc/sys/vm/dirty_expire_centisecs"
428
429    def get_permission_checker(self):
430        return target_file_utils.IsReadWrite
431
432
433class ProcDropCaches(KernelProcFileTestBase.KernelProcFileTestBase):
434    '''Writing to /proc/sys/vm/drop_caches will cause the kernel to drop clean
435    caches.
436    '''
437
438    def parse_contents(self, contents):
439        # Format of this file is not documented, so don't check that.
440        return ''
441
442    def get_path(self):
443        return "/proc/sys/vm/drop_caches"
444
445    def IsReadWriteOrWriteOnly(self, permission_bits):
446        return (target_file_utils.IsReadWrite(permission_bits) or
447                target_file_utils.IsWriteOnly(permission_bits))
448
449    def get_permission_checker(self):
450        if self.api_level > api.PLATFORM_API_LEVEL_Q:
451            return target_file_utils.IsWriteOnly
452        else:
453            return self.IsReadWriteOrWriteOnly
454
455    def test_format(self):
456        return False
457
458class ProcExtraFreeKbytes(KernelProcFileTestBase.KernelProcFileTestBase):
459    '''/proc/sys/vm/extra_free_kbytes tells the VM to keep extra free memory
460    between the threshold where background reclaim (kswapd) kicks in, and the
461    threshold where direct reclaim (by allocating processes) kicks in.
462    '''
463
464    def parse_contents(self, contents):
465        return self.parse_line("{:d}\n", contents)[0]
466
467    def get_path(self):
468        return "/proc/sys/vm/extra_free_kbytes"
469
470    def get_permission_checker(self):
471        return target_file_utils.IsReadWrite
472
473    def file_optional(self, shell=None, dut=None):
474        # This file isn't in Android common kernel.
475        return True
476
477
478class ProcOverCommitMemoryTest(KernelProcFileTestBase.KernelProcFileTestBase):
479    '''/proc/sys/vm/overcommit_memory determines the kernel virtual memory accounting mode.
480    '''
481
482    def parse_contents(self, contents):
483        return self.parse_line("{:d}\n", contents)[0]
484
485    def result_correct(self, result):
486        return result >= 0 and result <= 2
487
488    def get_path(self):
489        return "/proc/sys/vm/overcommit_memory"
490
491    def get_permission_checker(self):
492        """Get r/w file permission checker.
493        """
494        return target_file_utils.IsReadWrite
495
496
497class ProcMaxMapCount(KernelProcFileTestBase.KernelProcFileTestBase):
498    '''/proc/sys/vm/max_map_count contains the maximum number of memory map areas a process
499    may have.
500    '''
501
502    def parse_contents(self, contents):
503        return self.parse_line("{:d}\n", contents)[0]
504
505    def get_path(self):
506        return "/proc/sys/vm/max_map_count"
507
508    def get_permission_checker(self):
509        return target_file_utils.IsReadWrite
510
511
512class ProcMmapMinAddrTest(KernelProcFileTestBase.KernelProcFileTestBase):
513    '''/proc/sys/vm/mmap_min_addr specifies the minimum address that can be mmap'd.
514    '''
515
516    def parse_contents(self, contents):
517        return self.parse_line("{:d}\n", contents)[0]
518
519    def get_path(self):
520        return "/proc/sys/vm/mmap_min_addr"
521
522    def get_permission_checker(self):
523        """Get r/w file permission checker.
524        """
525        return target_file_utils.IsReadWrite
526
527
528class ProcMmapRndBitsTest(KernelProcFileTestBase.KernelProcFileTestBase):
529    '''/proc/sys/vm/mmap_rnd_(compat_)bits specifies the amount of randomness in mmap'd
530    addresses. Must be >= 8.
531    '''
532
533    def parse_contents(self, contents):
534        return self.parse_line("{:d}\n", contents)[0]
535
536    def result_correct(self, result):
537        return result >= 8
538
539    def get_path(self):
540        return "/proc/sys/vm/mmap_rnd_bits"
541
542    def get_permission_checker(self):
543        """Get r/w file permission checker.
544        """
545        return target_file_utils.IsReadWrite
546
547
548class ProcMmapRndCompatBitsTest(ProcMmapRndBitsTest):
549    def get_path(self):
550        return "/proc/sys/vm/mmap_rnd_compat_bits"
551
552
553class ProcPageCluster(KernelProcFileTestBase.KernelProcFileTestBase):
554    '''/proc/sys/vm/page-cluster controls the number of pages up to which
555    consecutive pages are read in from swap in a single attempt.
556    '''
557
558    def parse_contents(self, contents):
559        return self.parse_line("{:d}\n", contents)[0]
560
561    def get_path(self):
562        return "/proc/sys/vm/page-cluster"
563
564    def get_permission_checker(self):
565        return target_file_utils.IsReadWrite
566
567
568# Tests for /proc/sys/fs/*.
569
570class ProcPipeMaxSize(KernelProcFileTestBase.KernelProcFileTestBase):
571    '''/proc/sys/fs/pipe-max-size reports the maximum size (in bytes) of
572    individual pipes.
573    '''
574
575    def parse_contents(self, contents):
576        return self.parse_line("{:d}\n", contents)[0]
577
578    def get_path(self):
579        return "/proc/sys/fs/pipe-max-size"
580
581    def get_permission_checker(self):
582        return target_file_utils.IsReadWrite
583
584
585class ProcProtectedHardlinks(KernelProcFileTestBase.KernelProcFileTestBase):
586    '''/proc/sys/fs/protected_hardlinks reports hardlink creation behavior.'''
587
588    def parse_contents(self, contents):
589        return self.parse_line("{:d}\n", contents)[0]
590
591    def result_correct(self, result):
592        return result in [0, 1]
593
594    def get_path(self):
595        return "/proc/sys/fs/protected_hardlinks"
596
597    def get_permission_checker(self):
598        return target_file_utils.IsReadWrite
599
600
601class ProcProtectedSymlinks(KernelProcFileTestBase.KernelProcFileTestBase):
602    '''/proc/sys/fs/protected_symlinks reports symlink following behavior.'''
603
604    def parse_contents(self, contents):
605        return self.parse_line("{:d}\n", contents)[0]
606
607    def result_correct(self, result):
608        return result in [0, 1]
609
610    def get_path(self):
611        return "/proc/sys/fs/protected_symlinks"
612
613    def get_permission_checker(self):
614        return target_file_utils.IsReadWrite
615
616
617class ProcSuidDumpable(KernelProcFileTestBase.KernelProcFileTestBase):
618    '''/proc/sys/fs/suid_dumpable value can be used to query and set the core
619    dump mode for setuid or otherwise protected/tainted binaries.
620    '''
621
622    def parse_contents(self, contents):
623        return self.parse_line("{:d}\n", contents)[0]
624
625    def result_correct(self, result):
626        return result in [0, 1, 2]
627
628    def get_path(self):
629        return "/proc/sys/fs/suid_dumpable"
630
631    def get_permission_checker(self):
632        return target_file_utils.IsReadWrite
633
634
635class ProcUptime(KernelProcFileTestBase.KernelProcFileTestBase):
636    '''/proc/uptime tells how long the system has been running.'''
637
638    def parse_contents(self, contents):
639        return self.parse_line("{:f} {:f}\n", contents)[0]
640
641    def get_path(self):
642        return "/proc/uptime"
643