linux/fs/quota/quota.c
<<
>>
Prefs
   1/*
   2 * Quota code necessary even when VFS quota support is not compiled
   3 * into the kernel.  The interesting stuff is over in dquot.c, here
   4 * we have symbols for initial quotactl(2) handling, the sysctl(2)
   5 * variables, etc - things needed even when quota support disabled.
   6 */
   7
   8#include <linux/fs.h>
   9#include <linux/namei.h>
  10#include <linux/slab.h>
  11#include <asm/current.h>
  12#include <linux/uaccess.h>
  13#include <linux/kernel.h>
  14#include <linux/security.h>
  15#include <linux/syscalls.h>
  16#include <linux/capability.h>
  17#include <linux/quotaops.h>
  18#include <linux/types.h>
  19#include <linux/writeback.h>
  20
  21static int check_quotactl_permission(struct super_block *sb, int type, int cmd,
  22                                     qid_t id)
  23{
  24        switch (cmd) {
  25        /* these commands do not require any special privilegues */
  26        case Q_GETFMT:
  27        case Q_SYNC:
  28        case Q_GETINFO:
  29        case Q_XGETQSTAT:
  30        case Q_XGETQSTATV:
  31        case Q_XQUOTASYNC:
  32                break;
  33        /* allow to query information for dquots we "own" */
  34        case Q_GETQUOTA:
  35        case Q_XGETQUOTA:
  36                if ((type == USRQUOTA && uid_eq(current_euid(), make_kuid(current_user_ns(), id))) ||
  37                    (type == GRPQUOTA && in_egroup_p(make_kgid(current_user_ns(), id))))
  38                        break;
  39                /*FALLTHROUGH*/
  40        default:
  41                if (!capable(CAP_SYS_ADMIN))
  42                        return -EPERM;
  43        }
  44
  45        return security_quotactl(cmd, type, id, sb);
  46}
  47
  48static void quota_sync_one(struct super_block *sb, void *arg)
  49{
  50        if (sb->s_qcop && sb->s_qcop->quota_sync)
  51                sb->s_qcop->quota_sync(sb, *(int *)arg);
  52}
  53
  54static int quota_sync_all(int type)
  55{
  56        int ret;
  57
  58        if (type >= MAXQUOTAS)
  59                return -EINVAL;
  60        ret = security_quotactl(Q_SYNC, type, 0, NULL);
  61        if (!ret)
  62                iterate_supers(quota_sync_one, &type);
  63        return ret;
  64}
  65
  66static int quota_quotaon(struct super_block *sb, int type, int cmd, qid_t id,
  67                         struct path *path)
  68{
  69        if (!sb->s_qcop->quota_on && !sb->s_qcop->quota_on_meta)
  70                return -ENOSYS;
  71        if (sb->s_qcop->quota_on_meta)
  72                return sb->s_qcop->quota_on_meta(sb, type, id);
  73        if (IS_ERR(path))
  74                return PTR_ERR(path);
  75        return sb->s_qcop->quota_on(sb, type, id, path);
  76}
  77
  78static int quota_getfmt(struct super_block *sb, int type, void __user *addr)
  79{
  80        __u32 fmt;
  81
  82        down_read(&sb_dqopt(sb)->dqptr_sem);
  83        if (!sb_has_quota_active(sb, type)) {
  84                up_read(&sb_dqopt(sb)->dqptr_sem);
  85                return -ESRCH;
  86        }
  87        fmt = sb_dqopt(sb)->info[type].dqi_format->qf_fmt_id;
  88        up_read(&sb_dqopt(sb)->dqptr_sem);
  89        if (copy_to_user(addr, &fmt, sizeof(fmt)))
  90                return -EFAULT;
  91        return 0;
  92}
  93
  94static int quota_getinfo(struct super_block *sb, int type, void __user *addr)
  95{
  96        struct if_dqinfo info;
  97        int ret;
  98
  99        if (!sb->s_qcop->get_info)
 100                return -ENOSYS;
 101        ret = sb->s_qcop->get_info(sb, type, &info);
 102        if (!ret && copy_to_user(addr, &info, sizeof(info)))
 103                return -EFAULT;
 104        return ret;
 105}
 106
 107static int quota_setinfo(struct super_block *sb, int type, void __user *addr)
 108{
 109        struct if_dqinfo info;
 110
 111        if (copy_from_user(&info, addr, sizeof(info)))
 112                return -EFAULT;
 113        if (!sb->s_qcop->set_info)
 114                return -ENOSYS;
 115        return sb->s_qcop->set_info(sb, type, &info);
 116}
 117
 118static void copy_to_if_dqblk(struct if_dqblk *dst, struct fs_disk_quota *src)
 119{
 120        dst->dqb_bhardlimit = src->d_blk_hardlimit;
 121        dst->dqb_bsoftlimit = src->d_blk_softlimit;
 122        dst->dqb_curspace = src->d_bcount;
 123        dst->dqb_ihardlimit = src->d_ino_hardlimit;
 124        dst->dqb_isoftlimit = src->d_ino_softlimit;
 125        dst->dqb_curinodes = src->d_icount;
 126        dst->dqb_btime = src->d_btimer;
 127        dst->dqb_itime = src->d_itimer;
 128        dst->dqb_valid = QIF_ALL;
 129}
 130
 131static int quota_getquota(struct super_block *sb, int type, qid_t id,
 132                          void __user *addr)
 133{
 134        struct kqid qid;
 135        struct fs_disk_quota fdq;
 136        struct if_dqblk idq;
 137        int ret;
 138
 139        if (!sb->s_qcop->get_dqblk)
 140                return -ENOSYS;
 141        qid = make_kqid(current_user_ns(), type, id);
 142        if (!qid_valid(qid))
 143                return -EINVAL;
 144        ret = sb->s_qcop->get_dqblk(sb, qid, &fdq);
 145        if (ret)
 146                return ret;
 147        copy_to_if_dqblk(&idq, &fdq);
 148        if (copy_to_user(addr, &idq, sizeof(idq)))
 149                return -EFAULT;
 150        return 0;
 151}
 152
 153static void copy_from_if_dqblk(struct fs_disk_quota *dst, struct if_dqblk *src)
 154{
 155        dst->d_blk_hardlimit = src->dqb_bhardlimit;
 156        dst->d_blk_softlimit  = src->dqb_bsoftlimit;
 157        dst->d_bcount = src->dqb_curspace;
 158        dst->d_ino_hardlimit = src->dqb_ihardlimit;
 159        dst->d_ino_softlimit = src->dqb_isoftlimit;
 160        dst->d_icount = src->dqb_curinodes;
 161        dst->d_btimer = src->dqb_btime;
 162        dst->d_itimer = src->dqb_itime;
 163
 164        dst->d_fieldmask = 0;
 165        if (src->dqb_valid & QIF_BLIMITS)
 166                dst->d_fieldmask |= FS_DQ_BSOFT | FS_DQ_BHARD;
 167        if (src->dqb_valid & QIF_SPACE)
 168                dst->d_fieldmask |= FS_DQ_BCOUNT;
 169        if (src->dqb_valid & QIF_ILIMITS)
 170                dst->d_fieldmask |= FS_DQ_ISOFT | FS_DQ_IHARD;
 171        if (src->dqb_valid & QIF_INODES)
 172                dst->d_fieldmask |= FS_DQ_ICOUNT;
 173        if (src->dqb_valid & QIF_BTIME)
 174                dst->d_fieldmask |= FS_DQ_BTIMER;
 175        if (src->dqb_valid & QIF_ITIME)
 176                dst->d_fieldmask |= FS_DQ_ITIMER;
 177}
 178
 179static int quota_setquota(struct super_block *sb, int type, qid_t id,
 180                          void __user *addr)
 181{
 182        struct fs_disk_quota fdq;
 183        struct if_dqblk idq;
 184        struct kqid qid;
 185
 186        if (copy_from_user(&idq, addr, sizeof(idq)))
 187                return -EFAULT;
 188        if (!sb->s_qcop->set_dqblk)
 189                return -ENOSYS;
 190        qid = make_kqid(current_user_ns(), type, id);
 191        if (!qid_valid(qid))
 192                return -EINVAL;
 193        copy_from_if_dqblk(&fdq, &idq);
 194        return sb->s_qcop->set_dqblk(sb, qid, &fdq);
 195}
 196
 197static int quota_setxstate(struct super_block *sb, int cmd, void __user *addr)
 198{
 199        __u32 flags;
 200
 201        if (copy_from_user(&flags, addr, sizeof(flags)))
 202                return -EFAULT;
 203        if (!sb->s_qcop->set_xstate)
 204                return -ENOSYS;
 205        return sb->s_qcop->set_xstate(sb, flags, cmd);
 206}
 207
 208static int quota_getxstate(struct super_block *sb, void __user *addr)
 209{
 210        struct fs_quota_stat fqs;
 211        int ret;
 212
 213        if (!sb->s_qcop->get_xstate)
 214                return -ENOSYS;
 215        ret = sb->s_qcop->get_xstate(sb, &fqs);
 216        if (!ret && copy_to_user(addr, &fqs, sizeof(fqs)))
 217                return -EFAULT;
 218        return ret;
 219}
 220
 221static int quota_getxstatev(struct super_block *sb, void __user *addr)
 222{
 223        struct fs_quota_statv fqs;
 224        int ret;
 225
 226        if (!sb->s_qcop->get_xstatev)
 227                return -ENOSYS;
 228
 229        memset(&fqs, 0, sizeof(fqs));
 230        if (copy_from_user(&fqs, addr, 1)) /* Just read qs_version */
 231                return -EFAULT;
 232
 233        /* If this kernel doesn't support user specified version, fail */
 234        switch (fqs.qs_version) {
 235        case FS_QSTATV_VERSION1:
 236                break;
 237        default:
 238                return -EINVAL;
 239        }
 240        ret = sb->s_qcop->get_xstatev(sb, &fqs);
 241        if (!ret && copy_to_user(addr, &fqs, sizeof(fqs)))
 242                return -EFAULT;
 243        return ret;
 244}
 245
 246static int quota_setxquota(struct super_block *sb, int type, qid_t id,
 247                           void __user *addr)
 248{
 249        struct fs_disk_quota fdq;
 250        struct kqid qid;
 251
 252        if (copy_from_user(&fdq, addr, sizeof(fdq)))
 253                return -EFAULT;
 254        if (!sb->s_qcop->set_dqblk)
 255                return -ENOSYS;
 256        qid = make_kqid(current_user_ns(), type, id);
 257        if (!qid_valid(qid))
 258                return -EINVAL;
 259        return sb->s_qcop->set_dqblk(sb, qid, &fdq);
 260}
 261
 262static int quota_getxquota(struct super_block *sb, int type, qid_t id,
 263                           void __user *addr)
 264{
 265        struct fs_disk_quota fdq;
 266        struct kqid qid;
 267        int ret;
 268
 269        if (!sb->s_qcop->get_dqblk)
 270                return -ENOSYS;
 271        qid = make_kqid(current_user_ns(), type, id);
 272        if (!qid_valid(qid))
 273                return -EINVAL;
 274        ret = sb->s_qcop->get_dqblk(sb, qid, &fdq);
 275        if (!ret && copy_to_user(addr, &fdq, sizeof(fdq)))
 276                return -EFAULT;
 277        return ret;
 278}
 279
 280/* Copy parameters and call proper function */
 281static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id,
 282                       void __user *addr, struct path *path)
 283{
 284        int ret;
 285
 286        if (type >= (XQM_COMMAND(cmd) ? XQM_MAXQUOTAS : MAXQUOTAS))
 287                return -EINVAL;
 288        if (!sb->s_qcop)
 289                return -ENOSYS;
 290
 291        ret = check_quotactl_permission(sb, type, cmd, id);
 292        if (ret < 0)
 293                return ret;
 294
 295        switch (cmd) {
 296        case Q_QUOTAON:
 297                return quota_quotaon(sb, type, cmd, id, path);
 298        case Q_QUOTAOFF:
 299                if (!sb->s_qcop->quota_off)
 300                        return -ENOSYS;
 301                return sb->s_qcop->quota_off(sb, type);
 302        case Q_GETFMT:
 303                return quota_getfmt(sb, type, addr);
 304        case Q_GETINFO:
 305                return quota_getinfo(sb, type, addr);
 306        case Q_SETINFO:
 307                return quota_setinfo(sb, type, addr);
 308        case Q_GETQUOTA:
 309                return quota_getquota(sb, type, id, addr);
 310        case Q_SETQUOTA:
 311                return quota_setquota(sb, type, id, addr);
 312        case Q_SYNC:
 313                if (!sb->s_qcop->quota_sync)
 314                        return -ENOSYS;
 315                return sb->s_qcop->quota_sync(sb, type);
 316        case Q_XQUOTAON:
 317        case Q_XQUOTAOFF:
 318        case Q_XQUOTARM:
 319                return quota_setxstate(sb, cmd, addr);
 320        case Q_XGETQSTAT:
 321                return quota_getxstate(sb, addr);
 322        case Q_XGETQSTATV:
 323                return quota_getxstatev(sb, addr);
 324        case Q_XSETQLIM:
 325                return quota_setxquota(sb, type, id, addr);
 326        case Q_XGETQUOTA:
 327                return quota_getxquota(sb, type, id, addr);
 328        case Q_XQUOTASYNC:
 329                if (sb->s_flags & MS_RDONLY)
 330                        return -EROFS;
 331                /* XFS quotas are fully coherent now, making this call a noop */
 332                return 0;
 333        default:
 334                return -EINVAL;
 335        }
 336}
 337
 338#ifdef CONFIG_BLOCK
 339
 340/* Return 1 if 'cmd' will block on frozen filesystem */
 341static int quotactl_cmd_write(int cmd)
 342{
 343        switch (cmd) {
 344        case Q_GETFMT:
 345        case Q_GETINFO:
 346        case Q_SYNC:
 347        case Q_XGETQSTAT:
 348        case Q_XGETQSTATV:
 349        case Q_XGETQUOTA:
 350        case Q_XQUOTASYNC:
 351                return 0;
 352        }
 353        return 1;
 354}
 355
 356#endif /* CONFIG_BLOCK */
 357
 358/*
 359 * look up a superblock on which quota ops will be performed
 360 * - use the name of a block device to find the superblock thereon
 361 */
 362static struct super_block *quotactl_block(const char __user *special, int cmd)
 363{
 364#ifdef CONFIG_BLOCK
 365        struct block_device *bdev;
 366        struct super_block *sb;
 367        struct filename *tmp = getname(special);
 368
 369        if (IS_ERR(tmp))
 370                return ERR_CAST(tmp);
 371        bdev = lookup_bdev(tmp->name);
 372        putname(tmp);
 373        if (IS_ERR(bdev))
 374                return ERR_CAST(bdev);
 375        if (quotactl_cmd_write(cmd))
 376                sb = get_super_thawed(bdev);
 377        else
 378                sb = get_super(bdev);
 379        bdput(bdev);
 380        if (!sb)
 381                return ERR_PTR(-ENODEV);
 382
 383        return sb;
 384#else
 385        return ERR_PTR(-ENODEV);
 386#endif
 387}
 388
 389/*
 390 * This is the system call interface. This communicates with
 391 * the user-level programs. Currently this only supports diskquota
 392 * calls. Maybe we need to add the process quotas etc. in the future,
 393 * but we probably should use rlimits for that.
 394 */
 395SYSCALL_DEFINE4(quotactl, unsigned int, cmd, const char __user *, special,
 396                qid_t, id, void __user *, addr)
 397{
 398        uint cmds, type;
 399        struct super_block *sb = NULL;
 400        struct path path, *pathp = NULL;
 401        int ret;
 402
 403        cmds = cmd >> SUBCMDSHIFT;
 404        type = cmd & SUBCMDMASK;
 405
 406        /*
 407         * As a special case Q_SYNC can be called without a specific device.
 408         * It will iterate all superblocks that have quota enabled and call
 409         * the sync action on each of them.
 410         */
 411        if (!special) {
 412                if (cmds == Q_SYNC)
 413                        return quota_sync_all(type);
 414                return -ENODEV;
 415        }
 416
 417        /*
 418         * Path for quotaon has to be resolved before grabbing superblock
 419         * because that gets s_umount sem which is also possibly needed by path
 420         * resolution (think about autofs) and thus deadlocks could arise.
 421         */
 422        if (cmds == Q_QUOTAON) {
 423                ret = user_path_at(AT_FDCWD, addr, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &path);
 424                if (ret)
 425                        pathp = ERR_PTR(ret);
 426                else
 427                        pathp = &path;
 428        }
 429
 430        sb = quotactl_block(special, cmds);
 431        if (IS_ERR(sb)) {
 432                ret = PTR_ERR(sb);
 433                goto out;
 434        }
 435
 436        ret = do_quotactl(sb, type, cmds, id, addr, pathp);
 437
 438        drop_super(sb);
 439out:
 440        if (pathp && !IS_ERR(pathp))
 441                path_put(pathp);
 442        return ret;
 443}
 444
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.