linux/fs/quota/compat.c
<<
>>
Prefs
   1
   2#include <linux/syscalls.h>
   3#include <linux/compat.h>
   4#include <linux/quotaops.h>
   5
   6/*
   7 * This code works only for 32 bit quota tools over 64 bit OS (x86_64, ia64)
   8 * and is necessary due to alignment problems.
   9 */
  10struct compat_if_dqblk {
  11        compat_u64 dqb_bhardlimit;
  12        compat_u64 dqb_bsoftlimit;
  13        compat_u64 dqb_curspace;
  14        compat_u64 dqb_ihardlimit;
  15        compat_u64 dqb_isoftlimit;
  16        compat_u64 dqb_curinodes;
  17        compat_u64 dqb_btime;
  18        compat_u64 dqb_itime;
  19        compat_uint_t dqb_valid;
  20};
  21
  22/* XFS structures */
  23struct compat_fs_qfilestat {
  24        compat_u64 dqb_bhardlimit;
  25        compat_u64 qfs_nblks;
  26        compat_uint_t qfs_nextents;
  27};
  28
  29struct compat_fs_quota_stat {
  30        __s8            qs_version;
  31        __u16           qs_flags;
  32        __s8            qs_pad;
  33        struct compat_fs_qfilestat      qs_uquota;
  34        struct compat_fs_qfilestat      qs_gquota;
  35        compat_uint_t   qs_incoredqs;
  36        compat_int_t    qs_btimelimit;
  37        compat_int_t    qs_itimelimit;
  38        compat_int_t    qs_rtbtimelimit;
  39        __u16           qs_bwarnlimit;
  40        __u16           qs_iwarnlimit;
  41};
  42
  43asmlinkage long sys32_quotactl(unsigned int cmd, const char __user *special,
  44                                                qid_t id, void __user *addr)
  45{
  46        unsigned int cmds;
  47        struct if_dqblk __user *dqblk;
  48        struct compat_if_dqblk __user *compat_dqblk;
  49        struct fs_quota_stat __user *fsqstat;
  50        struct compat_fs_quota_stat __user *compat_fsqstat;
  51        compat_uint_t data;
  52        u16 xdata;
  53        long ret;
  54
  55        cmds = cmd >> SUBCMDSHIFT;
  56
  57        switch (cmds) {
  58        case Q_GETQUOTA:
  59                dqblk = compat_alloc_user_space(sizeof(struct if_dqblk));
  60                compat_dqblk = addr;
  61                ret = sys_quotactl(cmd, special, id, dqblk);
  62                if (ret)
  63                        break;
  64                if (copy_in_user(compat_dqblk, dqblk, sizeof(*compat_dqblk)) ||
  65                        get_user(data, &dqblk->dqb_valid) ||
  66                        put_user(data, &compat_dqblk->dqb_valid))
  67                        ret = -EFAULT;
  68                break;
  69        case Q_SETQUOTA:
  70                dqblk = compat_alloc_user_space(sizeof(struct if_dqblk));
  71                compat_dqblk = addr;
  72                ret = -EFAULT;
  73                if (copy_in_user(dqblk, compat_dqblk, sizeof(*compat_dqblk)) ||
  74                        get_user(data, &compat_dqblk->dqb_valid) ||
  75                        put_user(data, &dqblk->dqb_valid))
  76                        break;
  77                ret = sys_quotactl(cmd, special, id, dqblk);
  78                break;
  79        case Q_XGETQSTAT:
  80                fsqstat = compat_alloc_user_space(sizeof(struct fs_quota_stat));
  81                compat_fsqstat = addr;
  82                ret = sys_quotactl(cmd, special, id, fsqstat);
  83                if (ret)
  84                        break;
  85                ret = -EFAULT;
  86                /* Copying qs_version, qs_flags, qs_pad */
  87                if (copy_in_user(compat_fsqstat, fsqstat,
  88                        offsetof(struct compat_fs_quota_stat, qs_uquota)))
  89                        break;
  90                /* Copying qs_uquota */
  91                if (copy_in_user(&compat_fsqstat->qs_uquota,
  92                        &fsqstat->qs_uquota,
  93                        sizeof(compat_fsqstat->qs_uquota)) ||
  94                        get_user(data, &fsqstat->qs_uquota.qfs_nextents) ||
  95                        put_user(data, &compat_fsqstat->qs_uquota.qfs_nextents))
  96                        break;
  97                /* Copying qs_gquota */
  98                if (copy_in_user(&compat_fsqstat->qs_gquota,
  99                        &fsqstat->qs_gquota,
 100                        sizeof(compat_fsqstat->qs_gquota)) ||
 101                        get_user(data, &fsqstat->qs_gquota.qfs_nextents) ||
 102                        put_user(data, &compat_fsqstat->qs_gquota.qfs_nextents))
 103                        break;
 104                /* Copying the rest */
 105                if (copy_in_user(&compat_fsqstat->qs_incoredqs,
 106                        &fsqstat->qs_incoredqs,
 107                        sizeof(struct compat_fs_quota_stat) -
 108                        offsetof(struct compat_fs_quota_stat, qs_incoredqs)) ||
 109                        get_user(xdata, &fsqstat->qs_iwarnlimit) ||
 110                        put_user(xdata, &compat_fsqstat->qs_iwarnlimit))
 111                        break;
 112                ret = 0;
 113                break;
 114        default:
 115                ret = sys_quotactl(cmd, special, id, addr);
 116        }
 117        return ret;
 118}
 119