1 /*
2 * Check decoding of quotactl xfs subcommands.
3 *
4 * Copyright (c) 2016 Eugene Syromyatnikov <evgsyr@gmail.com>
5 * Copyright (c) 2016 Dmitry V. Levin <ldv@strace.io>
6 * Copyright (c) 2016-2021 The strace developers.
7 * All rights reserved.
8 *
9 * SPDX-License-Identifier: GPL-2.0-or-later
10 */
11
12 #include "tests.h"
13 #include "scno.h"
14
15 #include <stdio.h>
16 #include <string.h>
17 #include <unistd.h>
18
19 #include <linux/dqblk_xfs.h>
20
21 #include "quotactl.h"
22
23 #include "xlat.h"
24 #include "xlat/xfs_dqblk_flags.h"
25 #if VERBOSE
26 # include "xlat/xfs_quota_flags.h"
27 #endif
28
29
30 static void
31 print_xdisk_quota(int rc, void *ptr, void *arg)
32 {
33 struct fs_disk_quota *dq = ptr;
34 long out_arg = (long) arg;
35
36 if (((rc < 0) && out_arg) || (out_arg > 1)) {
37 printf("%p", dq);
38 return;
39 }
40
41 printf("{");
42 PRINT_FIELD_D(*dq, d_version);
43 printf(", d_flags=");
44 printflags(xfs_dqblk_flags, (uint8_t) dq->d_flags, "FS_???_QUOTA");
45
46 printf(", ");
47 PRINT_FIELD_X(*dq, d_fieldmask);
48 printf(", ");
49 PRINT_FIELD_U(*dq, d_id);
50 printf(", ");
51 PRINT_FIELD_U(*dq, d_blk_hardlimit);
52 printf(", ");
53 PRINT_FIELD_U(*dq, d_blk_softlimit);
54 printf(", ");
55 PRINT_FIELD_U(*dq, d_ino_hardlimit);
56 printf(", ");
57 PRINT_FIELD_U(*dq, d_ino_softlimit);
58 printf(", ");
59 PRINT_FIELD_U(*dq, d_bcount);
60 printf(", ");
61 PRINT_FIELD_U(*dq, d_icount);
62
63 #if VERBOSE
64 printf(", ");
65 PRINT_FIELD_D(*dq, d_itimer);
66 printf(", ");
67 PRINT_FIELD_D(*dq, d_btimer);
68 printf(", ");
69 PRINT_FIELD_U(*dq, d_iwarns);
70 printf(", ");
71 PRINT_FIELD_U(*dq, d_bwarns);
72 printf(", ");
73 PRINT_FIELD_U(*dq, d_rtb_hardlimit);
74 printf(", ");
75 PRINT_FIELD_U(*dq, d_rtb_softlimit);
76 printf(", ");
77 PRINT_FIELD_U(*dq, d_rtbcount);
78 printf(", ");
79 PRINT_FIELD_D(*dq, d_rtbtimer);
80 printf(", ");
81 PRINT_FIELD_U(*dq, d_rtbwarns);
82 #else
83 printf(", ...");
84 #endif /* !VERBOSE */
85 printf("}");
86 }
87
88 static void
89 print_xquota_stat(int rc, void *ptr, void *arg)
90 {
91 struct fs_quota_stat *qs = ptr;
92 long out_arg = (long) arg;
93
94 if (((rc < 0) && out_arg) || (out_arg > 1)) {
95 printf("%p", qs);
96 return;
97 }
98
99 printf("{");
100 PRINT_FIELD_D(*qs, qs_version);
101
102 #if VERBOSE
103 printf(", qs_flags=");
104 printflags(xfs_quota_flags, qs->qs_flags, "FS_QUOTA_???");
105 printf(", qs_uquota={");
106 PRINT_FIELD_U(qs->qs_uquota, qfs_ino);
107 printf(", ");
108 PRINT_FIELD_U(qs->qs_uquota, qfs_nblks);
109 printf(", ");
110 PRINT_FIELD_U(qs->qs_uquota, qfs_nextents);
111 printf("}, qs_gquota={");
112 PRINT_FIELD_U(qs->qs_gquota, qfs_ino);
113 printf(", ");
114 PRINT_FIELD_U(qs->qs_gquota, qfs_nblks);
115 printf(", ");
116 PRINT_FIELD_U(qs->qs_gquota, qfs_nextents);
117 printf("}, ");
118 PRINT_FIELD_U(*qs, qs_incoredqs);
119 printf(", ");
120 PRINT_FIELD_D(*qs, qs_btimelimit);
121 printf(", ");
122 PRINT_FIELD_D(*qs, qs_itimelimit);
123 printf(", ");
124 PRINT_FIELD_D(*qs, qs_rtbtimelimit);
125 printf(", ");
126 PRINT_FIELD_U(*qs, qs_bwarnlimit);
127 printf(", ");
128 PRINT_FIELD_U(*qs, qs_iwarnlimit);
129 #else
130 printf(", ...");
131 #endif /* !VERBOSE */
132 printf("}");
133 }
134
135 static void
136 print_xquota_statv(int rc, void *ptr, void *arg)
137 {
138 struct fs_quota_statv *qs = ptr;
139 long out_arg = (long) arg;
140
141 if (((rc < 0) && out_arg) || (out_arg > 1)) {
142 printf("%p", qs);
143 return;
144 }
145
146 printf("{");
147 PRINT_FIELD_D(*qs, qs_version);
148
149 #if VERBOSE
150 printf(", qs_flags=");
151 printflags(xfs_quota_flags, qs->qs_flags, "FS_QUOTA_???");
152 printf(", ");
153 PRINT_FIELD_U(*qs, qs_incoredqs);
154 printf(", qs_uquota={");
155 PRINT_FIELD_U(qs->qs_uquota, qfs_ino);
156 printf(", ");
157 PRINT_FIELD_U(qs->qs_uquota, qfs_nblks);
158 printf(", ");
159 PRINT_FIELD_U(qs->qs_uquota, qfs_nextents);
160 printf("}, qs_gquota={");
161 PRINT_FIELD_U(qs->qs_gquota, qfs_ino);
162 printf(", ");
163 PRINT_FIELD_U(qs->qs_gquota, qfs_nblks);
164 printf(", ");
165 PRINT_FIELD_U(qs->qs_gquota, qfs_nextents);
166 printf("}, qs_pquota={");
167 PRINT_FIELD_U(qs->qs_pquota, qfs_ino);
168 printf(", ");
169 PRINT_FIELD_U(qs->qs_pquota, qfs_nblks);
170 printf(", ");
171 PRINT_FIELD_U(qs->qs_pquota, qfs_nextents);
172 printf("}, ");
173 PRINT_FIELD_D(*qs, qs_btimelimit);
174 printf(", ");
175 PRINT_FIELD_D(*qs, qs_itimelimit);
176 printf(", ");
177 PRINT_FIELD_D(*qs, qs_rtbtimelimit);
178 printf(", ");
179 PRINT_FIELD_U(*qs, qs_bwarnlimit);
180 printf(", ");
181 PRINT_FIELD_U(*qs, qs_iwarnlimit);
182 #else
183 printf(", ...");
184 #endif /* !VERBOSE */
185 printf("}");
186 }
187
188 int
189 main(void)
190 {
191 char *bogus_special = (char *) tail_alloc(1) + 1;
192 void *bogus_addr = (char *) tail_alloc(1) + 1;
193
194 char bogus_special_str[sizeof(void *) * 2 + sizeof("0x")];
195 char bogus_addr_str[sizeof(void *) * 2 + sizeof("0x")];
196 char unterminated_str[sizeof(void *) * 2 + sizeof("0x")];
197
198 static char invalid_cmd_str[1024];
199 TAIL_ALLOC_OBJECT_CONST_PTR(struct fs_disk_quota, xdq);
200 TAIL_ALLOC_OBJECT_CONST_PTR(struct fs_quota_stat, xqstat);
201 TAIL_ALLOC_OBJECT_CONST_PTR(struct fs_quota_statv, xqstatv);
202 TAIL_ALLOC_OBJECT_CONST_PTR(uint32_t, flags);
203 char *unterminated = tail_memdup(unterminated_data,
204 sizeof(unterminated_data));
205
206 snprintf(bogus_special_str, sizeof(bogus_special_str), "%p",
207 bogus_special);
208 snprintf(bogus_addr_str, sizeof(bogus_addr_str), "%p",
209 bogus_addr);
210 snprintf(unterminated_str, sizeof(unterminated_str), "%p",
211 unterminated);
212
213
214 /* Q_XQUOTAON */
215
216 *flags = 0xdeadbeef;
217
218 check_quota(CQF_ID_SKIP | CQF_ADDR_STR,
219 ARG_STR(QCMD(Q_XQUOTAON, USRQUOTA)),
220 ARG_STR("/dev/bogus/"), flags,
221 "[FS_QUOTA_UDQ_ACCT|FS_QUOTA_UDQ_ENFD"
222 "|FS_QUOTA_GDQ_ACCT|FS_QUOTA_GDQ_ENFD"
223 "|FS_QUOTA_PDQ_ENFD|0xdeadbec0]");
224
225 snprintf(invalid_cmd_str, sizeof(invalid_cmd_str),
226 "QCMD(Q_XQUOTAON, %#x /* ???QUOTA */)",
227 QCMD_TYPE(QCMD(Q_XQUOTAON, 0xfacefeed)));
228 check_quota(CQF_ID_SKIP,
229 QCMD(Q_XQUOTAON, 0xfacefeed), invalid_cmd_str,
230 bogus_dev, bogus_dev_str, bogus_addr);
231
232
233 /* Q_XQUOTAOFF */
234
235 check_quota(CQF_ID_SKIP | CQF_ADDR_STR,
236 ARG_STR(QCMD(Q_XQUOTAOFF, USRQUOTA)),
237 bogus_special, bogus_special_str,
238 bogus_addr, bogus_addr_str);
239 check_quota(CQF_ID_SKIP | CQF_ADDR_STR,
240 ARG_STR(QCMD(Q_XQUOTAOFF, GRPQUOTA)),
241 ARG_STR("/dev/bogus/"),
242 ARG_STR(NULL));
243 check_quota(CQF_ID_SKIP | CQF_ADDR_STR,
244 QCMD(Q_XQUOTAOFF, 3),
245 "QCMD(Q_XQUOTAOFF, 0x3 /* ???QUOTA */)",
246 ARG_STR("/dev/bogus/"), flags,
247 "[FS_QUOTA_UDQ_ACCT|FS_QUOTA_UDQ_ENFD"
248 "|FS_QUOTA_GDQ_ACCT|FS_QUOTA_GDQ_ENFD"
249 "|FS_QUOTA_PDQ_ENFD|0xdeadbec0]");
250
251
252 /* Q_XGETQUOTA */
253
254 /* Trying our best to get successful result */
255 check_quota(CQF_ADDR_CB, ARG_STR(QCMD(Q_XGETQUOTA, USRQUOTA)),
256 ARG_STR("/dev/sda1"), getuid(), xdq, print_xdisk_quota,
257 (intptr_t) 1);
258
259 check_quota(CQF_ADDR_CB, ARG_STR(QCMD(Q_XGETQUOTA, GRPQUOTA)),
260 ARG_STR(NULL), -1, xdq, print_xdisk_quota, (intptr_t) 1);
261
262
263 /* Q_XGETNEXTQUOTA */
264
265 check_quota(CQF_ADDR_CB, ARG_STR(QCMD(Q_XGETNEXTQUOTA, USRQUOTA)),
266 ARG_STR("/dev/sda1"), 0, xdq, print_xdisk_quota,
267 (intptr_t) 1);
268
269
270 /* Q_XSETQLIM */
271
272 check_quota(CQF_NONE, ARG_STR(QCMD(Q_XSETQLIM, PRJQUOTA)),
273 bogus_special, bogus_special_str, 0, bogus_addr);
274
275 fill_memory_ex(xdq, sizeof(*xdq), 0x8e, 0x80);
276
277 check_quota(CQF_ADDR_CB, ARG_STR(QCMD(Q_XSETQLIM, PRJQUOTA)),
278 bogus_dev, bogus_dev_str, 3141592653U,
279 xdq, print_xdisk_quota, (intptr_t) 0);
280
281
282 /* Q_XGETQSTAT */
283
284 check_quota(CQF_ID_SKIP | CQF_ADDR_CB,
285 ARG_STR(QCMD(Q_XGETQSTAT, USRQUOTA)),
286 ARG_STR("/dev/sda1"), xqstat, print_xquota_stat, (intptr_t) 1);
287
288 check_quota(CQF_ID_SKIP | CQF_ADDR_CB,
289 ARG_STR(QCMD(Q_XGETQSTAT, USRQUOTA)),
290 ARG_STR("NULL"), xqstat, print_xquota_stat, (intptr_t) 1);
291
292 check_quota(CQF_ID_SKIP,
293 ARG_STR(QCMD(Q_XGETQSTAT, PRJQUOTA)),
294 unterminated, unterminated_str,
295 xqstat + 1);
296
297
298 /* Q_XGETQSTATV */
299
300 check_quota(CQF_ID_SKIP | CQF_ADDR_CB,
301 ARG_STR(QCMD(Q_XGETQSTATV, USRQUOTA)),
302 ARG_STR("/dev/sda1"), xqstatv, print_xquota_statv, (intptr_t) 1);
303
304 check_quota(CQF_ID_SKIP | CQF_ADDR_CB,
305 ARG_STR(QCMD(Q_XGETQSTATV, GRPQUOTA)),
306 ARG_STR(NULL), xqstatv, print_xquota_statv, (intptr_t) 1);
307
308 check_quota(CQF_ID_SKIP,
309 ARG_STR(QCMD(Q_XGETQSTATV, PRJQUOTA)),
310 unterminated, unterminated_str,
311 xqstatv + 1);
312
313
314 /* Q_XQUOTARM */
315
316 check_quota(CQF_ID_SKIP | CQF_ADDR_STR,
317 ARG_STR(QCMD(Q_XQUOTARM, PRJQUOTA)),
318 bogus_special, bogus_special_str, ARG_STR(NULL));
319 check_quota(CQF_ID_SKIP,
320 ARG_STR(QCMD(Q_XQUOTARM, USRQUOTA)),
321 unterminated, unterminated_str, flags + 1);
322
323 *flags = 0xdeadbeef;
324 check_quota(CQF_ID_SKIP | CQF_ADDR_STR,
325 ARG_STR(QCMD(Q_XQUOTARM, GRPQUOTA)),
326 ARG_STR(NULL), flags,
327 "[FS_USER_QUOTA|FS_PROJ_QUOTA"
328 "|FS_GROUP_QUOTA|0xdeadbee8]");
329
330
331 /* Q_XQUOTASYNC */
332
333 check_quota(CQF_ID_SKIP | CQF_ADDR_SKIP,
334 ARG_STR(QCMD(Q_XQUOTASYNC, USRQUOTA)),
335 bogus_special, bogus_special_str);
336 check_quota(CQF_ID_SKIP | CQF_ADDR_SKIP,
337 QCMD(Q_XQUOTASYNC, 0xfff),
338 "QCMD(Q_XQUOTASYNC, 0xff /* ???QUOTA */)",
339 ARG_STR(NULL));
340
341 puts("+++ exited with 0 +++");
342
343 return 0;
344 }