linux/fs/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 <asm/uaccess.h>
  13#include <linux/compat.h>
  14#include <linux/kernel.h>
  15#include <linux/security.h>
  16#include <linux/syscalls.h>
  17#include <linux/buffer_head.h>
  18#include <linux/capability.h>
  19#include <linux/quotaops.h>
  20#include <linux/types.h>
  21
  22/* Check validity of generic quotactl commands */
  23static int generic_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id)
  24{
  25        if (type >= MAXQUOTAS)
  26                return -EINVAL;
  27        if (!sb && cmd != Q_SYNC)
  28                return -ENODEV;
  29        /* Is operation supported? */
  30        if (sb && !sb->s_qcop)
  31                return -ENOSYS;
  32
  33        switch (cmd) {
  34                case Q_GETFMT:
  35                        break;
  36                case Q_QUOTAON:
  37                        if (!sb->s_qcop->quota_on)
  38                                return -ENOSYS;
  39                        break;
  40                case Q_QUOTAOFF:
  41                        if (!sb->s_qcop->quota_off)
  42                                return -ENOSYS;
  43                        break;
  44                case Q_SETINFO:
  45                        if (!sb->s_qcop->set_info)
  46                                return -ENOSYS;
  47                        break;
  48                case Q_GETINFO:
  49                        if (!sb->s_qcop->get_info)
  50                                return -ENOSYS;
  51                        break;
  52                case Q_SETQUOTA:
  53                        if (!sb->s_qcop->set_dqblk)
  54                                return -ENOSYS;
  55                        break;
  56                case Q_GETQUOTA:
  57                        if (!sb->s_qcop->get_dqblk)
  58                                return -ENOSYS;
  59                        break;
  60                case Q_SYNC:
  61                        if (sb && !sb->s_qcop->quota_sync)
  62                                return -ENOSYS;
  63                        break;
  64                default:
  65                        return -EINVAL;
  66        }
  67
  68        /* Is quota turned on for commands which need it? */
  69        switch (cmd) {
  70                case Q_GETFMT:
  71                case Q_GETINFO:
  72                case Q_QUOTAOFF:
  73                case Q_SETINFO:
  74                case Q_SETQUOTA:
  75                case Q_GETQUOTA:
  76                        /* This is just informative test so we are satisfied without a lock */
  77                        if (!sb_has_quota_enabled(sb, type))
  78                                return -ESRCH;
  79        }
  80
  81        /* Check privileges */
  82        if (cmd == Q_GETQUOTA) {
  83                if (((type == USRQUOTA && current->euid != id) ||
  84                     (type == GRPQUOTA && !in_egroup_p(id))) &&
  85                    !capable(CAP_SYS_ADMIN))
  86                        return -EPERM;
  87        }
  88        else if (cmd != Q_GETFMT && cmd != Q_SYNC && cmd != Q_GETINFO)
  89                if (!capable(CAP_SYS_ADMIN))
  90                        return -EPERM;
  91
  92        return 0;
  93}
  94
  95/* Check validity of XFS Quota Manager commands */
  96static int xqm_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id)
  97{
  98        if (type >= XQM_MAXQUOTAS)
  99                return -EINVAL;
 100        if (!sb)
 101                return -ENODEV;
 102        if (!sb->s_qcop)
 103                return -ENOSYS;
 104
 105        switch (cmd) {
 106                case Q_XQUOTAON:
 107                case Q_XQUOTAOFF:
 108                case Q_XQUOTARM:
 109                        if (!sb->s_qcop->set_xstate)
 110                                return -ENOSYS;
 111                        break;
 112                case Q_XGETQSTAT:
 113                        if (!sb->s_qcop->get_xstate)
 114                                return -ENOSYS;
 115                        break;
 116                case Q_XSETQLIM:
 117                        if (!sb->s_qcop->set_xquota)
 118                                return -ENOSYS;
 119                        break;
 120                case Q_XGETQUOTA:
 121                        if (!sb->s_qcop->get_xquota)
 122                                return -ENOSYS;
 123                        break;
 124                case Q_XQUOTASYNC:
 125                        if (!sb->s_qcop->quota_sync)
 126                                return -ENOSYS;
 127                        break;
 128                default:
 129                        return -EINVAL;
 130        }
 131
 132        /* Check privileges */
 133        if (cmd == Q_XGETQUOTA) {
 134                if (((type == XQM_USRQUOTA && current->euid != id) ||
 135                     (type == XQM_GRPQUOTA && !in_egroup_p(id))) &&
 136                     !capable(CAP_SYS_ADMIN))
 137                        return -EPERM;
 138        } else if (cmd != Q_XGETQSTAT && cmd != Q_XQUOTASYNC) {
 139                if (!capable(CAP_SYS_ADMIN))
 140                        return -EPERM;
 141        }
 142
 143        return 0;
 144}
 145
 146static int check_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id)
 147{
 148        int error;
 149
 150        if (XQM_COMMAND(cmd))
 151                error = xqm_quotactl_valid(sb, type, cmd, id);
 152        else
 153                error = generic_quotactl_valid(sb, type, cmd, id);
 154        if (!error)
 155                error = security_quotactl(cmd, type, id, sb);
 156        return error;
 157}
 158
 159static void quota_sync_sb(struct super_block *sb, int type)
 160{
 161        int cnt;
 162
 163        sb->s_qcop->quota_sync(sb, type);
 164        /* This is not very clever (and fast) but currently I don't know about
 165         * any other simple way of getting quota data to disk and we must get
 166         * them there for userspace to be visible... */
 167        if (sb->s_op->sync_fs)
 168                sb->s_op->sync_fs(sb, 1);
 169        sync_blockdev(sb->s_bdev);
 170
 171        /*
 172         * Now when everything is written we can discard the pagecache so
 173         * that userspace sees the changes.
 174         */
 175        mutex_lock(&sb_dqopt(sb)->dqonoff_mutex);
 176        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
 177                if (type != -1 && cnt != type)
 178                        continue;
 179                if (!sb_has_quota_enabled(sb, cnt))
 180                        continue;
 181                mutex_lock_nested(&sb_dqopt(sb)->files[cnt]->i_mutex, I_MUTEX_QUOTA);
 182                truncate_inode_pages(&sb_dqopt(sb)->files[cnt]->i_data, 0);
 183                mutex_unlock(&sb_dqopt(sb)->files[cnt]->i_mutex);
 184        }
 185        mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
 186}
 187
 188void sync_dquots(struct super_block *sb, int type)
 189{
 190        int cnt, dirty;
 191
 192        if (sb) {
 193                if (sb->s_qcop->quota_sync)
 194                        quota_sync_sb(sb, type);
 195                return;
 196        }
 197
 198        spin_lock(&sb_lock);
 199restart:
 200        list_for_each_entry(sb, &super_blocks, s_list) {
 201                /* This test just improves performance so it needn't be reliable... */
 202                for (cnt = 0, dirty = 0; cnt < MAXQUOTAS; cnt++)
 203                        if ((type == cnt || type == -1) && sb_has_quota_enabled(sb, cnt)
 204                            && info_any_dirty(&sb_dqopt(sb)->info[cnt]))
 205                                dirty = 1;
 206                if (!dirty)
 207                        continue;
 208                sb->s_count++;
 209                spin_unlock(&sb_lock);
 210                down_read(&sb->s_umount);
 211                if (sb->s_root && sb->s_qcop->quota_sync)
 212                        quota_sync_sb(sb, type);
 213                up_read(&sb->s_umount);
 214                spin_lock(&sb_lock);
 215                if (__put_super_and_need_restart(sb))
 216                        goto restart;
 217        }
 218        spin_unlock(&sb_lock);
 219}
 220
 221/* Copy parameters and call proper function */
 222static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, void __user *addr)
 223{
 224        int ret;
 225
 226        switch (cmd) {
 227                case Q_QUOTAON: {
 228                        char *pathname;
 229
 230                        if (IS_ERR(pathname = getname(addr)))
 231                                return PTR_ERR(pathname);
 232                        ret = sb->s_qcop->quota_on(sb, type, id, pathname);
 233                        putname(pathname);
 234                        return ret;
 235                }
 236                case Q_QUOTAOFF:
 237                        return sb->s_qcop->quota_off(sb, type);
 238
 239                case Q_GETFMT: {
 240                        __u32 fmt;
 241
 242                        down_read(&sb_dqopt(sb)->dqptr_sem);
 243                        if (!sb_has_quota_enabled(sb, type)) {
 244                                up_read(&sb_dqopt(sb)->dqptr_sem);
 245                                return -ESRCH;
 246                        }
 247                        fmt = sb_dqopt(sb)->info[type].dqi_format->qf_fmt_id;
 248                        up_read(&sb_dqopt(sb)->dqptr_sem);
 249                        if (copy_to_user(addr, &fmt, sizeof(fmt)))
 250                                return -EFAULT;
 251                        return 0;
 252                }
 253                case Q_GETINFO: {
 254                        struct if_dqinfo info;
 255
 256                        if ((ret = sb->s_qcop->get_info(sb, type, &info)))
 257                                return ret;
 258                        if (copy_to_user(addr, &info, sizeof(info)))
 259                                return -EFAULT;
 260                        return 0;
 261                }
 262                case Q_SETINFO: {
 263                        struct if_dqinfo info;
 264
 265                        if (copy_from_user(&info, addr, sizeof(info)))
 266                                return -EFAULT;
 267                        return sb->s_qcop->set_info(sb, type, &info);
 268                }
 269                case Q_GETQUOTA: {
 270                        struct if_dqblk idq;
 271
 272                        if ((ret = sb->s_qcop->get_dqblk(sb, type, id, &idq)))
 273                                return ret;
 274                        if (copy_to_user(addr, &idq, sizeof(idq)))
 275                                return -EFAULT;
 276                        return 0;
 277                }
 278                case Q_SETQUOTA: {
 279                        struct if_dqblk idq;
 280
 281                        if (copy_from_user(&idq, addr, sizeof(idq)))
 282                                return -EFAULT;
 283                        return sb->s_qcop->set_dqblk(sb, type, id, &idq);
 284                }
 285                case Q_SYNC:
 286                        sync_dquots(sb, type);
 287                        return 0;
 288
 289                case Q_XQUOTAON:
 290                case Q_XQUOTAOFF:
 291                case Q_XQUOTARM: {
 292                        __u32 flags;
 293
 294                        if (copy_from_user(&flags, addr, sizeof(flags)))
 295                                return -EFAULT;
 296                        return sb->s_qcop->set_xstate(sb, flags, cmd);
 297                }
 298                case Q_XGETQSTAT: {
 299                        struct fs_quota_stat fqs;
 300                
 301                        if ((ret = sb->s_qcop->get_xstate(sb, &fqs)))
 302                                return ret;
 303                        if (copy_to_user(addr, &fqs, sizeof(fqs)))
 304                                return -EFAULT;
 305                        return 0;
 306                }
 307                case Q_XSETQLIM: {
 308                        struct fs_disk_quota fdq;
 309
 310                        if (copy_from_user(&fdq, addr, sizeof(fdq)))
 311                                return -EFAULT;
 312                       return sb->s_qcop->set_xquota(sb, type, id, &fdq);
 313                }
 314                case Q_XGETQUOTA: {
 315                        struct fs_disk_quota fdq;
 316
 317                        if ((ret = sb->s_qcop->get_xquota(sb, type, id, &fdq)))
 318                                return ret;
 319                        if (copy_to_user(addr, &fdq, sizeof(fdq)))
 320                                return -EFAULT;
 321                        return 0;
 322                }
 323                case Q_XQUOTASYNC:
 324                        return sb->s_qcop->quota_sync(sb, type);
 325                /* We never reach here unless validity check is broken */
 326                default:
 327                        BUG();
 328        }
 329        return 0;
 330}
 331
 332/*
 333 * look up a superblock on which quota ops will be performed
 334 * - use the name of a block device to find the superblock thereon
 335 */
 336static inline struct super_block *quotactl_block(const char __user *special)
 337{
 338#ifdef CONFIG_BLOCK
 339        struct block_device *bdev;
 340        struct super_block *sb;
 341        char *tmp = getname(special);
 342
 343        if (IS_ERR(tmp))
 344                return ERR_CAST(tmp);
 345        bdev = lookup_bdev(tmp);
 346        putname(tmp);
 347        if (IS_ERR(bdev))
 348                return ERR_CAST(bdev);
 349        sb = get_super(bdev);
 350        bdput(bdev);
 351        if (!sb)
 352                return ERR_PTR(-ENODEV);
 353
 354        return sb;
 355#else
 356        return ERR_PTR(-ENODEV);
 357#endif
 358}
 359
 360/*
 361 * This is the system call interface. This communicates with
 362 * the user-level programs. Currently this only supports diskquota
 363 * calls. Maybe we need to add the process quotas etc. in the future,
 364 * but we probably should use rlimits for that.
 365 */
 366asmlinkage long sys_quotactl(unsigned int cmd, const char __user *special, qid_t id, void __user *addr)
 367{
 368        uint cmds, type;
 369        struct super_block *sb = NULL;
 370        int ret;
 371
 372        cmds = cmd >> SUBCMDSHIFT;
 373        type = cmd & SUBCMDMASK;
 374
 375        if (cmds != Q_SYNC || special) {
 376                sb = quotactl_block(special);
 377                if (IS_ERR(sb))
 378                        return PTR_ERR(sb);
 379        }
 380
 381        ret = check_quotactl_valid(sb, type, cmds, id);
 382        if (ret >= 0)
 383                ret = do_quotactl(sb, type, cmds, id, addr);
 384        if (sb)
 385                drop_super(sb);
 386
 387        return ret;
 388}
 389
 390#if defined(CONFIG_COMPAT_FOR_U64_ALIGNMENT)
 391/*
 392 * This code works only for 32 bit quota tools over 64 bit OS (x86_64, ia64)
 393 * and is necessary due to alignment problems.
 394 */
 395struct compat_if_dqblk {
 396        compat_u64 dqb_bhardlimit;
 397        compat_u64 dqb_bsoftlimit;
 398        compat_u64 dqb_curspace;
 399        compat_u64 dqb_ihardlimit;
 400        compat_u64 dqb_isoftlimit;
 401        compat_u64 dqb_curinodes;
 402        compat_u64 dqb_btime;
 403        compat_u64 dqb_itime;
 404        compat_uint_t dqb_valid;
 405};
 406
 407/* XFS structures */
 408struct compat_fs_qfilestat {
 409        compat_u64 dqb_bhardlimit;
 410        compat_u64 qfs_nblks;
 411        compat_uint_t qfs_nextents;
 412};
 413
 414struct compat_fs_quota_stat {
 415        __s8            qs_version;
 416        __u16           qs_flags;
 417        __s8            qs_pad;
 418        struct compat_fs_qfilestat      qs_uquota;
 419        struct compat_fs_qfilestat      qs_gquota;
 420        compat_uint_t   qs_incoredqs;
 421        compat_int_t    qs_btimelimit;
 422        compat_int_t    qs_itimelimit;
 423        compat_int_t    qs_rtbtimelimit;
 424        __u16           qs_bwarnlimit;
 425        __u16           qs_iwarnlimit;
 426};
 427
 428asmlinkage long sys32_quotactl(unsigned int cmd, const char __user *special,
 429                                                qid_t id, void __user *addr)
 430{
 431        unsigned int cmds;
 432        struct if_dqblk __user *dqblk;
 433        struct compat_if_dqblk __user *compat_dqblk;
 434        struct fs_quota_stat __user *fsqstat;
 435        struct compat_fs_quota_stat __user *compat_fsqstat;
 436        compat_uint_t data;
 437        u16 xdata;
 438        long ret;
 439
 440        cmds = cmd >> SUBCMDSHIFT;
 441
 442        switch (cmds) {
 443        case Q_GETQUOTA:
 444                dqblk = compat_alloc_user_space(sizeof(struct if_dqblk));
 445                compat_dqblk = addr;
 446                ret = sys_quotactl(cmd, special, id, dqblk);
 447                if (ret)
 448                        break;
 449                if (copy_in_user(compat_dqblk, dqblk, sizeof(*compat_dqblk)) ||
 450                        get_user(data, &dqblk->dqb_valid) ||
 451                        put_user(data, &compat_dqblk->dqb_valid))
 452                        ret = -EFAULT;
 453                break;
 454        case Q_SETQUOTA:
 455                dqblk = compat_alloc_user_space(sizeof(struct if_dqblk));
 456                compat_dqblk = addr;
 457                ret = -EFAULT;
 458                if (copy_in_user(dqblk, compat_dqblk, sizeof(*compat_dqblk)) ||
 459                        get_user(data, &compat_dqblk->dqb_valid) ||
 460                        put_user(data, &dqblk->dqb_valid))
 461                        break;
 462                ret = sys_quotactl(cmd, special, id, dqblk);
 463                break;
 464        case Q_XGETQSTAT:
 465                fsqstat = compat_alloc_user_space(sizeof(struct fs_quota_stat));
 466                compat_fsqstat = addr;
 467                ret = sys_quotactl(cmd, special, id, fsqstat);
 468                if (ret)
 469                        break;
 470                ret = -EFAULT;
 471                /* Copying qs_version, qs_flags, qs_pad */
 472                if (copy_in_user(compat_fsqstat, fsqstat,
 473                        offsetof(struct compat_fs_quota_stat, qs_uquota)))
 474                        break;
 475                /* Copying qs_uquota */
 476                if (copy_in_user(&compat_fsqstat->qs_uquota,
 477                        &fsqstat->qs_uquota,
 478                        sizeof(compat_fsqstat->qs_uquota)) ||
 479                        get_user(data, &fsqstat->qs_uquota.qfs_nextents) ||
 480                        put_user(data, &compat_fsqstat->qs_uquota.qfs_nextents))
 481                        break;
 482                /* Copying qs_gquota */
 483                if (copy_in_user(&compat_fsqstat->qs_gquota,
 484                        &fsqstat->qs_gquota,
 485                        sizeof(compat_fsqstat->qs_gquota)) ||
 486                        get_user(data, &fsqstat->qs_gquota.qfs_nextents) ||
 487                        put_user(data, &compat_fsqstat->qs_gquota.qfs_nextents))
 488                        break;
 489                /* Copying the rest */
 490                if (copy_in_user(&compat_fsqstat->qs_incoredqs,
 491                        &fsqstat->qs_incoredqs,
 492                        sizeof(struct compat_fs_quota_stat) -
 493                        offsetof(struct compat_fs_quota_stat, qs_incoredqs)) ||
 494                        get_user(xdata, &fsqstat->qs_iwarnlimit) ||
 495                        put_user(xdata, &compat_fsqstat->qs_iwarnlimit))
 496                        break;
 497                ret = 0;
 498                break;
 499        default:
 500                ret = sys_quotactl(cmd, special, id, addr);
 501        }
 502        return ret;
 503}
 504#endif
 505
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.