LCOV - code coverage report
Current view: top level - fs/quota - quota.c (source / functions) Hit Total Coverage
Test: gcov_data_raspi2_real_modules_combined.info Lines: 0 420 0.0 %
Date: 2020-09-30 20:25:40 Functions: 0 32 0.0 %
Branches: 0 314 0.0 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0
       2                 :            : /*
       3                 :            :  * Quota code necessary even when VFS quota support is not compiled
       4                 :            :  * into the kernel.  The interesting stuff is over in dquot.c, here
       5                 :            :  * we have symbols for initial quotactl(2) handling, the sysctl(2)
       6                 :            :  * variables, etc - things needed even when quota support disabled.
       7                 :            :  */
       8                 :            : 
       9                 :            : #include <linux/fs.h>
      10                 :            : #include <linux/namei.h>
      11                 :            : #include <linux/slab.h>
      12                 :            : #include <asm/current.h>
      13                 :            : #include <linux/uaccess.h>
      14                 :            : #include <linux/kernel.h>
      15                 :            : #include <linux/security.h>
      16                 :            : #include <linux/syscalls.h>
      17                 :            : #include <linux/capability.h>
      18                 :            : #include <linux/quotaops.h>
      19                 :            : #include <linux/types.h>
      20                 :            : #include <linux/writeback.h>
      21                 :            : #include <linux/nospec.h>
      22                 :            : 
      23                 :          0 : static int check_quotactl_permission(struct super_block *sb, int type, int cmd,
      24                 :            :                                      qid_t id)
      25                 :            : {
      26      [ #  #  # ]:          0 :         switch (cmd) {
      27                 :            :         /* these commands do not require any special privilegues */
      28                 :            :         case Q_GETFMT:
      29                 :            :         case Q_SYNC:
      30                 :            :         case Q_GETINFO:
      31                 :            :         case Q_XGETQSTAT:
      32                 :            :         case Q_XGETQSTATV:
      33                 :            :         case Q_XQUOTASYNC:
      34                 :            :                 break;
      35                 :            :         /* allow to query information for dquots we "own" */
      36                 :            :         case Q_GETQUOTA:
      37                 :            :         case Q_XGETQUOTA:
      38   [ #  #  #  #  :          0 :                 if ((type == USRQUOTA && uid_eq(current_euid(), make_kuid(current_user_ns(), id))) ||
                   #  # ]
      39         [ #  # ]:          0 :                     (type == GRPQUOTA && in_egroup_p(make_kgid(current_user_ns(), id))))
      40                 :            :                         break;
      41                 :            :                 /*FALLTHROUGH*/
      42                 :            :         default:
      43         [ #  # ]:          0 :                 if (!capable(CAP_SYS_ADMIN))
      44                 :            :                         return -EPERM;
      45                 :            :         }
      46                 :            : 
      47                 :          0 :         return security_quotactl(cmd, type, id, sb);
      48                 :            : }
      49                 :            : 
      50                 :          0 : static void quota_sync_one(struct super_block *sb, void *arg)
      51                 :            : {
      52                 :          0 :         int type = *(int *)arg;
      53                 :            : 
      54   [ #  #  #  #  :          0 :         if (sb->s_qcop && sb->s_qcop->quota_sync &&
                   #  # ]
      55                 :          0 :             (sb->s_quota_types & (1 << type)))
      56                 :          0 :                 sb->s_qcop->quota_sync(sb, type);
      57                 :          0 : }
      58                 :            : 
      59                 :          0 : static int quota_sync_all(int type)
      60                 :            : {
      61                 :            :         int ret;
      62                 :            : 
      63         [ #  # ]:          0 :         if (type >= MAXQUOTAS)
      64                 :            :                 return -EINVAL;
      65                 :          0 :         ret = security_quotactl(Q_SYNC, type, 0, NULL);
      66         [ #  # ]:          0 :         if (!ret)
      67                 :          0 :                 iterate_supers(quota_sync_one, &type);
      68                 :          0 :         return ret;
      69                 :            : }
      70                 :            : 
      71         [ #  # ]:          0 : unsigned int qtype_enforce_flag(int type)
      72                 :            : {
      73                 :            :         switch (type) {
      74                 :            :         case USRQUOTA:
      75                 :            :                 return FS_QUOTA_UDQ_ENFD;
      76                 :            :         case GRPQUOTA:
      77                 :            :                 return FS_QUOTA_GDQ_ENFD;
      78                 :            :         case PRJQUOTA:
      79                 :            :                 return FS_QUOTA_PDQ_ENFD;
      80                 :            :         }
      81                 :            :         return 0;
      82                 :            : }
      83                 :            : 
      84                 :          0 : static int quota_quotaon(struct super_block *sb, int type, qid_t id,
      85                 :            :                          const struct path *path)
      86                 :            : {
      87   [ #  #  #  # ]:          0 :         if (!sb->s_qcop->quota_on && !sb->s_qcop->quota_enable)
      88                 :            :                 return -ENOSYS;
      89   [ #  #  #  # ]:          0 :         if (sb->s_qcop->quota_enable)
      90                 :          0 :                 return sb->s_qcop->quota_enable(sb, qtype_enforce_flag(type));
      91         [ #  # ]:          0 :         if (IS_ERR(path))
      92                 :          0 :                 return PTR_ERR(path);
      93                 :          0 :         return sb->s_qcop->quota_on(sb, type, id, path);
      94                 :            : }
      95                 :            : 
      96                 :          0 : static int quota_quotaoff(struct super_block *sb, int type)
      97                 :            : {
      98   [ #  #  #  # ]:          0 :         if (!sb->s_qcop->quota_off && !sb->s_qcop->quota_disable)
      99                 :            :                 return -ENOSYS;
     100   [ #  #  #  # ]:          0 :         if (sb->s_qcop->quota_disable)
     101                 :          0 :                 return sb->s_qcop->quota_disable(sb, qtype_enforce_flag(type));
     102                 :          0 :         return sb->s_qcop->quota_off(sb, type);
     103                 :            : }
     104                 :            : 
     105                 :          0 : static int quota_getfmt(struct super_block *sb, int type, void __user *addr)
     106                 :            : {
     107                 :            :         __u32 fmt;
     108                 :            : 
     109         [ #  # ]:          0 :         if (!sb_has_quota_active(sb, type))
     110                 :            :                 return -ESRCH;
     111                 :          0 :         fmt = sb_dqopt(sb)->info[type].dqi_format->qf_fmt_id;
     112         [ #  # ]:          0 :         if (copy_to_user(addr, &fmt, sizeof(fmt)))
     113                 :            :                 return -EFAULT;
     114                 :          0 :         return 0;
     115                 :            : }
     116                 :            : 
     117                 :          0 : static int quota_getinfo(struct super_block *sb, int type, void __user *addr)
     118                 :            : {
     119                 :            :         struct qc_state state;
     120                 :            :         struct qc_type_state *tstate;
     121                 :            :         struct if_dqinfo uinfo;
     122                 :            :         int ret;
     123                 :            : 
     124         [ #  # ]:          0 :         if (!sb->s_qcop->get_state)
     125                 :            :                 return -ENOSYS;
     126                 :          0 :         ret = sb->s_qcop->get_state(sb, &state);
     127         [ #  # ]:          0 :         if (ret)
     128                 :            :                 return ret;
     129                 :          0 :         tstate = state.s_state + type;
     130         [ #  # ]:          0 :         if (!(tstate->flags & QCI_ACCT_ENABLED))
     131                 :            :                 return -ESRCH;
     132                 :          0 :         memset(&uinfo, 0, sizeof(uinfo));
     133                 :          0 :         uinfo.dqi_bgrace = tstate->spc_timelimit;
     134                 :          0 :         uinfo.dqi_igrace = tstate->ino_timelimit;
     135         [ #  # ]:          0 :         if (tstate->flags & QCI_SYSFILE)
     136                 :          0 :                 uinfo.dqi_flags |= DQF_SYS_FILE;
     137         [ #  # ]:          0 :         if (tstate->flags & QCI_ROOT_SQUASH)
     138                 :          0 :                 uinfo.dqi_flags |= DQF_ROOT_SQUASH;
     139                 :          0 :         uinfo.dqi_valid = IIF_ALL;
     140         [ #  # ]:          0 :         if (copy_to_user(addr, &uinfo, sizeof(uinfo)))
     141                 :            :                 return -EFAULT;
     142                 :          0 :         return 0;
     143                 :            : }
     144                 :            : 
     145                 :          0 : static int quota_setinfo(struct super_block *sb, int type, void __user *addr)
     146                 :            : {
     147                 :            :         struct if_dqinfo info;
     148                 :            :         struct qc_info qinfo;
     149                 :            : 
     150         [ #  # ]:          0 :         if (copy_from_user(&info, addr, sizeof(info)))
     151                 :            :                 return -EFAULT;
     152         [ #  # ]:          0 :         if (!sb->s_qcop->set_info)
     153                 :            :                 return -ENOSYS;
     154         [ #  # ]:          0 :         if (info.dqi_valid & ~(IIF_FLAGS | IIF_BGRACE | IIF_IGRACE))
     155                 :            :                 return -EINVAL;
     156                 :          0 :         memset(&qinfo, 0, sizeof(qinfo));
     157         [ #  # ]:          0 :         if (info.dqi_valid & IIF_FLAGS) {
     158         [ #  # ]:          0 :                 if (info.dqi_flags & ~DQF_SETINFO_MASK)
     159                 :            :                         return -EINVAL;
     160         [ #  # ]:          0 :                 if (info.dqi_flags & DQF_ROOT_SQUASH)
     161                 :          0 :                         qinfo.i_flags |= QCI_ROOT_SQUASH;
     162                 :          0 :                 qinfo.i_fieldmask |= QC_FLAGS;
     163                 :            :         }
     164         [ #  # ]:          0 :         if (info.dqi_valid & IIF_BGRACE) {
     165                 :          0 :                 qinfo.i_spc_timelimit = info.dqi_bgrace;
     166                 :          0 :                 qinfo.i_fieldmask |= QC_SPC_TIMER;
     167                 :            :         }
     168         [ #  # ]:          0 :         if (info.dqi_valid & IIF_IGRACE) {
     169                 :          0 :                 qinfo.i_ino_timelimit = info.dqi_igrace;
     170                 :          0 :                 qinfo.i_fieldmask |= QC_INO_TIMER;
     171                 :            :         }
     172                 :          0 :         return sb->s_qcop->set_info(sb, type, &qinfo);
     173                 :            : }
     174                 :            : 
     175                 :            : static inline qsize_t qbtos(qsize_t blocks)
     176                 :            : {
     177                 :          0 :         return blocks << QIF_DQBLKSIZE_BITS;
     178                 :            : }
     179                 :            : 
     180                 :            : static inline qsize_t stoqb(qsize_t space)
     181                 :            : {
     182                 :          0 :         return (space + QIF_DQBLKSIZE - 1) >> QIF_DQBLKSIZE_BITS;
     183                 :            : }
     184                 :            : 
     185                 :          0 : static void copy_to_if_dqblk(struct if_dqblk *dst, struct qc_dqblk *src)
     186                 :            : {
     187                 :          0 :         memset(dst, 0, sizeof(*dst));
     188                 :          0 :         dst->dqb_bhardlimit = stoqb(src->d_spc_hardlimit);
     189                 :          0 :         dst->dqb_bsoftlimit = stoqb(src->d_spc_softlimit);
     190                 :          0 :         dst->dqb_curspace = src->d_space;
     191                 :          0 :         dst->dqb_ihardlimit = src->d_ino_hardlimit;
     192                 :          0 :         dst->dqb_isoftlimit = src->d_ino_softlimit;
     193                 :          0 :         dst->dqb_curinodes = src->d_ino_count;
     194                 :          0 :         dst->dqb_btime = src->d_spc_timer;
     195                 :          0 :         dst->dqb_itime = src->d_ino_timer;
     196                 :          0 :         dst->dqb_valid = QIF_ALL;
     197                 :          0 : }
     198                 :            : 
     199                 :          0 : static int quota_getquota(struct super_block *sb, int type, qid_t id,
     200                 :            :                           void __user *addr)
     201                 :            : {
     202                 :            :         struct kqid qid;
     203                 :            :         struct qc_dqblk fdq;
     204                 :            :         struct if_dqblk idq;
     205                 :            :         int ret;
     206                 :            : 
     207         [ #  # ]:          0 :         if (!sb->s_qcop->get_dqblk)
     208                 :            :                 return -ENOSYS;
     209                 :          0 :         qid = make_kqid(current_user_ns(), type, id);
     210         [ #  # ]:          0 :         if (!qid_has_mapping(sb->s_user_ns, qid))
     211                 :            :                 return -EINVAL;
     212                 :          0 :         ret = sb->s_qcop->get_dqblk(sb, qid, &fdq);
     213         [ #  # ]:          0 :         if (ret)
     214                 :            :                 return ret;
     215                 :          0 :         copy_to_if_dqblk(&idq, &fdq);
     216         [ #  # ]:          0 :         if (copy_to_user(addr, &idq, sizeof(idq)))
     217                 :            :                 return -EFAULT;
     218                 :          0 :         return 0;
     219                 :            : }
     220                 :            : 
     221                 :            : /*
     222                 :            :  * Return quota for next active quota >= this id, if any exists,
     223                 :            :  * otherwise return -ENOENT via ->get_nextdqblk
     224                 :            :  */
     225                 :          0 : static int quota_getnextquota(struct super_block *sb, int type, qid_t id,
     226                 :            :                           void __user *addr)
     227                 :            : {
     228                 :            :         struct kqid qid;
     229                 :            :         struct qc_dqblk fdq;
     230                 :            :         struct if_nextdqblk idq;
     231                 :            :         int ret;
     232                 :            : 
     233         [ #  # ]:          0 :         if (!sb->s_qcop->get_nextdqblk)
     234                 :            :                 return -ENOSYS;
     235                 :          0 :         qid = make_kqid(current_user_ns(), type, id);
     236         [ #  # ]:          0 :         if (!qid_has_mapping(sb->s_user_ns, qid))
     237                 :            :                 return -EINVAL;
     238                 :          0 :         ret = sb->s_qcop->get_nextdqblk(sb, &qid, &fdq);
     239         [ #  # ]:          0 :         if (ret)
     240                 :            :                 return ret;
     241                 :            :         /* struct if_nextdqblk is a superset of struct if_dqblk */
     242                 :          0 :         copy_to_if_dqblk((struct if_dqblk *)&idq, &fdq);
     243                 :          0 :         idq.dqb_id = from_kqid(current_user_ns(), qid);
     244         [ #  # ]:          0 :         if (copy_to_user(addr, &idq, sizeof(idq)))
     245                 :            :                 return -EFAULT;
     246                 :          0 :         return 0;
     247                 :            : }
     248                 :            : 
     249                 :          0 : static void copy_from_if_dqblk(struct qc_dqblk *dst, struct if_dqblk *src)
     250                 :            : {
     251                 :          0 :         dst->d_spc_hardlimit = qbtos(src->dqb_bhardlimit);
     252                 :          0 :         dst->d_spc_softlimit = qbtos(src->dqb_bsoftlimit);
     253                 :          0 :         dst->d_space = src->dqb_curspace;
     254                 :          0 :         dst->d_ino_hardlimit = src->dqb_ihardlimit;
     255                 :          0 :         dst->d_ino_softlimit = src->dqb_isoftlimit;
     256                 :          0 :         dst->d_ino_count = src->dqb_curinodes;
     257                 :          0 :         dst->d_spc_timer = src->dqb_btime;
     258                 :          0 :         dst->d_ino_timer = src->dqb_itime;
     259                 :            : 
     260                 :          0 :         dst->d_fieldmask = 0;
     261         [ #  # ]:          0 :         if (src->dqb_valid & QIF_BLIMITS)
     262                 :          0 :                 dst->d_fieldmask |= QC_SPC_SOFT | QC_SPC_HARD;
     263         [ #  # ]:          0 :         if (src->dqb_valid & QIF_SPACE)
     264                 :          0 :                 dst->d_fieldmask |= QC_SPACE;
     265         [ #  # ]:          0 :         if (src->dqb_valid & QIF_ILIMITS)
     266                 :          0 :                 dst->d_fieldmask |= QC_INO_SOFT | QC_INO_HARD;
     267         [ #  # ]:          0 :         if (src->dqb_valid & QIF_INODES)
     268                 :          0 :                 dst->d_fieldmask |= QC_INO_COUNT;
     269         [ #  # ]:          0 :         if (src->dqb_valid & QIF_BTIME)
     270                 :          0 :                 dst->d_fieldmask |= QC_SPC_TIMER;
     271         [ #  # ]:          0 :         if (src->dqb_valid & QIF_ITIME)
     272                 :          0 :                 dst->d_fieldmask |= QC_INO_TIMER;
     273                 :          0 : }
     274                 :            : 
     275                 :          0 : static int quota_setquota(struct super_block *sb, int type, qid_t id,
     276                 :            :                           void __user *addr)
     277                 :            : {
     278                 :            :         struct qc_dqblk fdq;
     279                 :            :         struct if_dqblk idq;
     280                 :            :         struct kqid qid;
     281                 :            : 
     282         [ #  # ]:          0 :         if (copy_from_user(&idq, addr, sizeof(idq)))
     283                 :            :                 return -EFAULT;
     284         [ #  # ]:          0 :         if (!sb->s_qcop->set_dqblk)
     285                 :            :                 return -ENOSYS;
     286                 :          0 :         qid = make_kqid(current_user_ns(), type, id);
     287         [ #  # ]:          0 :         if (!qid_has_mapping(sb->s_user_ns, qid))
     288                 :            :                 return -EINVAL;
     289                 :          0 :         copy_from_if_dqblk(&fdq, &idq);
     290                 :          0 :         return sb->s_qcop->set_dqblk(sb, qid, &fdq);
     291                 :            : }
     292                 :            : 
     293                 :          0 : static int quota_enable(struct super_block *sb, void __user *addr)
     294                 :            : {
     295                 :            :         __u32 flags;
     296                 :            : 
     297         [ #  # ]:          0 :         if (copy_from_user(&flags, addr, sizeof(flags)))
     298                 :            :                 return -EFAULT;
     299         [ #  # ]:          0 :         if (!sb->s_qcop->quota_enable)
     300                 :            :                 return -ENOSYS;
     301                 :          0 :         return sb->s_qcop->quota_enable(sb, flags);
     302                 :            : }
     303                 :            : 
     304                 :          0 : static int quota_disable(struct super_block *sb, void __user *addr)
     305                 :            : {
     306                 :            :         __u32 flags;
     307                 :            : 
     308         [ #  # ]:          0 :         if (copy_from_user(&flags, addr, sizeof(flags)))
     309                 :            :                 return -EFAULT;
     310         [ #  # ]:          0 :         if (!sb->s_qcop->quota_disable)
     311                 :            :                 return -ENOSYS;
     312                 :          0 :         return sb->s_qcop->quota_disable(sb, flags);
     313                 :            : }
     314                 :            : 
     315                 :          0 : static int quota_state_to_flags(struct qc_state *state)
     316                 :            : {
     317                 :            :         int flags = 0;
     318                 :            : 
     319         [ #  # ]:          0 :         if (state->s_state[USRQUOTA].flags & QCI_ACCT_ENABLED)
     320                 :            :                 flags |= FS_QUOTA_UDQ_ACCT;
     321         [ #  # ]:          0 :         if (state->s_state[USRQUOTA].flags & QCI_LIMITS_ENFORCED)
     322                 :          0 :                 flags |= FS_QUOTA_UDQ_ENFD;
     323         [ #  # ]:          0 :         if (state->s_state[GRPQUOTA].flags & QCI_ACCT_ENABLED)
     324                 :          0 :                 flags |= FS_QUOTA_GDQ_ACCT;
     325         [ #  # ]:          0 :         if (state->s_state[GRPQUOTA].flags & QCI_LIMITS_ENFORCED)
     326                 :          0 :                 flags |= FS_QUOTA_GDQ_ENFD;
     327         [ #  # ]:          0 :         if (state->s_state[PRJQUOTA].flags & QCI_ACCT_ENABLED)
     328                 :          0 :                 flags |= FS_QUOTA_PDQ_ACCT;
     329         [ #  # ]:          0 :         if (state->s_state[PRJQUOTA].flags & QCI_LIMITS_ENFORCED)
     330                 :          0 :                 flags |= FS_QUOTA_PDQ_ENFD;
     331                 :          0 :         return flags;
     332                 :            : }
     333                 :            : 
     334                 :          0 : static int quota_getstate(struct super_block *sb, int type,
     335                 :            :                           struct fs_quota_stat *fqs)
     336                 :            : {
     337                 :            :         struct qc_state state;
     338                 :            :         int ret;
     339                 :            : 
     340                 :          0 :         memset(&state, 0, sizeof (struct qc_state));
     341                 :          0 :         ret = sb->s_qcop->get_state(sb, &state);
     342         [ #  # ]:          0 :         if (ret < 0)
     343                 :            :                 return ret;
     344                 :            : 
     345                 :          0 :         memset(fqs, 0, sizeof(*fqs));
     346                 :          0 :         fqs->qs_version = FS_QSTAT_VERSION;
     347                 :          0 :         fqs->qs_flags = quota_state_to_flags(&state);
     348                 :            :         /* No quota enabled? */
     349         [ #  # ]:          0 :         if (!fqs->qs_flags)
     350                 :            :                 return -ENOSYS;
     351                 :          0 :         fqs->qs_incoredqs = state.s_incoredqs;
     352                 :            : 
     353                 :          0 :         fqs->qs_btimelimit = state.s_state[type].spc_timelimit;
     354                 :          0 :         fqs->qs_itimelimit = state.s_state[type].ino_timelimit;
     355                 :          0 :         fqs->qs_rtbtimelimit = state.s_state[type].rt_spc_timelimit;
     356                 :          0 :         fqs->qs_bwarnlimit = state.s_state[type].spc_warnlimit;
     357                 :          0 :         fqs->qs_iwarnlimit = state.s_state[type].ino_warnlimit;
     358                 :            : 
     359                 :            :         /* Inodes may be allocated even if inactive; copy out if present */
     360         [ #  # ]:          0 :         if (state.s_state[USRQUOTA].ino) {
     361                 :          0 :                 fqs->qs_uquota.qfs_ino = state.s_state[USRQUOTA].ino;
     362                 :          0 :                 fqs->qs_uquota.qfs_nblks = state.s_state[USRQUOTA].blocks;
     363                 :          0 :                 fqs->qs_uquota.qfs_nextents = state.s_state[USRQUOTA].nextents;
     364                 :            :         }
     365         [ #  # ]:          0 :         if (state.s_state[GRPQUOTA].ino) {
     366                 :          0 :                 fqs->qs_gquota.qfs_ino = state.s_state[GRPQUOTA].ino;
     367                 :          0 :                 fqs->qs_gquota.qfs_nblks = state.s_state[GRPQUOTA].blocks;
     368                 :          0 :                 fqs->qs_gquota.qfs_nextents = state.s_state[GRPQUOTA].nextents;
     369                 :            :         }
     370         [ #  # ]:          0 :         if (state.s_state[PRJQUOTA].ino) {
     371                 :            :                 /*
     372                 :            :                  * Q_XGETQSTAT doesn't have room for both group and project
     373                 :            :                  * quotas.  So, allow the project quota values to be copied out
     374                 :            :                  * only if there is no group quota information available.
     375                 :            :                  */
     376         [ #  # ]:          0 :                 if (!(state.s_state[GRPQUOTA].flags & QCI_ACCT_ENABLED)) {
     377                 :          0 :                         fqs->qs_gquota.qfs_ino = state.s_state[PRJQUOTA].ino;
     378                 :          0 :                         fqs->qs_gquota.qfs_nblks =
     379                 :          0 :                                         state.s_state[PRJQUOTA].blocks;
     380                 :          0 :                         fqs->qs_gquota.qfs_nextents =
     381                 :          0 :                                         state.s_state[PRJQUOTA].nextents;
     382                 :            :                 }
     383                 :            :         }
     384                 :            :         return 0;
     385                 :            : }
     386                 :            : 
     387                 :          0 : static int quota_getxstate(struct super_block *sb, int type, void __user *addr)
     388                 :            : {
     389                 :            :         struct fs_quota_stat fqs;
     390                 :            :         int ret;
     391                 :            : 
     392         [ #  # ]:          0 :         if (!sb->s_qcop->get_state)
     393                 :            :                 return -ENOSYS;
     394                 :          0 :         ret = quota_getstate(sb, type, &fqs);
     395   [ #  #  #  # ]:          0 :         if (!ret && copy_to_user(addr, &fqs, sizeof(fqs)))
     396                 :            :                 return -EFAULT;
     397                 :          0 :         return ret;
     398                 :            : }
     399                 :            : 
     400                 :          0 : static int quota_getstatev(struct super_block *sb, int type,
     401                 :            :                            struct fs_quota_statv *fqs)
     402                 :            : {
     403                 :            :         struct qc_state state;
     404                 :            :         int ret;
     405                 :            : 
     406                 :          0 :         memset(&state, 0, sizeof (struct qc_state));
     407                 :          0 :         ret = sb->s_qcop->get_state(sb, &state);
     408         [ #  # ]:          0 :         if (ret < 0)
     409                 :            :                 return ret;
     410                 :            : 
     411                 :          0 :         memset(fqs, 0, sizeof(*fqs));
     412                 :          0 :         fqs->qs_version = FS_QSTAT_VERSION;
     413                 :          0 :         fqs->qs_flags = quota_state_to_flags(&state);
     414                 :            :         /* No quota enabled? */
     415         [ #  # ]:          0 :         if (!fqs->qs_flags)
     416                 :            :                 return -ENOSYS;
     417                 :          0 :         fqs->qs_incoredqs = state.s_incoredqs;
     418                 :            : 
     419                 :          0 :         fqs->qs_btimelimit = state.s_state[type].spc_timelimit;
     420                 :          0 :         fqs->qs_itimelimit = state.s_state[type].ino_timelimit;
     421                 :          0 :         fqs->qs_rtbtimelimit = state.s_state[type].rt_spc_timelimit;
     422                 :          0 :         fqs->qs_bwarnlimit = state.s_state[type].spc_warnlimit;
     423                 :          0 :         fqs->qs_iwarnlimit = state.s_state[type].ino_warnlimit;
     424                 :            : 
     425                 :            :         /* Inodes may be allocated even if inactive; copy out if present */
     426         [ #  # ]:          0 :         if (state.s_state[USRQUOTA].ino) {
     427                 :          0 :                 fqs->qs_uquota.qfs_ino = state.s_state[USRQUOTA].ino;
     428                 :          0 :                 fqs->qs_uquota.qfs_nblks = state.s_state[USRQUOTA].blocks;
     429                 :          0 :                 fqs->qs_uquota.qfs_nextents = state.s_state[USRQUOTA].nextents;
     430                 :            :         }
     431         [ #  # ]:          0 :         if (state.s_state[GRPQUOTA].ino) {
     432                 :          0 :                 fqs->qs_gquota.qfs_ino = state.s_state[GRPQUOTA].ino;
     433                 :          0 :                 fqs->qs_gquota.qfs_nblks = state.s_state[GRPQUOTA].blocks;
     434                 :          0 :                 fqs->qs_gquota.qfs_nextents = state.s_state[GRPQUOTA].nextents;
     435                 :            :         }
     436         [ #  # ]:          0 :         if (state.s_state[PRJQUOTA].ino) {
     437                 :          0 :                 fqs->qs_pquota.qfs_ino = state.s_state[PRJQUOTA].ino;
     438                 :          0 :                 fqs->qs_pquota.qfs_nblks = state.s_state[PRJQUOTA].blocks;
     439                 :          0 :                 fqs->qs_pquota.qfs_nextents = state.s_state[PRJQUOTA].nextents;
     440                 :            :         }
     441                 :            :         return 0;
     442                 :            : }
     443                 :            : 
     444                 :          0 : static int quota_getxstatev(struct super_block *sb, int type, void __user *addr)
     445                 :            : {
     446                 :            :         struct fs_quota_statv fqs;
     447                 :            :         int ret;
     448                 :            : 
     449         [ #  # ]:          0 :         if (!sb->s_qcop->get_state)
     450                 :            :                 return -ENOSYS;
     451                 :            : 
     452                 :          0 :         memset(&fqs, 0, sizeof(fqs));
     453         [ #  # ]:          0 :         if (copy_from_user(&fqs, addr, 1)) /* Just read qs_version */
     454                 :            :                 return -EFAULT;
     455                 :            : 
     456                 :            :         /* If this kernel doesn't support user specified version, fail */
     457         [ #  # ]:          0 :         switch (fqs.qs_version) {
     458                 :            :         case FS_QSTATV_VERSION1:
     459                 :            :                 break;
     460                 :            :         default:
     461                 :            :                 return -EINVAL;
     462                 :            :         }
     463                 :          0 :         ret = quota_getstatev(sb, type, &fqs);
     464   [ #  #  #  # ]:          0 :         if (!ret && copy_to_user(addr, &fqs, sizeof(fqs)))
     465                 :            :                 return -EFAULT;
     466                 :          0 :         return ret;
     467                 :            : }
     468                 :            : 
     469                 :            : /*
     470                 :            :  * XFS defines BBTOB and BTOBB macros inside fs/xfs/ and we cannot move them
     471                 :            :  * out of there as xfsprogs rely on definitions being in that header file. So
     472                 :            :  * just define same functions here for quota purposes.
     473                 :            :  */
     474                 :            : #define XFS_BB_SHIFT 9
     475                 :            : 
     476                 :            : static inline u64 quota_bbtob(u64 blocks)
     477                 :            : {
     478                 :          0 :         return blocks << XFS_BB_SHIFT;
     479                 :            : }
     480                 :            : 
     481                 :            : static inline u64 quota_btobb(u64 bytes)
     482                 :            : {
     483                 :          0 :         return (bytes + (1 << XFS_BB_SHIFT) - 1) >> XFS_BB_SHIFT;
     484                 :            : }
     485                 :            : 
     486                 :          0 : static void copy_from_xfs_dqblk(struct qc_dqblk *dst, struct fs_disk_quota *src)
     487                 :            : {
     488                 :          0 :         dst->d_spc_hardlimit = quota_bbtob(src->d_blk_hardlimit);
     489                 :          0 :         dst->d_spc_softlimit = quota_bbtob(src->d_blk_softlimit);
     490                 :          0 :         dst->d_ino_hardlimit = src->d_ino_hardlimit;
     491                 :          0 :         dst->d_ino_softlimit = src->d_ino_softlimit;
     492                 :          0 :         dst->d_space = quota_bbtob(src->d_bcount);
     493                 :          0 :         dst->d_ino_count = src->d_icount;
     494                 :          0 :         dst->d_ino_timer = src->d_itimer;
     495                 :          0 :         dst->d_spc_timer = src->d_btimer;
     496                 :          0 :         dst->d_ino_warns = src->d_iwarns;
     497                 :          0 :         dst->d_spc_warns = src->d_bwarns;
     498                 :          0 :         dst->d_rt_spc_hardlimit = quota_bbtob(src->d_rtb_hardlimit);
     499                 :          0 :         dst->d_rt_spc_softlimit = quota_bbtob(src->d_rtb_softlimit);
     500                 :          0 :         dst->d_rt_space = quota_bbtob(src->d_rtbcount);
     501                 :          0 :         dst->d_rt_spc_timer = src->d_rtbtimer;
     502                 :          0 :         dst->d_rt_spc_warns = src->d_rtbwarns;
     503                 :          0 :         dst->d_fieldmask = 0;
     504         [ #  # ]:          0 :         if (src->d_fieldmask & FS_DQ_ISOFT)
     505                 :          0 :                 dst->d_fieldmask |= QC_INO_SOFT;
     506         [ #  # ]:          0 :         if (src->d_fieldmask & FS_DQ_IHARD)
     507                 :          0 :                 dst->d_fieldmask |= QC_INO_HARD;
     508         [ #  # ]:          0 :         if (src->d_fieldmask & FS_DQ_BSOFT)
     509                 :          0 :                 dst->d_fieldmask |= QC_SPC_SOFT;
     510         [ #  # ]:          0 :         if (src->d_fieldmask & FS_DQ_BHARD)
     511                 :          0 :                 dst->d_fieldmask |= QC_SPC_HARD;
     512         [ #  # ]:          0 :         if (src->d_fieldmask & FS_DQ_RTBSOFT)
     513                 :          0 :                 dst->d_fieldmask |= QC_RT_SPC_SOFT;
     514         [ #  # ]:          0 :         if (src->d_fieldmask & FS_DQ_RTBHARD)
     515                 :          0 :                 dst->d_fieldmask |= QC_RT_SPC_HARD;
     516         [ #  # ]:          0 :         if (src->d_fieldmask & FS_DQ_BTIMER)
     517                 :          0 :                 dst->d_fieldmask |= QC_SPC_TIMER;
     518         [ #  # ]:          0 :         if (src->d_fieldmask & FS_DQ_ITIMER)
     519                 :          0 :                 dst->d_fieldmask |= QC_INO_TIMER;
     520         [ #  # ]:          0 :         if (src->d_fieldmask & FS_DQ_RTBTIMER)
     521                 :          0 :                 dst->d_fieldmask |= QC_RT_SPC_TIMER;
     522         [ #  # ]:          0 :         if (src->d_fieldmask & FS_DQ_BWARNS)
     523                 :          0 :                 dst->d_fieldmask |= QC_SPC_WARNS;
     524         [ #  # ]:          0 :         if (src->d_fieldmask & FS_DQ_IWARNS)
     525                 :          0 :                 dst->d_fieldmask |= QC_INO_WARNS;
     526         [ #  # ]:          0 :         if (src->d_fieldmask & FS_DQ_RTBWARNS)
     527                 :          0 :                 dst->d_fieldmask |= QC_RT_SPC_WARNS;
     528         [ #  # ]:          0 :         if (src->d_fieldmask & FS_DQ_BCOUNT)
     529                 :          0 :                 dst->d_fieldmask |= QC_SPACE;
     530         [ #  # ]:          0 :         if (src->d_fieldmask & FS_DQ_ICOUNT)
     531                 :          0 :                 dst->d_fieldmask |= QC_INO_COUNT;
     532         [ #  # ]:          0 :         if (src->d_fieldmask & FS_DQ_RTBCOUNT)
     533                 :          0 :                 dst->d_fieldmask |= QC_RT_SPACE;
     534                 :          0 : }
     535                 :            : 
     536                 :          0 : static void copy_qcinfo_from_xfs_dqblk(struct qc_info *dst,
     537                 :            :                                        struct fs_disk_quota *src)
     538                 :            : {
     539                 :          0 :         memset(dst, 0, sizeof(*dst));
     540                 :          0 :         dst->i_spc_timelimit = src->d_btimer;
     541                 :          0 :         dst->i_ino_timelimit = src->d_itimer;
     542                 :          0 :         dst->i_rt_spc_timelimit = src->d_rtbtimer;
     543                 :          0 :         dst->i_ino_warnlimit = src->d_iwarns;
     544                 :          0 :         dst->i_spc_warnlimit = src->d_bwarns;
     545                 :          0 :         dst->i_rt_spc_warnlimit = src->d_rtbwarns;
     546         [ #  # ]:          0 :         if (src->d_fieldmask & FS_DQ_BWARNS)
     547                 :          0 :                 dst->i_fieldmask |= QC_SPC_WARNS;
     548         [ #  # ]:          0 :         if (src->d_fieldmask & FS_DQ_IWARNS)
     549                 :          0 :                 dst->i_fieldmask |= QC_INO_WARNS;
     550         [ #  # ]:          0 :         if (src->d_fieldmask & FS_DQ_RTBWARNS)
     551                 :          0 :                 dst->i_fieldmask |= QC_RT_SPC_WARNS;
     552         [ #  # ]:          0 :         if (src->d_fieldmask & FS_DQ_BTIMER)
     553                 :          0 :                 dst->i_fieldmask |= QC_SPC_TIMER;
     554         [ #  # ]:          0 :         if (src->d_fieldmask & FS_DQ_ITIMER)
     555                 :          0 :                 dst->i_fieldmask |= QC_INO_TIMER;
     556         [ #  # ]:          0 :         if (src->d_fieldmask & FS_DQ_RTBTIMER)
     557                 :          0 :                 dst->i_fieldmask |= QC_RT_SPC_TIMER;
     558                 :          0 : }
     559                 :            : 
     560                 :          0 : static int quota_setxquota(struct super_block *sb, int type, qid_t id,
     561                 :            :                            void __user *addr)
     562                 :            : {
     563                 :            :         struct fs_disk_quota fdq;
     564                 :            :         struct qc_dqblk qdq;
     565                 :            :         struct kqid qid;
     566                 :            : 
     567         [ #  # ]:          0 :         if (copy_from_user(&fdq, addr, sizeof(fdq)))
     568                 :            :                 return -EFAULT;
     569         [ #  # ]:          0 :         if (!sb->s_qcop->set_dqblk)
     570                 :            :                 return -ENOSYS;
     571                 :          0 :         qid = make_kqid(current_user_ns(), type, id);
     572         [ #  # ]:          0 :         if (!qid_has_mapping(sb->s_user_ns, qid))
     573                 :            :                 return -EINVAL;
     574                 :            :         /* Are we actually setting timer / warning limits for all users? */
     575   [ #  #  #  # ]:          0 :         if (from_kqid(sb->s_user_ns, qid) == 0 &&
     576                 :          0 :             fdq.d_fieldmask & (FS_DQ_WARNS_MASK | FS_DQ_TIMER_MASK)) {
     577                 :            :                 struct qc_info qinfo;
     578                 :            :                 int ret;
     579                 :            : 
     580         [ #  # ]:          0 :                 if (!sb->s_qcop->set_info)
     581                 :          0 :                         return -EINVAL;
     582                 :          0 :                 copy_qcinfo_from_xfs_dqblk(&qinfo, &fdq);
     583                 :          0 :                 ret = sb->s_qcop->set_info(sb, type, &qinfo);
     584         [ #  # ]:          0 :                 if (ret)
     585                 :            :                         return ret;
     586                 :            :                 /* These are already done */
     587                 :          0 :                 fdq.d_fieldmask &= ~(FS_DQ_WARNS_MASK | FS_DQ_TIMER_MASK);
     588                 :            :         }
     589                 :          0 :         copy_from_xfs_dqblk(&qdq, &fdq);
     590                 :          0 :         return sb->s_qcop->set_dqblk(sb, qid, &qdq);
     591                 :            : }
     592                 :            : 
     593                 :          0 : static void copy_to_xfs_dqblk(struct fs_disk_quota *dst, struct qc_dqblk *src,
     594                 :            :                               int type, qid_t id)
     595                 :            : {
     596                 :          0 :         memset(dst, 0, sizeof(*dst));
     597                 :          0 :         dst->d_version = FS_DQUOT_VERSION;
     598                 :          0 :         dst->d_id = id;
     599         [ #  # ]:          0 :         if (type == USRQUOTA)
     600                 :          0 :                 dst->d_flags = FS_USER_QUOTA;
     601         [ #  # ]:          0 :         else if (type == PRJQUOTA)
     602                 :          0 :                 dst->d_flags = FS_PROJ_QUOTA;
     603                 :            :         else
     604                 :          0 :                 dst->d_flags = FS_GROUP_QUOTA;
     605                 :          0 :         dst->d_blk_hardlimit = quota_btobb(src->d_spc_hardlimit);
     606                 :          0 :         dst->d_blk_softlimit = quota_btobb(src->d_spc_softlimit);
     607                 :          0 :         dst->d_ino_hardlimit = src->d_ino_hardlimit;
     608                 :          0 :         dst->d_ino_softlimit = src->d_ino_softlimit;
     609                 :          0 :         dst->d_bcount = quota_btobb(src->d_space);
     610                 :          0 :         dst->d_icount = src->d_ino_count;
     611                 :          0 :         dst->d_itimer = src->d_ino_timer;
     612                 :          0 :         dst->d_btimer = src->d_spc_timer;
     613                 :          0 :         dst->d_iwarns = src->d_ino_warns;
     614                 :          0 :         dst->d_bwarns = src->d_spc_warns;
     615                 :          0 :         dst->d_rtb_hardlimit = quota_btobb(src->d_rt_spc_hardlimit);
     616                 :          0 :         dst->d_rtb_softlimit = quota_btobb(src->d_rt_spc_softlimit);
     617                 :          0 :         dst->d_rtbcount = quota_btobb(src->d_rt_space);
     618                 :          0 :         dst->d_rtbtimer = src->d_rt_spc_timer;
     619                 :          0 :         dst->d_rtbwarns = src->d_rt_spc_warns;
     620                 :          0 : }
     621                 :            : 
     622                 :          0 : static int quota_getxquota(struct super_block *sb, int type, qid_t id,
     623                 :            :                            void __user *addr)
     624                 :            : {
     625                 :            :         struct fs_disk_quota fdq;
     626                 :            :         struct qc_dqblk qdq;
     627                 :            :         struct kqid qid;
     628                 :            :         int ret;
     629                 :            : 
     630         [ #  # ]:          0 :         if (!sb->s_qcop->get_dqblk)
     631                 :            :                 return -ENOSYS;
     632                 :          0 :         qid = make_kqid(current_user_ns(), type, id);
     633         [ #  # ]:          0 :         if (!qid_has_mapping(sb->s_user_ns, qid))
     634                 :            :                 return -EINVAL;
     635                 :          0 :         ret = sb->s_qcop->get_dqblk(sb, qid, &qdq);
     636         [ #  # ]:          0 :         if (ret)
     637                 :            :                 return ret;
     638                 :          0 :         copy_to_xfs_dqblk(&fdq, &qdq, type, id);
     639         [ #  # ]:          0 :         if (copy_to_user(addr, &fdq, sizeof(fdq)))
     640                 :            :                 return -EFAULT;
     641                 :          0 :         return ret;
     642                 :            : }
     643                 :            : 
     644                 :            : /*
     645                 :            :  * Return quota for next active quota >= this id, if any exists,
     646                 :            :  * otherwise return -ENOENT via ->get_nextdqblk.
     647                 :            :  */
     648                 :          0 : static int quota_getnextxquota(struct super_block *sb, int type, qid_t id,
     649                 :            :                             void __user *addr)
     650                 :            : {
     651                 :            :         struct fs_disk_quota fdq;
     652                 :            :         struct qc_dqblk qdq;
     653                 :            :         struct kqid qid;
     654                 :            :         qid_t id_out;
     655                 :            :         int ret;
     656                 :            : 
     657         [ #  # ]:          0 :         if (!sb->s_qcop->get_nextdqblk)
     658                 :            :                 return -ENOSYS;
     659                 :          0 :         qid = make_kqid(current_user_ns(), type, id);
     660         [ #  # ]:          0 :         if (!qid_has_mapping(sb->s_user_ns, qid))
     661                 :            :                 return -EINVAL;
     662                 :          0 :         ret = sb->s_qcop->get_nextdqblk(sb, &qid, &qdq);
     663         [ #  # ]:          0 :         if (ret)
     664                 :            :                 return ret;
     665                 :          0 :         id_out = from_kqid(current_user_ns(), qid);
     666                 :          0 :         copy_to_xfs_dqblk(&fdq, &qdq, type, id_out);
     667         [ #  # ]:          0 :         if (copy_to_user(addr, &fdq, sizeof(fdq)))
     668                 :            :                 return -EFAULT;
     669                 :          0 :         return ret;
     670                 :            : }
     671                 :            : 
     672                 :          0 : static int quota_rmxquota(struct super_block *sb, void __user *addr)
     673                 :            : {
     674                 :            :         __u32 flags;
     675                 :            : 
     676         [ #  # ]:          0 :         if (copy_from_user(&flags, addr, sizeof(flags)))
     677                 :            :                 return -EFAULT;
     678         [ #  # ]:          0 :         if (!sb->s_qcop->rm_xquota)
     679                 :            :                 return -ENOSYS;
     680                 :          0 :         return sb->s_qcop->rm_xquota(sb, flags);
     681                 :            : }
     682                 :            : 
     683                 :            : /* Copy parameters and call proper function */
     684                 :          0 : static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id,
     685                 :            :                        void __user *addr, const struct path *path)
     686                 :            : {
     687                 :            :         int ret;
     688                 :            : 
     689         [ #  # ]:          0 :         if (type >= MAXQUOTAS)
     690                 :            :                 return -EINVAL;
     691                 :          0 :         type = array_index_nospec(type, MAXQUOTAS);
     692                 :            :         /*
     693                 :            :          * Quota not supported on this fs? Check this before s_quota_types
     694                 :            :          * since they needn't be set if quota is not supported at all.
     695                 :            :          */
     696         [ #  # ]:          0 :         if (!sb->s_qcop)
     697                 :            :                 return -ENOSYS;
     698         [ #  # ]:          0 :         if (!(sb->s_quota_types & (1 << type)))
     699                 :            :                 return -EINVAL;
     700                 :            : 
     701                 :          0 :         ret = check_quotactl_permission(sb, type, cmd, id);
     702         [ #  # ]:          0 :         if (ret < 0)
     703                 :            :                 return ret;
     704                 :            : 
     705   [ #  #  #  #  :          0 :         switch (cmd) {
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     706                 :            :         case Q_QUOTAON:
     707                 :          0 :                 return quota_quotaon(sb, type, id, path);
     708                 :            :         case Q_QUOTAOFF:
     709                 :          0 :                 return quota_quotaoff(sb, type);
     710                 :            :         case Q_GETFMT:
     711                 :          0 :                 return quota_getfmt(sb, type, addr);
     712                 :            :         case Q_GETINFO:
     713                 :          0 :                 return quota_getinfo(sb, type, addr);
     714                 :            :         case Q_SETINFO:
     715                 :          0 :                 return quota_setinfo(sb, type, addr);
     716                 :            :         case Q_GETQUOTA:
     717                 :          0 :                 return quota_getquota(sb, type, id, addr);
     718                 :            :         case Q_GETNEXTQUOTA:
     719                 :          0 :                 return quota_getnextquota(sb, type, id, addr);
     720                 :            :         case Q_SETQUOTA:
     721                 :          0 :                 return quota_setquota(sb, type, id, addr);
     722                 :            :         case Q_SYNC:
     723         [ #  # ]:          0 :                 if (!sb->s_qcop->quota_sync)
     724                 :            :                         return -ENOSYS;
     725                 :          0 :                 return sb->s_qcop->quota_sync(sb, type);
     726                 :            :         case Q_XQUOTAON:
     727                 :          0 :                 return quota_enable(sb, addr);
     728                 :            :         case Q_XQUOTAOFF:
     729                 :          0 :                 return quota_disable(sb, addr);
     730                 :            :         case Q_XQUOTARM:
     731                 :          0 :                 return quota_rmxquota(sb, addr);
     732                 :            :         case Q_XGETQSTAT:
     733                 :          0 :                 return quota_getxstate(sb, type, addr);
     734                 :            :         case Q_XGETQSTATV:
     735                 :          0 :                 return quota_getxstatev(sb, type, addr);
     736                 :            :         case Q_XSETQLIM:
     737                 :          0 :                 return quota_setxquota(sb, type, id, addr);
     738                 :            :         case Q_XGETQUOTA:
     739                 :          0 :                 return quota_getxquota(sb, type, id, addr);
     740                 :            :         case Q_XGETNEXTQUOTA:
     741                 :          0 :                 return quota_getnextxquota(sb, type, id, addr);
     742                 :            :         case Q_XQUOTASYNC:
     743         [ #  # ]:          0 :                 if (sb_rdonly(sb))
     744                 :            :                         return -EROFS;
     745                 :            :                 /* XFS quotas are fully coherent now, making this call a noop */
     746                 :          0 :                 return 0;
     747                 :            :         default:
     748                 :            :                 return -EINVAL;
     749                 :            :         }
     750                 :            : }
     751                 :            : 
     752                 :            : #ifdef CONFIG_BLOCK
     753                 :            : 
     754                 :            : /* Return 1 if 'cmd' will block on frozen filesystem */
     755                 :            : static int quotactl_cmd_write(int cmd)
     756                 :            : {
     757                 :            :         /*
     758                 :            :          * We cannot allow Q_GETQUOTA and Q_GETNEXTQUOTA without write access
     759                 :            :          * as dquot_acquire() may allocate space for new structure and OCFS2
     760                 :            :          * needs to increment on-disk use count.
     761                 :            :          */
     762         [ #  # ]:          0 :         switch (cmd) {
     763                 :            :         case Q_GETFMT:
     764                 :            :         case Q_GETINFO:
     765                 :            :         case Q_SYNC:
     766                 :            :         case Q_XGETQSTAT:
     767                 :            :         case Q_XGETQSTATV:
     768                 :            :         case Q_XGETQUOTA:
     769                 :            :         case Q_XGETNEXTQUOTA:
     770                 :            :         case Q_XQUOTASYNC:
     771                 :            :                 return 0;
     772                 :            :         }
     773                 :            :         return 1;
     774                 :            : }
     775                 :            : #endif /* CONFIG_BLOCK */
     776                 :            : 
     777                 :            : /* Return true if quotactl command is manipulating quota on/off state */
     778                 :            : static bool quotactl_cmd_onoff(int cmd)
     779                 :            : {
     780                 :          0 :         return (cmd == Q_QUOTAON) || (cmd == Q_QUOTAOFF) ||
     781   [ #  #  #  #  :          0 :                  (cmd == Q_XQUOTAON) || (cmd == Q_XQUOTAOFF);
             #  #  #  # ]
     782                 :            : }
     783                 :            : 
     784                 :            : /*
     785                 :            :  * look up a superblock on which quota ops will be performed
     786                 :            :  * - use the name of a block device to find the superblock thereon
     787                 :            :  */
     788                 :          0 : static struct super_block *quotactl_block(const char __user *special, int cmd)
     789                 :            : {
     790                 :            : #ifdef CONFIG_BLOCK
     791                 :            :         struct block_device *bdev;
     792                 :            :         struct super_block *sb;
     793                 :          0 :         struct filename *tmp = getname(special);
     794                 :            : 
     795         [ #  # ]:          0 :         if (IS_ERR(tmp))
     796                 :            :                 return ERR_CAST(tmp);
     797                 :          0 :         bdev = lookup_bdev(tmp->name);
     798                 :          0 :         putname(tmp);
     799         [ #  # ]:          0 :         if (IS_ERR(bdev))
     800                 :            :                 return ERR_CAST(bdev);
     801         [ #  # ]:          0 :         if (quotactl_cmd_onoff(cmd))
     802                 :          0 :                 sb = get_super_exclusive_thawed(bdev);
     803         [ #  # ]:          0 :         else if (quotactl_cmd_write(cmd))
     804                 :          0 :                 sb = get_super_thawed(bdev);
     805                 :            :         else
     806                 :          0 :                 sb = get_super(bdev);
     807                 :          0 :         bdput(bdev);
     808         [ #  # ]:          0 :         if (!sb)
     809                 :            :                 return ERR_PTR(-ENODEV);
     810                 :            : 
     811                 :          0 :         return sb;
     812                 :            : #else
     813                 :            :         return ERR_PTR(-ENODEV);
     814                 :            : #endif
     815                 :            : }
     816                 :            : 
     817                 :            : /*
     818                 :            :  * This is the system call interface. This communicates with
     819                 :            :  * the user-level programs. Currently this only supports diskquota
     820                 :            :  * calls. Maybe we need to add the process quotas etc. in the future,
     821                 :            :  * but we probably should use rlimits for that.
     822                 :            :  */
     823                 :          0 : int kernel_quotactl(unsigned int cmd, const char __user *special,
     824                 :            :                     qid_t id, void __user *addr)
     825                 :            : {
     826                 :            :         uint cmds, type;
     827                 :            :         struct super_block *sb = NULL;
     828                 :            :         struct path path, *pathp = NULL;
     829                 :            :         int ret;
     830                 :            : 
     831                 :          0 :         cmds = cmd >> SUBCMDSHIFT;
     832                 :          0 :         type = cmd & SUBCMDMASK;
     833                 :            : 
     834                 :            :         /*
     835                 :            :          * As a special case Q_SYNC can be called without a specific device.
     836                 :            :          * It will iterate all superblocks that have quota enabled and call
     837                 :            :          * the sync action on each of them.
     838                 :            :          */
     839         [ #  # ]:          0 :         if (!special) {
     840         [ #  # ]:          0 :                 if (cmds == Q_SYNC)
     841                 :          0 :                         return quota_sync_all(type);
     842                 :            :                 return -ENODEV;
     843                 :            :         }
     844                 :            : 
     845                 :            :         /*
     846                 :            :          * Path for quotaon has to be resolved before grabbing superblock
     847                 :            :          * because that gets s_umount sem which is also possibly needed by path
     848                 :            :          * resolution (think about autofs) and thus deadlocks could arise.
     849                 :            :          */
     850         [ #  # ]:          0 :         if (cmds == Q_QUOTAON) {
     851                 :            :                 ret = user_path_at(AT_FDCWD, addr, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &path);
     852         [ #  # ]:          0 :                 if (ret)
     853                 :            :                         pathp = ERR_PTR(ret);
     854                 :            :                 else
     855                 :            :                         pathp = &path;
     856                 :            :         }
     857                 :            : 
     858                 :          0 :         sb = quotactl_block(special, cmds);
     859         [ #  # ]:          0 :         if (IS_ERR(sb)) {
     860                 :            :                 ret = PTR_ERR(sb);
     861                 :          0 :                 goto out;
     862                 :            :         }
     863                 :            : 
     864                 :          0 :         ret = do_quotactl(sb, type, cmds, id, addr, pathp);
     865                 :            : 
     866         [ #  # ]:          0 :         if (!quotactl_cmd_onoff(cmds))
     867                 :          0 :                 drop_super(sb);
     868                 :            :         else
     869                 :          0 :                 drop_super_exclusive(sb);
     870                 :            : out:
     871   [ #  #  #  # ]:          0 :         if (pathp && !IS_ERR(pathp))
     872                 :          0 :                 path_put(pathp);
     873                 :          0 :         return ret;
     874                 :            : }
     875                 :            : 
     876                 :          0 : SYSCALL_DEFINE4(quotactl, unsigned int, cmd, const char __user *, special,
     877                 :            :                 qid_t, id, void __user *, addr)
     878                 :            : {
     879                 :          0 :         return kernel_quotactl(cmd, special, id, addr);
     880                 :            : }

Generated by: LCOV version 1.14