1 /*
2 * Check decoding of prlimit64 syscall.
3 *
4 * Copyright (c) 2016-2018 Dmitry V. Levin <ldv@strace.io>
5 * Copyright (c) 2016-2021 The strace developers.
6 * All rights reserved.
7 *
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
10
11 #include "tests.h"
12 #include "scno.h"
13
14 #include <inttypes.h>
15 #include <stdio.h>
16 #include <stdint.h>
17 #include <stdlib.h>
18 #include <sys/resource.h>
19 #include <unistd.h>
20
21 #include "pidns.h"
22 #include "xlat.h"
23 #include "xlat/resources.h"
24
25 #ifndef RETVAL_INJECTED
26 # define RETVAL_INJECTED 0
27 #endif
28
29 #if RETVAL_INJECTED
30 # define INJ_STR " (INJECTED)"
31 #else
32 # define INJ_STR ""
33 #endif
34 #define INJECT_RETVAL 42
35
36 static const char *
37 sprint_rlim(uint64_t lim)
38 {
39 if (lim == -1ULL)
40 return "RLIM64_INFINITY";
41
42 static char buf[2][sizeof(lim)*3 + sizeof("*1024")];
43 static int i;
44 i &= 1;
45 if (lim > 1024 && lim % 1024 == 0)
46 sprintf(buf[i], "%" PRIu64 "*1024", lim / 1024);
47 else
48 sprintf(buf[i], "%" PRIu64, lim);
49
50 return buf[i++];
51 }
52
53 int
54 main(int argc, char *argv[])
55 {
56 PIDNS_TEST_INIT;
57
58 unsigned long pid =
59 (unsigned long) 0xdefaced00000000ULL | (unsigned) getpid();
60 const char *pid_str = pidns_pid2str(PT_TGID);
61 uint64_t *const rlimit = tail_alloc(sizeof(*rlimit) * 2);
62 const struct xlat_data *xlat;
63 long rc;
64 unsigned long num_skip = 256;
65 size_t i = 0;
66
67 if (argc >= 2)
68 num_skip = strtoul(argv[1], NULL, 0);
69
70 for (i = 0; i < num_skip; i++) {
71 long rc = syscall(__NR_prlimit64, 0, 16, 0, 0);
72 pidns_print_leader();
73 printf("prlimit64(0, 0x10 /* RLIMIT_??? */, NULL, NULL)"
74 " = %s%s\n",
75 sprintrc(rc), rc == INJECT_RETVAL ? INJ_STR : "");
76 }
77
78 /* The shortest output */
79 rc = syscall(__NR_prlimit64, 0, RLIMIT_AS, 0, 0);
80 pidns_print_leader();
81 printf("prlimit64(0, RLIMIT_AS, NULL, NULL) = %s" INJ_STR "\n",
82 sprintrc(rc));
83
84 for (i = 0, xlat = resources->data; i < resources->size; ++xlat, ++i) {
85 if (!xlat->str)
86 continue;
87
88 unsigned long res = 0xfacefeed00000000ULL | xlat->val;
89 rc = syscall(__NR_prlimit64, pid, res, 0, rlimit);
90 pidns_print_leader();
91 if (!RETVAL_INJECTED && (rc < 0)) {
92 printf("prlimit64(%d%s, %s, NULL, %p) = %s\n",
93 (unsigned) pid, pid_str,
94 xlat->str, rlimit,
95 sprintrc(rc));
96 } else {
97 printf("prlimit64(%d%s, %s, NULL"
98 ", {rlim_cur=%s, rlim_max=%s})"
99 " = %d" INJ_STR "\n",
100 (unsigned) pid, pid_str,
101 xlat->str,
102 sprint_rlim(rlimit[0]),
103 sprint_rlim(rlimit[1]),
104 RETVAL_INJECTED ? INJECT_RETVAL : 0);
105 }
106 }
107
108 pidns_print_leader();
109 puts("+++ exited with 0 +++");
110 return 0;
111 }