(root)/
strace-6.5/
src/
quota.c
       1  /*
       2   * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
       3   * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
       4   * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
       5   * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
       6   * Copyright (c) 2005-2016 Dmitry V. Levin <ldv@strace.io>
       7   * Copyright (c) 2006-2021 The strace developers.
       8   * All rights reserved.
       9   *
      10   * SPDX-License-Identifier: LGPL-2.1-or-later
      11   */
      12  
      13  #include "defs.h"
      14  #include <linux/dqblk_xfs.h>
      15  
      16  #define SUBCMDMASK  0x00ff
      17  #define SUBCMDSHIFT 8
      18  #define QCMD_CMD(cmd)	((uint32_t)(cmd) >> SUBCMDSHIFT)
      19  #define QCMD_TYPE(cmd)	((uint32_t)(cmd) & SUBCMDMASK)
      20  
      21  #define OLD_CMD(cmd)	((uint32_t)(cmd) << SUBCMDSHIFT)
      22  #define NEW_CMD(cmd)	((uint32_t)(cmd) | 0x800000)
      23  
      24  #include "xlat/quotacmds.h"
      25  #include "xlat/quotatypes.h"
      26  #include "xlat/quota_formats.h"
      27  #include "xlat/xfs_quota_flags.h"
      28  #include "xlat/xfs_dqblk_flags.h"
      29  #include "xlat/if_dqblk_valid.h"
      30  #include "xlat/if_dqinfo_flags.h"
      31  #include "xlat/if_dqinfo_valid.h"
      32  
      33  /*
      34   * We add attribute packed due to the fact that the structure is 8-byte aligned
      35   * on 64-bit systems and therefore has additional 4 bytes of padding, which
      36   * leads to problems when it is used on 32-bit tracee which does not have such
      37   * padding.
      38   */
      39  struct if_dqblk {
      40  	uint64_t dqb_bhardlimit;
      41  	uint64_t dqb_bsoftlimit;
      42  	uint64_t dqb_curspace;
      43  	uint64_t dqb_ihardlimit;
      44  	uint64_t dqb_isoftlimit;
      45  	uint64_t dqb_curinodes;
      46  	uint64_t dqb_btime;
      47  	uint64_t dqb_itime;
      48  	uint32_t dqb_valid;
      49  } ATTRIBUTE_PACKED;
      50  
      51  struct if_nextdqblk {
      52  	uint64_t dqb_bhardlimit;
      53  	uint64_t dqb_bsoftlimit;
      54  	uint64_t dqb_curspace;
      55  	uint64_t dqb_ihardlimit;
      56  	uint64_t dqb_isoftlimit;
      57  	uint64_t dqb_curinodes;
      58  	uint64_t dqb_btime;
      59  	uint64_t dqb_itime;
      60  	uint32_t dqb_valid;
      61  	uint32_t dqb_id;
      62  };
      63  
      64  struct if_dqinfo {
      65  	uint64_t dqi_bgrace;
      66  	uint64_t dqi_igrace;
      67  	uint32_t dqi_flags;
      68  	uint32_t dqi_valid;
      69  };
      70  
      71  static void
      72  print_fs_qfilestat(const struct fs_qfilestat *const p)
      73  {
      74  	tprint_struct_begin();
      75  	PRINT_FIELD_U(*p, qfs_ino);
      76  	tprint_struct_next();
      77  	PRINT_FIELD_U(*p, qfs_nblks);
      78  	tprint_struct_next();
      79  	PRINT_FIELD_U(*p, qfs_nextents);
      80  	tprint_struct_end();
      81  }
      82  
      83  static void
      84  print_fs_qfilestatv(const struct fs_qfilestatv *const p)
      85  {
      86  	tprint_struct_begin();
      87  	PRINT_FIELD_U(*p, qfs_ino);
      88  	tprint_struct_next();
      89  	PRINT_FIELD_U(*p, qfs_nblks);
      90  	tprint_struct_next();
      91  	PRINT_FIELD_U(*p, qfs_nextents);
      92  	tprint_struct_end();
      93  }
      94  
      95  static int
      96  decode_cmd_data(struct tcb *tcp, uint32_t id, uint32_t cmd, kernel_ulong_t data)
      97  {
      98  	switch (cmd) {
      99  	case Q_QUOTAOFF:
     100  	case Q_SYNC:
     101  	case Q_XQUOTASYNC:
     102  		break;
     103  	case Q_QUOTAON:
     104  		tprint_arg_next();
     105  		printxval(quota_formats, id, "QFMT_VFS_???");
     106  		tprint_arg_next();
     107  		printpath(tcp, data);
     108  		break;
     109  	case Q_GETQUOTA:
     110  		if (entering(tcp)) {
     111  			tprint_arg_next();
     112  			printuid(id);
     113  			tprint_arg_next();
     114  
     115  			return 0;
     116  		}
     117  
     118  		ATTRIBUTE_FALLTHROUGH;
     119  	case Q_SETQUOTA:
     120  	{
     121  		struct if_dqblk dq;
     122  
     123  		if (entering(tcp)) {
     124  			tprint_arg_next();
     125  			printuid(id);
     126  			tprint_arg_next();
     127  		}
     128  
     129  		if (umove_or_printaddr(tcp, data, &dq))
     130  			break;
     131  		tprint_struct_begin();
     132  		PRINT_FIELD_U(dq, dqb_bhardlimit);
     133  		tprint_struct_next();
     134  		PRINT_FIELD_U(dq, dqb_bsoftlimit);
     135  		tprint_struct_next();
     136  		PRINT_FIELD_U(dq, dqb_curspace);
     137  		tprint_struct_next();
     138  		PRINT_FIELD_U(dq, dqb_ihardlimit);
     139  		tprint_struct_next();
     140  		PRINT_FIELD_U(dq, dqb_isoftlimit);
     141  		tprint_struct_next();
     142  		PRINT_FIELD_U(dq, dqb_curinodes);
     143  		if (!abbrev(tcp)) {
     144  			tprint_struct_next();
     145  			PRINT_FIELD_U(dq, dqb_btime);
     146  			tprint_struct_next();
     147  			PRINT_FIELD_U(dq, dqb_itime);
     148  			tprint_struct_next();
     149  			PRINT_FIELD_FLAGS(dq, dqb_valid,
     150  					  if_dqblk_valid, "QIF_???");
     151  		} else {
     152  			tprint_struct_next();
     153  			tprint_more_data_follows();
     154  		}
     155  		tprint_struct_end();
     156  		break;
     157  	}
     158  	case Q_GETNEXTQUOTA:
     159  	{
     160  		struct if_nextdqblk dq;
     161  
     162  		if (entering(tcp)) {
     163  			tprint_arg_next();
     164  			printuid(id);
     165  			tprint_arg_next();
     166  
     167  			return 0;
     168  		}
     169  
     170  		if (umove_or_printaddr(tcp, data, &dq))
     171  			break;
     172  		tprint_struct_begin();
     173  		PRINT_FIELD_U(dq, dqb_bhardlimit);
     174  		tprint_struct_next();
     175  		PRINT_FIELD_U(dq, dqb_bsoftlimit);
     176  		tprint_struct_next();
     177  		PRINT_FIELD_U(dq, dqb_curspace);
     178  		tprint_struct_next();
     179  		PRINT_FIELD_U(dq, dqb_ihardlimit);
     180  		tprint_struct_next();
     181  		PRINT_FIELD_U(dq, dqb_isoftlimit);
     182  		tprint_struct_next();
     183  		PRINT_FIELD_U(dq, dqb_curinodes);
     184  		if (!abbrev(tcp)) {
     185  			tprint_struct_next();
     186  			PRINT_FIELD_U(dq, dqb_btime);
     187  			tprint_struct_next();
     188  			PRINT_FIELD_U(dq, dqb_itime);
     189  			tprint_struct_next();
     190  			PRINT_FIELD_FLAGS(dq, dqb_valid,
     191  					  if_dqblk_valid, "QIF_???");
     192  			tprint_struct_next();
     193  			PRINT_FIELD_U(dq, dqb_id);
     194  		} else {
     195  			tprint_struct_next();
     196  			PRINT_FIELD_U(dq, dqb_id);
     197  			tprint_struct_next();
     198  			tprint_more_data_follows();
     199  		}
     200  		tprint_struct_end();
     201  		break;
     202  	}
     203  	case Q_XGETQUOTA:
     204  	case Q_XGETNEXTQUOTA:
     205  		if (entering(tcp)) {
     206  			tprint_arg_next();
     207  			printuid(id);
     208  			tprint_arg_next();
     209  
     210  			return 0;
     211  		}
     212  
     213  		ATTRIBUTE_FALLTHROUGH;
     214  	case Q_XSETQLIM:
     215  	{
     216  		fs_disk_quota_t dq;
     217  
     218  		if (entering(tcp)) {
     219  			tprint_arg_next();
     220  			printuid(id);
     221  			tprint_arg_next();
     222  		}
     223  
     224  		if (umove_or_printaddr(tcp, data, &dq))
     225  			break;
     226  		tprint_struct_begin();
     227  		PRINT_FIELD_D(dq, d_version);
     228  		tprint_struct_next();
     229  		PRINT_FIELD_FLAGS(dq, d_flags,
     230  				  xfs_dqblk_flags, "FS_???_QUOTA");
     231  		tprint_struct_next();
     232  		PRINT_FIELD_X(dq, d_fieldmask);
     233  		tprint_struct_next();
     234  		PRINT_FIELD_U(dq, d_id);
     235  		tprint_struct_next();
     236  		PRINT_FIELD_U(dq, d_blk_hardlimit);
     237  		tprint_struct_next();
     238  		PRINT_FIELD_U(dq, d_blk_softlimit);
     239  		tprint_struct_next();
     240  		PRINT_FIELD_U(dq, d_ino_hardlimit);
     241  		tprint_struct_next();
     242  		PRINT_FIELD_U(dq, d_ino_softlimit);
     243  		tprint_struct_next();
     244  		PRINT_FIELD_U(dq, d_bcount);
     245  		tprint_struct_next();
     246  		PRINT_FIELD_U(dq, d_icount);
     247  		if (!abbrev(tcp)) {
     248  			tprint_struct_next();
     249  			PRINT_FIELD_D(dq, d_itimer);
     250  			tprint_struct_next();
     251  			PRINT_FIELD_D(dq, d_btimer);
     252  			tprint_struct_next();
     253  			PRINT_FIELD_U(dq, d_iwarns);
     254  			tprint_struct_next();
     255  			PRINT_FIELD_U(dq, d_bwarns);
     256  			tprint_struct_next();
     257  			PRINT_FIELD_U(dq, d_rtb_hardlimit);
     258  			tprint_struct_next();
     259  			PRINT_FIELD_U(dq, d_rtb_softlimit);
     260  			tprint_struct_next();
     261  			PRINT_FIELD_U(dq, d_rtbcount);
     262  			tprint_struct_next();
     263  			PRINT_FIELD_D(dq, d_rtbtimer);
     264  			tprint_struct_next();
     265  			PRINT_FIELD_U(dq, d_rtbwarns);
     266  		} else {
     267  			tprint_struct_next();
     268  			tprint_more_data_follows();
     269  		}
     270  		tprint_struct_end();
     271  		break;
     272  	}
     273  	case Q_GETFMT:
     274  	{
     275  		uint32_t fmt;
     276  
     277  		if (entering(tcp)) {
     278  			tprint_arg_next();
     279  
     280  			return 0;
     281  		}
     282  
     283  		if (umove_or_printaddr(tcp, data, &fmt))
     284  			break;
     285  		tprint_indirect_begin();
     286  		printxval(quota_formats, fmt, "QFMT_VFS_???");
     287  		tprint_indirect_end();
     288  		break;
     289  	}
     290  	case Q_GETINFO:
     291  		if (entering(tcp)) {
     292  			tprint_arg_next();
     293  
     294  			return 0;
     295  		}
     296  
     297  		ATTRIBUTE_FALLTHROUGH;
     298  	case Q_SETINFO:
     299  	{
     300  		struct if_dqinfo dq;
     301  
     302  		if (entering(tcp))
     303  			tprint_arg_next();
     304  
     305  		if (umove_or_printaddr(tcp, data, &dq))
     306  			break;
     307  		tprint_struct_begin();
     308  		PRINT_FIELD_U(dq, dqi_bgrace);
     309  		tprint_struct_next();
     310  		PRINT_FIELD_U(dq, dqi_igrace);
     311  		tprint_struct_next();
     312  		PRINT_FIELD_FLAGS(dq, dqi_flags, if_dqinfo_flags, "DQF_???");
     313  		tprint_struct_next();
     314  		PRINT_FIELD_FLAGS(dq, dqi_valid, if_dqinfo_valid, "IIF_???");
     315  		tprint_struct_end();
     316  		break;
     317  	}
     318  	case Q_XGETQSTAT:
     319  	{
     320  		fs_quota_stat_t dq;
     321  
     322  		if (entering(tcp)) {
     323  			tprint_arg_next();
     324  
     325  			return 0;
     326  		}
     327  		if (fetch_struct_quotastat(tcp, data, &dq)) {
     328  			tprint_struct_begin();
     329  			PRINT_FIELD_D(dq, qs_version);
     330  			if (!abbrev(tcp)) {
     331  				tprint_struct_next();
     332  				PRINT_FIELD_FLAGS(dq, qs_flags,
     333  						  xfs_quota_flags, "FS_QUOTA_???");
     334  				tprint_struct_next();
     335  				PRINT_FIELD_OBJ_PTR(dq, qs_uquota,
     336  						    print_fs_qfilestat);
     337  				tprint_struct_next();
     338  				PRINT_FIELD_OBJ_PTR(dq, qs_gquota,
     339  						    print_fs_qfilestat);
     340  				tprint_struct_next();
     341  				PRINT_FIELD_U(dq, qs_incoredqs);
     342  				tprint_struct_next();
     343  				PRINT_FIELD_D(dq, qs_btimelimit);
     344  				tprint_struct_next();
     345  				PRINT_FIELD_D(dq, qs_itimelimit);
     346  				tprint_struct_next();
     347  				PRINT_FIELD_D(dq, qs_rtbtimelimit);
     348  				tprint_struct_next();
     349  				PRINT_FIELD_U(dq, qs_bwarnlimit);
     350  				tprint_struct_next();
     351  				PRINT_FIELD_U(dq, qs_iwarnlimit);
     352  			} else {
     353  				tprint_struct_next();
     354  				tprint_more_data_follows();
     355  			}
     356  			tprint_struct_end();
     357  		}
     358  		break;
     359  	}
     360  	case Q_XGETQSTATV:
     361  	{
     362  		struct fs_quota_statv dq;
     363  
     364  		if (entering(tcp)) {
     365  			tprint_arg_next();
     366  
     367  			return 0;
     368  		}
     369  
     370  		if (umove_or_printaddr(tcp, data, &dq))
     371  			break;
     372  		tprint_struct_begin();
     373  		PRINT_FIELD_D(dq, qs_version);
     374  		if (!abbrev(tcp)) {
     375  			tprint_struct_next();
     376  			PRINT_FIELD_FLAGS(dq, qs_flags,
     377  					  xfs_quota_flags, "FS_QUOTA_???");
     378  			tprint_struct_next();
     379  			PRINT_FIELD_U(dq, qs_incoredqs);
     380  			tprint_struct_next();
     381  			PRINT_FIELD_OBJ_PTR(dq, qs_uquota,
     382  					    print_fs_qfilestatv);
     383  			tprint_struct_next();
     384  			PRINT_FIELD_OBJ_PTR(dq, qs_gquota,
     385  					    print_fs_qfilestatv);
     386  			tprint_struct_next();
     387  			PRINT_FIELD_OBJ_PTR(dq, qs_pquota,
     388  					    print_fs_qfilestatv);
     389  			tprint_struct_next();
     390  			PRINT_FIELD_D(dq, qs_btimelimit);
     391  			tprint_struct_next();
     392  			PRINT_FIELD_D(dq, qs_itimelimit);
     393  			tprint_struct_next();
     394  			PRINT_FIELD_D(dq, qs_rtbtimelimit);
     395  			tprint_struct_next();
     396  			PRINT_FIELD_U(dq, qs_bwarnlimit);
     397  			tprint_struct_next();
     398  			PRINT_FIELD_U(dq, qs_iwarnlimit);
     399  		} else {
     400  			tprint_struct_next();
     401  			tprint_more_data_follows();
     402  		}
     403  		tprint_struct_end();
     404  		break;
     405  	}
     406  	case Q_XQUOTAON:
     407  	case Q_XQUOTAOFF:
     408  	{
     409  		uint32_t flag;
     410  
     411  		tprint_arg_next();
     412  
     413  		if (umove_or_printaddr(tcp, data, &flag))
     414  			break;
     415  		tprint_indirect_begin();
     416  		printflags(xfs_quota_flags, flag, "FS_QUOTA_???");
     417  		tprint_indirect_end();
     418  		break;
     419  	}
     420  	case Q_XQUOTARM:
     421  	{
     422  		uint32_t flag;
     423  
     424  		tprint_arg_next();
     425  
     426  		if (umove_or_printaddr(tcp, data, &flag))
     427  			break;
     428  		tprint_indirect_begin();
     429  		printflags(xfs_dqblk_flags, flag, "FS_???_QUOTA");
     430  		tprint_indirect_end();
     431  		break;
     432  	}
     433  	default:
     434  		tprint_arg_next();
     435  		printuid(id);
     436  		tprint_arg_next();
     437  		printaddr(data);
     438  		break;
     439  	}
     440  	return RVAL_DECODED;
     441  }
     442  
     443  static void
     444  print_qcmd(const uint32_t qcmd)
     445  {
     446  	const uint32_t cmd = QCMD_CMD(qcmd);
     447  	const uint32_t type = QCMD_TYPE(qcmd);
     448  
     449  	if (xlat_verbose(xlat_verbosity) != XLAT_STYLE_ABBREV)
     450  		PRINT_VAL_U(qcmd);
     451  
     452  	if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_RAW)
     453  		return;
     454  
     455  	if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_VERBOSE)
     456  		tprint_comment_begin();
     457  
     458  	tprints_arg_begin("QCMD");
     459  	printxvals_ex(cmd, "Q_???", XLAT_STYLE_ABBREV, quotacmds, NULL);
     460  	tprint_arg_next();
     461  	printxvals_ex(type, "???QUOTA", XLAT_STYLE_ABBREV, quotatypes, NULL);
     462  	tprint_arg_end();
     463  
     464  	if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_VERBOSE)
     465  		tprint_comment_end();
     466  }
     467  
     468  SYS_FUNC(quotactl)
     469  {
     470  	/*
     471  	 * The Linux kernel only looks at the low 32 bits of command and id
     472  	 * arguments, but on some 64-bit architectures (s390x) this word
     473  	 * will have been sign-extended when we see it.  The high 1 bits
     474  	 * don't mean anything, so don't confuse the output with them.
     475  	 */
     476  	uint32_t qcmd = tcp->u_arg[0];
     477  	uint32_t cmd = QCMD_CMD(qcmd);
     478  	uint32_t id = tcp->u_arg[2];
     479  
     480  	if (entering(tcp)) {
     481  		/* cmd */
     482  		print_qcmd(qcmd);
     483  		tprint_arg_next();
     484  
     485  		/* special */
     486  		printpath(tcp, tcp->u_arg[1]);
     487  	}
     488  	return decode_cmd_data(tcp, id, cmd, tcp->u_arg[3]);
     489  }
     490  
     491  SYS_FUNC(quotactl_fd)
     492  {
     493  	const unsigned int fd = tcp->u_arg[0];
     494  	const unsigned int qcmd = tcp->u_arg[1];
     495  	const uint32_t id = tcp->u_arg[2];
     496  	const kernel_ulong_t addr = tcp->u_arg[3];
     497  
     498  	if (entering(tcp)) {
     499  		/* fd */
     500  		printfd(tcp, fd);
     501  		tprint_arg_next();
     502  
     503  		/* cmd */
     504  		print_qcmd(qcmd);
     505  	}
     506  
     507  	return decode_cmd_data(tcp, id, QCMD_CMD(qcmd), addr);
     508  }