Home | History | Annotate | Download | only in tests-m32
      1 /*
      2  * Check decoding of quotactl xfs subcommands.
      3  *
      4  * Copyright (c) 2016 Eugene Syromyatnikov <evgsyr (at) gmail.com>
      5  * Copyright (c) 2016 Dmitry V. Levin <ldv (at) altlinux.org>
      6  * Copyright (c) 2016-2017 The strace developers.
      7  * All rights reserved.
      8  *
      9  * Redistribution and use in source and binary forms, with or without
     10  * modification, are permitted provided that the following conditions
     11  * are met:
     12  * 1. Redistributions of source code must retain the above copyright
     13  *    notice, this list of conditions and the following disclaimer.
     14  * 2. Redistributions in binary form must reproduce the above copyright
     15  *    notice, this list of conditions and the following disclaimer in the
     16  *    documentation and/or other materials provided with the distribution.
     17  * 3. The name of the author may not be used to endorse or promote products
     18  *    derived from this software without specific prior written permission.
     19  *
     20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include "tests.h"
     33 
     34 #include <asm/unistd.h>
     35 
     36 #if defined(__NR_quotactl) && \
     37 	(defined(HAVE_LINUX_QUOTA_H) || defined(HAVE_SYS_QUOTA_H)) && \
     38 	defined(HAVE_LINUX_DQBLK_XFS_H)
     39 
     40 # include <stdio.h>
     41 # include <string.h>
     42 # include <unistd.h>
     43 
     44 # include <linux/dqblk_xfs.h>
     45 
     46 # include "quotactl.h"
     47 
     48 # ifndef Q_GETNEXTQUOTA
     49 #  define Q_XGETNEXTQUOTA	XQM_CMD(0x9)
     50 # endif /* !Q_GETNEXTQUOTA */
     51 
     52 # ifndef Q_XGETQSTATV
     53 
     54 #  define Q_XGETQSTATV		XQM_CMD(8)
     55 #  define FS_QSTATV_VERSION1	1
     56 
     57 struct fs_qfilestatv {
     58 	uint64_t	qfs_ino;	/* inode number */
     59 	uint64_t	qfs_nblks;	/* number of BBs 512-byte-blks */
     60 	uint32_t	qfs_nextents;	/* number of extents */
     61 	uint32_t	qfs_pad;	/* pad for 8-byte alignment */
     62 };
     63 
     64 struct fs_quota_statv {
     65 	int8_t		qs_version;		/* version for future changes */
     66 	uint8_t		qs_pad1;		/* pad for 16bit alignment */
     67 	uint16_t	qs_flags;		/* XFS_QUOTA_.* flags */
     68 	uint32_t	qs_incoredqs;		/* number of dquots incore */
     69 	struct fs_qfilestatv	qs_uquota;	/* user quota information */
     70 	struct fs_qfilestatv	qs_gquota;	/* group quota information */
     71 	struct fs_qfilestatv	qs_pquota;	/* project quota information */
     72 	int32_t		qs_btimelimit;		/* limit for blks timer */
     73 	int32_t		qs_itimelimit;		/* limit for inodes timer */
     74 	int32_t		qs_rtbtimelimit;	/* limit for rt blks timer */
     75 	uint16_t	qs_bwarnlimit;		/* limit for num warnings */
     76 	uint16_t	qs_iwarnlimit;		/* limit for num warnings */
     77 	uint64_t	qs_pad2[8];		/* for future proofing */
     78 };
     79 
     80 # endif /* !Q_XGETQSTATV */
     81 
     82 # include "xlat.h"
     83 # include "xlat/xfs_dqblk_flags.h"
     84 # if VERBOSE
     85 #  include "xlat/xfs_quota_flags.h"
     86 # endif
     87 
     88 
     89 void
     90 print_xdisk_quota(int rc, void *ptr, void *arg)
     91 {
     92 	struct fs_disk_quota *dq = ptr;
     93 	long out_arg = (long) arg;
     94 
     95 	if (((rc != 0) && out_arg) || (out_arg > 1)) {
     96 		printf("%p", dq);
     97 		return;
     98 	}
     99 
    100 	PRINT_FIELD_D("{", *dq, d_version);
    101 	printf(", d_flags=");
    102 	printflags(xfs_dqblk_flags, (uint8_t) dq->d_flags, "XFS_???_QUOTA");
    103 
    104 	PRINT_FIELD_X(", ", *dq, d_fieldmask);
    105 	PRINT_FIELD_U(", ", *dq, d_id);
    106 	PRINT_FIELD_U(", ", *dq, d_blk_hardlimit);
    107 	PRINT_FIELD_U(", ", *dq, d_blk_softlimit);
    108 	PRINT_FIELD_U(", ", *dq, d_ino_hardlimit);
    109 	PRINT_FIELD_U(", ", *dq, d_ino_softlimit);
    110 	PRINT_FIELD_U(", ", *dq, d_bcount);
    111 	PRINT_FIELD_U(", ", *dq, d_icount);
    112 
    113 # if VERBOSE
    114 	PRINT_FIELD_D(", ", *dq, d_itimer);
    115 	PRINT_FIELD_D(", ", *dq, d_btimer);
    116 	PRINT_FIELD_U(", ", *dq, d_iwarns);
    117 	PRINT_FIELD_U(", ", *dq, d_bwarns);
    118 	PRINT_FIELD_U(", ", *dq, d_rtb_hardlimit);
    119 	PRINT_FIELD_U(", ", *dq, d_rtb_softlimit);
    120 	PRINT_FIELD_U(", ", *dq, d_rtbcount);
    121 	PRINT_FIELD_D(", ", *dq, d_rtbtimer);
    122 	PRINT_FIELD_U(", ", *dq, d_rtbwarns);
    123 # else
    124 	printf(", ...");
    125 # endif /* !VERBOSE */
    126 	printf("}");
    127 }
    128 
    129 void
    130 print_xquota_stat(int rc, void *ptr, void *arg)
    131 {
    132 	struct fs_quota_stat *qs = ptr;
    133 	long out_arg = (long) arg;
    134 
    135 	if (((rc != 0) && out_arg) || (out_arg > 1)) {
    136 		printf("%p", qs);
    137 		return;
    138 	}
    139 
    140 	PRINT_FIELD_D("{", *qs, qs_version);
    141 
    142 # if VERBOSE
    143 	printf(", qs_flags=");
    144 	printflags(xfs_quota_flags, qs->qs_flags, "XFS_QUOTA_???");
    145 	PRINT_FIELD_U(", qs_uquota={", qs->qs_uquota, qfs_ino);
    146 	PRINT_FIELD_U(", ", qs->qs_uquota, qfs_nblks);
    147 	PRINT_FIELD_U(", ", qs->qs_uquota, qfs_nextents);
    148 	PRINT_FIELD_U("}, qs_gquota={", qs->qs_gquota, qfs_ino);
    149 	PRINT_FIELD_U(", ", qs->qs_gquota, qfs_nblks);
    150 	PRINT_FIELD_U(", ", qs->qs_gquota, qfs_nextents);
    151 	PRINT_FIELD_U("}, ", *qs, qs_incoredqs);
    152 	PRINT_FIELD_D(", ", *qs, qs_btimelimit);
    153 	PRINT_FIELD_D(", ", *qs, qs_itimelimit);
    154 	PRINT_FIELD_D(", ", *qs, qs_rtbtimelimit);
    155 	PRINT_FIELD_U(", ", *qs, qs_bwarnlimit);
    156 	PRINT_FIELD_U(", ", *qs, qs_iwarnlimit);
    157 # else
    158 	printf(", ...");
    159 # endif /* !VERBOSE */
    160 	printf("}");
    161 }
    162 
    163 void
    164 print_xquota_statv(int rc, void *ptr, void *arg)
    165 {
    166 	struct fs_quota_statv *qs = ptr;
    167 	long out_arg = (long) arg;
    168 
    169 	if (((rc != 0) && out_arg) || (out_arg > 1)) {
    170 		printf("%p", qs);
    171 		return;
    172 	}
    173 
    174 	PRINT_FIELD_D("{", *qs, qs_version);
    175 
    176 # if VERBOSE
    177 	printf(", qs_flags=");
    178 	printflags(xfs_quota_flags, qs->qs_flags, "XFS_QUOTA_???");
    179 	PRINT_FIELD_U(", ", *qs, qs_incoredqs);
    180 	PRINT_FIELD_U(", qs_uquota={", qs->qs_uquota, qfs_ino);
    181 	PRINT_FIELD_U(", ", qs->qs_uquota, qfs_nblks);
    182 	PRINT_FIELD_U(", ", qs->qs_uquota, qfs_nextents);
    183 	PRINT_FIELD_U("}, qs_gquota={", qs->qs_gquota, qfs_ino);
    184 	PRINT_FIELD_U(", ", qs->qs_gquota, qfs_nblks);
    185 	PRINT_FIELD_U(", ", qs->qs_gquota, qfs_nextents);
    186 	PRINT_FIELD_U("}, qs_pquota={", qs->qs_pquota, qfs_ino);
    187 	PRINT_FIELD_U(", ", qs->qs_pquota, qfs_nblks);
    188 	PRINT_FIELD_U(", ", qs->qs_pquota, qfs_nextents);
    189 	PRINT_FIELD_D("}, ", *qs, qs_btimelimit);
    190 	PRINT_FIELD_D(", ", *qs, qs_itimelimit);
    191 	PRINT_FIELD_D(", ", *qs, qs_rtbtimelimit);
    192 	PRINT_FIELD_U(", ", *qs, qs_bwarnlimit);
    193 	PRINT_FIELD_U(", ", *qs, qs_iwarnlimit);
    194 # else
    195 	printf(", ...");
    196 # endif /* !VERBOSE */
    197 	printf("}");
    198 }
    199 
    200 int
    201 main(void)
    202 {
    203 	char *bogus_special = (char *) tail_alloc(1) + 1;
    204 	void *bogus_addr = (char *) tail_alloc(1) + 1;
    205 
    206 	char bogus_special_str[sizeof(void *) * 2 + sizeof("0x")];
    207 	char bogus_addr_str[sizeof(void *) * 2 + sizeof("0x")];
    208 	char unterminated_str[sizeof(void *) * 2 + sizeof("0x")];
    209 
    210 	long rc;
    211 	TAIL_ALLOC_OBJECT_CONST_PTR(struct fs_disk_quota, xdq);
    212 	TAIL_ALLOC_OBJECT_CONST_PTR(struct fs_quota_stat, xqstat);
    213 	TAIL_ALLOC_OBJECT_CONST_PTR(struct fs_quota_statv, xqstatv);
    214 	TAIL_ALLOC_OBJECT_CONST_PTR(uint32_t, flags);
    215 	char *unterminated = tail_memdup(unterminated_data,
    216 		sizeof(unterminated_data));
    217 
    218 	snprintf(bogus_special_str, sizeof(bogus_special_str), "%p",
    219 		 bogus_special);
    220 	snprintf(bogus_addr_str, sizeof(bogus_addr_str), "%p",
    221 		 bogus_addr);
    222 	snprintf(unterminated_str, sizeof(unterminated_str), "%p",
    223 		 unterminated);
    224 
    225 
    226 	/* Q_XQUOTAON */
    227 
    228 	*flags = 0xdeadbeef;
    229 
    230 	check_quota(CQF_ID_SKIP | CQF_ADDR_STR,
    231 		    ARG_STR(QCMD(Q_XQUOTAON, USRQUOTA)),
    232 		    ARG_STR("/dev/bogus/"), flags,
    233 		    "[XFS_QUOTA_UDQ_ACCT|XFS_QUOTA_UDQ_ENFD"
    234 		    "|XFS_QUOTA_GDQ_ACCT|XFS_QUOTA_GDQ_ENFD"
    235 		    "|XFS_QUOTA_PDQ_ENFD|0xdeadbec0]");
    236 
    237 	rc = syscall(__NR_quotactl, QCMD(Q_XQUOTAON, 0xfacefeed), bogus_dev,
    238 		     bogus_id, bogus_addr);
    239 	printf("quotactl(QCMD(Q_XQUOTAON, %#x /* ???QUOTA */)"
    240 	       ", %s, %p) = %s\n",
    241 	       QCMD_TYPE(QCMD(Q_XQUOTAON, 0xfacefeed)),
    242 	       bogus_dev_str, bogus_addr, sprintrc(rc));
    243 
    244 
    245 	/* Q_XQUOTAOFF */
    246 
    247 	check_quota(CQF_ID_SKIP | CQF_ADDR_STR,
    248 		    ARG_STR(QCMD(Q_XQUOTAOFF, USRQUOTA)),
    249 		    bogus_special, bogus_special_str,
    250 		    bogus_addr, bogus_addr_str);
    251 	check_quota(CQF_ID_SKIP | CQF_ADDR_STR,
    252 		    ARG_STR(QCMD(Q_XQUOTAOFF, GRPQUOTA)),
    253 		    ARG_STR("/dev/bogus/"),
    254 		    ARG_STR(NULL));
    255 	check_quota(CQF_ID_SKIP | CQF_ADDR_STR,
    256 		    QCMD(Q_XQUOTAOFF, 3),
    257 		    "QCMD(Q_XQUOTAOFF, 0x3 /* ???QUOTA */)",
    258 		    ARG_STR("/dev/bogus/"), flags,
    259 		    "[XFS_QUOTA_UDQ_ACCT|XFS_QUOTA_UDQ_ENFD"
    260 		    "|XFS_QUOTA_GDQ_ACCT|XFS_QUOTA_GDQ_ENFD"
    261 		    "|XFS_QUOTA_PDQ_ENFD|0xdeadbec0]");
    262 
    263 
    264 	/* Q_XGETQUOTA */
    265 
    266 	/* Trying our best to get successful result */
    267 	check_quota(CQF_ADDR_CB, ARG_STR(QCMD(Q_GETQUOTA, USRQUOTA)),
    268 		    ARG_STR("/dev/sda1"), getuid(), xdq, print_xdisk_quota,
    269 		    (intptr_t) 1);
    270 
    271 	check_quota(CQF_ADDR_CB, ARG_STR(QCMD(Q_GETQUOTA, GRPQUOTA)),
    272 		    ARG_STR(NULL), -1, xdq, print_xdisk_quota, (intptr_t) 2);
    273 
    274 
    275 	/* Q_XGETNEXTQUOTA */
    276 
    277 	check_quota(CQF_ADDR_CB, ARG_STR(QCMD(Q_XGETNEXTQUOTA, USRQUOTA)),
    278 		    ARG_STR("/dev/sda1"), 0, xdq, print_xdisk_quota,
    279 		    (intptr_t) 1);
    280 
    281 
    282 	/* Q_XSETQLIM */
    283 
    284 	check_quota(CQF_NONE, ARG_STR(QCMD(Q_XSETQLIM, PRJQUOTA)),
    285 		    bogus_special, bogus_special_str, 0, bogus_addr);
    286 
    287 	fill_memory_ex(xdq, sizeof(*xdq), 0x8e, 0x80);
    288 
    289 	check_quota(CQF_ADDR_CB, ARG_STR(QCMD(Q_XSETQLIM, PRJQUOTA)),
    290 		    bogus_dev, bogus_dev_str, 3141592653U,
    291 		    xdq, print_xdisk_quota, (intptr_t) 0);
    292 
    293 
    294 	/* Q_XGETQSTAT */
    295 
    296 	check_quota(CQF_ID_SKIP | CQF_ADDR_CB,
    297 		    ARG_STR(QCMD(Q_XGETQSTAT, USRQUOTA)),
    298 		    ARG_STR("/dev/sda1"), xqstat, print_xquota_stat, (intptr_t) 1);
    299 
    300 	check_quota(CQF_ID_SKIP | CQF_ADDR_CB,
    301 		    ARG_STR(QCMD(Q_XGETQSTATV, PRJQUOTA)),
    302 		    unterminated, unterminated_str,
    303 		    xqstat + 1, print_xquota_stat, (intptr_t) 2);
    304 
    305 
    306 	/* Q_XGETQSTATV */
    307 
    308 	check_quota(CQF_ID_SKIP | CQF_ADDR_CB,
    309 		    ARG_STR(QCMD(Q_XGETQSTAT, USRQUOTA)),
    310 		    ARG_STR("/dev/sda1"), xqstatv, print_xquota_statv, 1);
    311 
    312 	check_quota(CQF_ID_SKIP | CQF_ADDR_CB,
    313 		    ARG_STR(QCMD(Q_XGETQSTATV, GRPQUOTA)),
    314 		    ARG_STR(NULL), xqstatv, print_xquota_statv, (intptr_t) 2);
    315 
    316 
    317 	/* Q_XQUOTARM */
    318 
    319 	check_quota(CQF_ID_SKIP | CQF_ADDR_STR,
    320 		    ARG_STR(QCMD(Q_XQUOTARM, PRJQUOTA)),
    321 		    bogus_special, bogus_special_str, ARG_STR(NULL));
    322 	check_quota(CQF_ID_SKIP,
    323 		    ARG_STR(QCMD(Q_XQUOTARM, USRQUOTA)),
    324 		    unterminated, unterminated_str, flags + 1);
    325 
    326 	*flags = 0xdeadbeef;
    327 	check_quota(CQF_ID_SKIP | CQF_ADDR_STR,
    328 		    ARG_STR(QCMD(Q_XQUOTARM, GRPQUOTA)),
    329 		    ARG_STR(NULL), flags,
    330 		    "[XFS_USER_QUOTA|XFS_PROJ_QUOTA"
    331 		    "|XFS_GROUP_QUOTA|0xdeadbee8]");
    332 
    333 
    334 	/* Q_XQUOTASYNC */
    335 
    336 	check_quota(CQF_ID_SKIP | CQF_ADDR_SKIP,
    337 		    ARG_STR(QCMD(Q_XQUOTASYNC, USRQUOTA)),
    338 		    bogus_special, bogus_special_str);
    339 	check_quota(CQF_ID_SKIP | CQF_ADDR_SKIP,
    340 		    QCMD(Q_XQUOTASYNC, 0xfff),
    341 		    "QCMD(Q_XQUOTASYNC, 0xff /* ???QUOTA */)",
    342 		    ARG_STR(NULL));
    343 
    344 	puts("+++ exited with 0 +++");
    345 
    346 	return 0;
    347 }
    348 
    349 #else
    350 
    351 SKIP_MAIN_UNDEFINED("__NR_quotactl && "
    352 	"(HAVE_LINUX_QUOTA_H || HAVE_SYS_QUOTA_H) && "
    353 	"HAVE_LINUX_DQBLK_XFS_H");
    354 
    355 #endif
    356