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 && current_euid() == id) ||
  36                    (type == GRPQUOTA && in_egroup_p(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 fs_disk_quota fdq;
 134        struct if_dqblk idq;
 135        int ret;
 136
 137        if (!sb->s_qcop->get_dqblk)
 138                return -ENOSYS;
 139        ret = sb->s_qcop->get_dqblk(sb, type, id, &fdq);
 140        if (ret)
 141                return ret;
 142        copy_to_if_dqblk(&idq, &fdq);
 143        if (copy_to_user(addr, &idq, sizeof(idq)))
 144                return -EFAULT;
 145        return 0;
 146}
 147
 148static void copy_from_if_dqblk(struct fs_disk_quota *dst, struct if_dqblk *src)
 149{
 150        dst->d_blk_hardlimit = src->dqb_bhardlimit;
 151        dst->d_blk_softlimit  = src->dqb_bsoftlimit;
 152        dst->d_bcount = src->dqb_curspace;
 153        dst->d_ino_hardlimit = src->dqb_ihardlimit;
 154        dst->d_ino_softlimit = src->dqb_isoftlimit;
 155        dst->d_icount = src->dqb_curinodes;
 156        dst->d_btimer = src->dqb_btime;
 157        dst->d_itimer = src->dqb_itime;
 158
 159        dst->d_fieldmask = 0;
 160        if (src->dqb_valid & QIF_BLIMITS)
 161                dst->d_fieldmask |= FS_DQ_BSOFT | FS_DQ_BHARD;
 162        if (src->dqb_valid & QIF_SPACE)
 163                dst->d_fieldmask |= FS_DQ_BCOUNT;
 164        if (src->dqb_valid & QIF_ILIMITS)
 165                dst->d_fieldmask |= FS_DQ_ISOFT | FS_DQ_IHARD;
 166        if (src->dqb_valid & QIF_INODES)
 167                dst->d_fieldmask |= FS_DQ_ICOUNT;
 168        if (src->dqb_valid & QIF_BTIME)
 169                dst->d_fieldmask |= FS_DQ_BTIMER;
 170        if (src->dqb_valid & QIF_ITIME)
 171                dst->d_fieldmask |= FS_DQ_ITIMER;
 172}
 173
 174static int quota_setquota(struct super_block *sb, int type, qid_t id,
 175                          void __user *addr)
 176{
 177        struct fs_disk_quota fdq;
 178        struct if_dqblk idq;
 179
 180        if (copy_from_user(&idq, addr, sizeof(idq)))
 181                return -EFAULT;
 182        if (!sb->s_qcop->set_dqblk)
 183                return -ENOSYS;
 184        copy_from_if_dqblk(&fdq, &idq);
 185        return sb->s_qcop->set_dqblk(sb, type, id, &fdq);
 186}
 187
 188static int quota_setxstate(struct super_block *sb, int cmd, void __user *addr)
 189{
 190        __u32 flags;
 191
 192        if (copy_from_user(&flags, addr, sizeof(flags)))
 193                return -EFAULT;
 194        if (!sb->s_qcop->set_xstate)
 195                return -ENOSYS;
 196        return sb->s_qcop->set_xstate(sb, flags, cmd);
 197}
 198
 199static int quota_getxstate(struct super_block *sb, void __user *addr)
 200{
 201        struct fs_quota_stat fqs;
 202        int ret;
 203
 204        if (!sb->s_qcop->get_xstate)
 205                return -ENOSYS;
 206        ret = sb->s_qcop->get_xstate(sb, &fqs);
 207        if (!ret && copy_to_user(addr, &fqs, sizeof(fqs)))
 208                return -EFAULT;
 209        return ret;
 210}
 211
 212static int quota_setxquota(struct super_block *sb, int type, qid_t id,
 213                           void __user *addr)
 214{
 215        struct fs_disk_quota fdq;
 216
 217        if (copy_from_user(&fdq, addr, sizeof(fdq)))
 218                return -EFAULT;
 219        if (!sb->s_qcop->set_dqblk)
 220                return -ENOSYS;
 221        return sb->s_qcop->set_dqblk(sb, type, id, &fdq);
 222}
 223
 224static int quota_getxquota(struct super_block *sb, int type, qid_t id,
 225                           void __user *addr)
 226{
 227        struct fs_disk_quota fdq;
 228        int ret;
 229
 230        if (!sb->s_qcop->get_dqblk)
 231                return -ENOSYS;
 232        ret = sb->s_qcop->get_dqblk(sb, type, id, &fdq);
 233        if (!ret && copy_to_user(addr, &fdq, sizeof(fdq)))
 234                return -EFAULT;
 235        return ret;
 236}
 237
 238/* Copy parameters and call proper function */
 239static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id,
 240                       void __user *addr, struct path *path)
 241{
 242        int ret;
 243
 244        if (type >= (XQM_COMMAND(cmd) ? XQM_MAXQUOTAS : MAXQUOTAS))
 245                return -EINVAL;
 246        if (!sb->s_qcop)
 247                return -ENOSYS;
 248
 249        ret = check_quotactl_permission(sb, type, cmd, id);
 250        if (ret < 0)
 251                return ret;
 252
 253        switch (cmd) {
 254        case Q_QUOTAON:
 255                return quota_quotaon(sb, type, cmd, id, path);
 256        case Q_QUOTAOFF:
 257                if (!sb->s_qcop->quota_off)
 258                        return -ENOSYS;
 259                return sb->s_qcop->quota_off(sb, type);
 260        case Q_GETFMT:
 261                return quota_getfmt(sb, type, addr);
 262        case Q_GETINFO:
 263                return quota_getinfo(sb, type, addr);
 264        case Q_SETINFO:
 265                return quota_setinfo(sb, type, addr);
 266        case Q_GETQUOTA:
 267                return quota_getquota(sb, type, id, addr);
 268        case Q_SETQUOTA:
 269                return quota_setquota(sb, type, id, addr);
 270        case Q_SYNC:
 271                if (!sb->s_qcop->quota_sync)
 272                        return -ENOSYS;
 273                return sb->s_qcop->quota_sync(sb, type);
 274        case Q_XQUOTAON:
 275        case Q_XQUOTAOFF:
 276        case Q_XQUOTARM:
 277                return quota_setxstate(sb, cmd, addr);
 278        case Q_XGETQSTAT:
 279                return quota_getxstate(sb, addr);
 280        case Q_XSETQLIM:
 281                return quota_setxquota(sb, type, id, addr);
 282        case Q_XGETQUOTA:
 283                return quota_getxquota(sb, type, id, addr);
 284        case Q_XQUOTASYNC:
 285                if (sb->s_flags & MS_RDONLY)
 286                        return -EROFS;
 287                /* XFS quotas are fully coherent now, making this call a noop */
 288                return 0;
 289        default:
 290                return -EINVAL;
 291        }
 292}
 293
 294/* Return 1 if 'cmd' will block on frozen filesystem */
 295static int quotactl_cmd_write(int cmd)
 296{
 297        switch (cmd) {
 298        case Q_GETFMT:
 299        case Q_GETINFO:
 300        case Q_SYNC:
 301        case Q_XGETQSTAT:
 302        case Q_XGETQUOTA:
 303        case Q_XQUOTASYNC:
 304                return 0;
 305        }
 306        return 1;
 307}
 308
 309/*
 310 * look up a superblock on which quota ops will be performed
 311 * - use the name of a block device to find the superblock thereon
 312 */
 313static struct super_block *quotactl_block(const char __user *special, int cmd)
 314{
 315#ifdef CONFIG_BLOCK
 316        struct block_device *bdev;
 317        struct super_block *sb;
 318        char *tmp = getname(special);
 319
 320        if (IS_ERR(tmp))
 321                return ERR_CAST(tmp);
 322        bdev = lookup_bdev(tmp);
 323        putname(tmp);
 324        if (IS_ERR(bdev))
 325                return ERR_CAST(bdev);
 326        if (quotactl_cmd_write(cmd))
 327                sb = get_super_thawed(bdev);
 328        else
 329                sb = get_super(bdev);
 330        bdput(bdev);
 331        if (!sb)
 332                return ERR_PTR(-ENODEV);
 333
 334        return sb;
 335#else
 336        return ERR_PTR(-ENODEV);
 337#endif
 338}
 339
 340/*
 341 * This is the system call interface. This communicates with
 342 * the user-level programs. Currently this only supports diskquota
 343 * calls. Maybe we need to add the process quotas etc. in the future,
 344 * but we probably should use rlimits for that.
 345 */
 346SYSCALL_DEFINE4(quotactl, unsigned int, cmd, const char __user *, special,
 347                qid_t, id, void __user *, addr)
 348{
 349        uint cmds, type;
 350        struct super_block *sb = NULL;
 351        struct path path, *pathp = NULL;
 352        int ret;
 353
 354        cmds = cmd >> SUBCMDSHIFT;
 355        type = cmd & SUBCMDMASK;
 356
 357        /*
 358         * As a special case Q_SYNC can be called without a specific device.
 359         * It will iterate all superblocks that have quota enabled and call
 360         * the sync action on each of them.
 361         */
 362        if (!special) {
 363                if (cmds == Q_SYNC)
 364                        return quota_sync_all(type);
 365                return -ENODEV;
 366        }
 367
 368        /*
 369         * Path for quotaon has to be resolved before grabbing superblock
 370         * because that gets s_umount sem which is also possibly needed by path
 371         * resolution (think about autofs) and thus deadlocks could arise.
 372         */
 373        if (cmds == Q_QUOTAON) {
 374                ret = user_path_at(AT_FDCWD, addr, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &path);
 375                if (ret)
 376                        pathp = ERR_PTR(ret);
 377                else
 378                        pathp = &path;
 379        }
 380
 381        sb = quotactl_block(special, cmds);
 382        if (IS_ERR(sb)) {
 383                ret = PTR_ERR(sb);
 384                goto out;
 385        }
 386
 387        ret = do_quotactl(sb, type, cmds, id, addr, pathp);
 388
 389        drop_super(sb);
 390out:
 391        if (pathp && !IS_ERR(pathp))
 392                path_put(pathp);
 393        return ret;
 394}
 395
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.