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