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

Generated by: LCOV version 1.14