File: cachestat.c

package info (click to toggle)
strace 6.13%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 71,488 kB
  • sloc: ansic: 176,497; sh: 9,675; makefile: 4,133; cpp: 885; awk: 353; perl: 267; exp: 62; sed: 9
file content (108 lines) | stat: -rw-r--r-- 2,886 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
/*
 * Check decoding of cachestat syscall.
 *
 * Copyright (c) 2023 Dmitry V. Levin <ldv@strace.io>
 * All rights reserved.
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 */

#include "tests.h"
#include "scno.h"
#include "cachestat.h"

#include <stdio.h>
#include <unistd.h>

#ifndef SKIP_IF_PROC_IS_UNAVAILABLE
# define SKIP_IF_PROC_IS_UNAVAILABLE skip_if_unavailable("/proc/self/fd/")
#endif

#ifndef FD9_PATH
# define FD9_PATH "</dev/full>"
#endif

#ifdef RETVAL_INJECTED
# define INJ_STR " (INJECTED)\n"
#else
# define INJ_STR "\n"
#endif

#ifndef TRACE_FDS
# define TRACE_FDS 0
#endif
#ifndef TRACE_PATH
# define TRACE_PATH 0
#endif
#define TRACE_FILTERED (TRACE_FDS || TRACE_PATH)

static const char *errstr;

static long
k_cachestat(const unsigned int fd, const void *crange,
	      const void *cstat, const unsigned int flags)
{
	const kernel_ulong_t fill = (kernel_ulong_t) 0xbadc0ded00000000ULL;
	const kernel_ulong_t arg1 = fill | fd;
	const kernel_ulong_t arg2 = (uintptr_t) crange;
	const kernel_ulong_t arg3 = (uintptr_t) cstat;
	const kernel_ulong_t arg4 = fill | flags;
	const kernel_ulong_t arg5 = fill | 0xdecaffed;
	const kernel_ulong_t arg6 = fill | 0xdeefaced;
	const long rc = syscall(__NR_cachestat,
				arg1, arg2, arg3, arg4, arg5, arg6);
	errstr = sprintrc(rc);
	return rc;
}

int
main(void)
{
	SKIP_IF_PROC_IS_UNAVAILABLE;

	k_cachestat(-1, 0, 0, 0);
#if !TRACE_FILTERED
	printf("cachestat(-1, NULL, NULL, 0) = %s" INJ_STR, errstr);
#endif

	k_cachestat(9, 0, 0, -1U);
	printf("cachestat(9%s, NULL, NULL, %#x) = %s" INJ_STR,
	       FD9_PATH, -1U, errstr);

	TAIL_ALLOC_OBJECT_CONST_PTR(struct cachestat_range, crange);
	fill_memory(crange, sizeof(*crange));
	const void *const bad_crange = (void *) crange + 1;

	k_cachestat(9, bad_crange, 0, 0);
	printf("cachestat(9%s, %p, NULL, 0) = %s" INJ_STR,
	       FD9_PATH, bad_crange, errstr);

	TAIL_ALLOC_OBJECT_CONST_PTR(struct cachestat, cstat);
	fill_memory(cstat, sizeof(*cstat));
	const void *const bad_cstat = (void *) cstat + 1;

	k_cachestat(9, crange, bad_cstat, 0);
	printf("cachestat(9%s, {off=%#llx, len=%llu}, %p, 0) = %s"
	       INJ_STR, FD9_PATH,
	       (unsigned long long) crange->off,
	       (unsigned long long) crange->len,
	       bad_cstat, errstr);

	if (k_cachestat(9, 0, cstat, 0) < 0) {
		printf("cachestat(9%s, NULL, %p, 0) = %s" INJ_STR,
		       FD9_PATH, cstat, errstr);
	} else {
		printf("cachestat(9%s, NULL, {nr_cache=%llu"
		       ", nr_dirty=%llu, nr_writeback=%llu, nr_evicted=%llu"
		       ", nr_recently_evicted=%llu}, 0) = %s" INJ_STR, FD9_PATH,
		       (unsigned long long) cstat->nr_cache,
		       (unsigned long long) cstat->nr_dirty,
		       (unsigned long long) cstat->nr_writeback,
		       (unsigned long long) cstat->nr_evicted,
		       (unsigned long long) cstat->nr_recently_evicted,
		       errstr);
	}

	puts("+++ exited with 0 +++");
	return 0;
}