1884d179dSJan Kara /* 2884d179dSJan Kara * Quota code necessary even when VFS quota support is not compiled 3884d179dSJan Kara * into the kernel. The interesting stuff is over in dquot.c, here 4884d179dSJan Kara * we have symbols for initial quotactl(2) handling, the sysctl(2) 5884d179dSJan Kara * variables, etc - things needed even when quota support disabled. 6884d179dSJan Kara */ 7884d179dSJan Kara 8884d179dSJan Kara #include <linux/fs.h> 9884d179dSJan Kara #include <linux/namei.h> 10884d179dSJan Kara #include <linux/slab.h> 11884d179dSJan Kara #include <asm/current.h> 12884d179dSJan Kara #include <asm/uaccess.h> 13884d179dSJan Kara #include <linux/compat.h> 14884d179dSJan Kara #include <linux/kernel.h> 15884d179dSJan Kara #include <linux/security.h> 16884d179dSJan Kara #include <linux/syscalls.h> 17884d179dSJan Kara #include <linux/buffer_head.h> 18884d179dSJan Kara #include <linux/capability.h> 19884d179dSJan Kara #include <linux/quotaops.h> 20884d179dSJan Kara #include <linux/types.h> 2186e931a3SSteven Whitehouse #include <net/netlink.h> 2286e931a3SSteven Whitehouse #include <net/genetlink.h> 23884d179dSJan Kara 24884d179dSJan Kara /* Check validity of generic quotactl commands */ 25268157baSJan Kara static int generic_quotactl_valid(struct super_block *sb, int type, int cmd, 26268157baSJan Kara qid_t id) 27884d179dSJan Kara { 28884d179dSJan Kara if (type >= MAXQUOTAS) 29884d179dSJan Kara return -EINVAL; 30884d179dSJan Kara if (!sb && cmd != Q_SYNC) 31884d179dSJan Kara return -ENODEV; 32884d179dSJan Kara /* Is operation supported? */ 33884d179dSJan Kara if (sb && !sb->s_qcop) 34884d179dSJan Kara return -ENOSYS; 35884d179dSJan Kara 36884d179dSJan Kara switch (cmd) { 37884d179dSJan Kara case Q_GETFMT: 38884d179dSJan Kara break; 39884d179dSJan Kara case Q_QUOTAON: 40884d179dSJan Kara if (!sb->s_qcop->quota_on) 41884d179dSJan Kara return -ENOSYS; 42884d179dSJan Kara break; 43884d179dSJan Kara case Q_QUOTAOFF: 44884d179dSJan Kara if (!sb->s_qcop->quota_off) 45884d179dSJan Kara return -ENOSYS; 46884d179dSJan Kara break; 47884d179dSJan Kara case Q_SETINFO: 48884d179dSJan Kara if (!sb->s_qcop->set_info) 49884d179dSJan Kara return -ENOSYS; 50884d179dSJan Kara break; 51884d179dSJan Kara case Q_GETINFO: 52884d179dSJan Kara if (!sb->s_qcop->get_info) 53884d179dSJan Kara return -ENOSYS; 54884d179dSJan Kara break; 55884d179dSJan Kara case Q_SETQUOTA: 56884d179dSJan Kara if (!sb->s_qcop->set_dqblk) 57884d179dSJan Kara return -ENOSYS; 58884d179dSJan Kara break; 59884d179dSJan Kara case Q_GETQUOTA: 60884d179dSJan Kara if (!sb->s_qcop->get_dqblk) 61884d179dSJan Kara return -ENOSYS; 62884d179dSJan Kara break; 63884d179dSJan Kara case Q_SYNC: 64884d179dSJan Kara if (sb && !sb->s_qcop->quota_sync) 65884d179dSJan Kara return -ENOSYS; 66884d179dSJan Kara break; 67884d179dSJan Kara default: 68884d179dSJan Kara return -EINVAL; 69884d179dSJan Kara } 70884d179dSJan Kara 71884d179dSJan Kara /* Is quota turned on for commands which need it? */ 72884d179dSJan Kara switch (cmd) { 73884d179dSJan Kara case Q_GETFMT: 74884d179dSJan Kara case Q_GETINFO: 75884d179dSJan Kara case Q_SETINFO: 76884d179dSJan Kara case Q_SETQUOTA: 77884d179dSJan Kara case Q_GETQUOTA: 78268157baSJan Kara /* This is just an informative test so we are satisfied 79268157baSJan Kara * without the lock */ 80884d179dSJan Kara if (!sb_has_quota_active(sb, type)) 81884d179dSJan Kara return -ESRCH; 82884d179dSJan Kara } 83884d179dSJan Kara 84884d179dSJan Kara /* Check privileges */ 85884d179dSJan Kara if (cmd == Q_GETQUOTA) { 86884d179dSJan Kara if (((type == USRQUOTA && current_euid() != id) || 87884d179dSJan Kara (type == GRPQUOTA && !in_egroup_p(id))) && 88884d179dSJan Kara !capable(CAP_SYS_ADMIN)) 89884d179dSJan Kara return -EPERM; 90884d179dSJan Kara } 91884d179dSJan Kara else if (cmd != Q_GETFMT && cmd != Q_SYNC && cmd != Q_GETINFO) 92884d179dSJan Kara if (!capable(CAP_SYS_ADMIN)) 93884d179dSJan Kara return -EPERM; 94884d179dSJan Kara 95884d179dSJan Kara return 0; 96884d179dSJan Kara } 97884d179dSJan Kara 98884d179dSJan Kara /* Check validity of XFS Quota Manager commands */ 99268157baSJan Kara static int xqm_quotactl_valid(struct super_block *sb, int type, int cmd, 100268157baSJan Kara qid_t id) 101884d179dSJan Kara { 102884d179dSJan Kara if (type >= XQM_MAXQUOTAS) 103884d179dSJan Kara return -EINVAL; 104884d179dSJan Kara if (!sb) 105884d179dSJan Kara return -ENODEV; 106884d179dSJan Kara if (!sb->s_qcop) 107884d179dSJan Kara return -ENOSYS; 108884d179dSJan Kara 109884d179dSJan Kara switch (cmd) { 110884d179dSJan Kara case Q_XQUOTAON: 111884d179dSJan Kara case Q_XQUOTAOFF: 112884d179dSJan Kara case Q_XQUOTARM: 113884d179dSJan Kara if (!sb->s_qcop->set_xstate) 114884d179dSJan Kara return -ENOSYS; 115884d179dSJan Kara break; 116884d179dSJan Kara case Q_XGETQSTAT: 117884d179dSJan Kara if (!sb->s_qcop->get_xstate) 118884d179dSJan Kara return -ENOSYS; 119884d179dSJan Kara break; 120884d179dSJan Kara case Q_XSETQLIM: 121884d179dSJan Kara if (!sb->s_qcop->set_xquota) 122884d179dSJan Kara return -ENOSYS; 123884d179dSJan Kara break; 124884d179dSJan Kara case Q_XGETQUOTA: 125884d179dSJan Kara if (!sb->s_qcop->get_xquota) 126884d179dSJan Kara return -ENOSYS; 127884d179dSJan Kara break; 128884d179dSJan Kara case Q_XQUOTASYNC: 129884d179dSJan Kara if (!sb->s_qcop->quota_sync) 130884d179dSJan Kara return -ENOSYS; 131884d179dSJan Kara break; 132884d179dSJan Kara default: 133884d179dSJan Kara return -EINVAL; 134884d179dSJan Kara } 135884d179dSJan Kara 136884d179dSJan Kara /* Check privileges */ 137884d179dSJan Kara if (cmd == Q_XGETQUOTA) { 138884d179dSJan Kara if (((type == XQM_USRQUOTA && current_euid() != id) || 139884d179dSJan Kara (type == XQM_GRPQUOTA && !in_egroup_p(id))) && 140884d179dSJan Kara !capable(CAP_SYS_ADMIN)) 141884d179dSJan Kara return -EPERM; 142884d179dSJan Kara } else if (cmd != Q_XGETQSTAT && cmd != Q_XQUOTASYNC) { 143884d179dSJan Kara if (!capable(CAP_SYS_ADMIN)) 144884d179dSJan Kara return -EPERM; 145884d179dSJan Kara } 146884d179dSJan Kara 147884d179dSJan Kara return 0; 148884d179dSJan Kara } 149884d179dSJan Kara 150268157baSJan Kara static int check_quotactl_valid(struct super_block *sb, int type, int cmd, 151268157baSJan Kara qid_t id) 152884d179dSJan Kara { 153884d179dSJan Kara int error; 154884d179dSJan Kara 155884d179dSJan Kara if (XQM_COMMAND(cmd)) 156884d179dSJan Kara error = xqm_quotactl_valid(sb, type, cmd, id); 157884d179dSJan Kara else 158884d179dSJan Kara error = generic_quotactl_valid(sb, type, cmd, id); 159884d179dSJan Kara if (!error) 160884d179dSJan Kara error = security_quotactl(cmd, type, id, sb); 161884d179dSJan Kara return error; 162884d179dSJan Kara } 163884d179dSJan Kara 164850b201bSChristoph Hellwig #ifdef CONFIG_QUOTA 165850b201bSChristoph Hellwig void sync_quota_sb(struct super_block *sb, int type) 166884d179dSJan Kara { 167884d179dSJan Kara int cnt; 168884d179dSJan Kara 169850b201bSChristoph Hellwig if (!sb->s_qcop->quota_sync) 170850b201bSChristoph Hellwig return; 171850b201bSChristoph Hellwig 172884d179dSJan Kara sb->s_qcop->quota_sync(sb, type); 173884d179dSJan Kara 174884d179dSJan Kara if (sb_dqopt(sb)->flags & DQUOT_QUOTA_SYS_FILE) 175884d179dSJan Kara return; 176884d179dSJan Kara /* This is not very clever (and fast) but currently I don't know about 177884d179dSJan Kara * any other simple way of getting quota data to disk and we must get 178884d179dSJan Kara * them there for userspace to be visible... */ 179884d179dSJan Kara if (sb->s_op->sync_fs) 180884d179dSJan Kara sb->s_op->sync_fs(sb, 1); 181884d179dSJan Kara sync_blockdev(sb->s_bdev); 182884d179dSJan Kara 183884d179dSJan Kara /* 184884d179dSJan Kara * Now when everything is written we can discard the pagecache so 185884d179dSJan Kara * that userspace sees the changes. 186884d179dSJan Kara */ 187884d179dSJan Kara mutex_lock(&sb_dqopt(sb)->dqonoff_mutex); 188884d179dSJan Kara for (cnt = 0; cnt < MAXQUOTAS; cnt++) { 189884d179dSJan Kara if (type != -1 && cnt != type) 190884d179dSJan Kara continue; 191884d179dSJan Kara if (!sb_has_quota_active(sb, cnt)) 192884d179dSJan Kara continue; 193268157baSJan Kara mutex_lock_nested(&sb_dqopt(sb)->files[cnt]->i_mutex, 194268157baSJan Kara I_MUTEX_QUOTA); 195884d179dSJan Kara truncate_inode_pages(&sb_dqopt(sb)->files[cnt]->i_data, 0); 196884d179dSJan Kara mutex_unlock(&sb_dqopt(sb)->files[cnt]->i_mutex); 197884d179dSJan Kara } 198884d179dSJan Kara mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex); 199884d179dSJan Kara } 200850b201bSChristoph Hellwig #endif 201884d179dSJan Kara 202850b201bSChristoph Hellwig static void sync_dquots(int type) 203884d179dSJan Kara { 204850b201bSChristoph Hellwig struct super_block *sb; 205884d179dSJan Kara int cnt; 206884d179dSJan Kara 207884d179dSJan Kara spin_lock(&sb_lock); 208884d179dSJan Kara restart: 209884d179dSJan Kara list_for_each_entry(sb, &super_blocks, s_list) { 210268157baSJan Kara /* This test just improves performance so it needn't be 211268157baSJan Kara * reliable... */ 212884d179dSJan Kara for (cnt = 0; cnt < MAXQUOTAS; cnt++) { 213884d179dSJan Kara if (type != -1 && type != cnt) 214884d179dSJan Kara continue; 215884d179dSJan Kara if (!sb_has_quota_active(sb, cnt)) 216884d179dSJan Kara continue; 217884d179dSJan Kara if (!info_dirty(&sb_dqopt(sb)->info[cnt]) && 218884d179dSJan Kara list_empty(&sb_dqopt(sb)->info[cnt].dqi_dirty_list)) 219884d179dSJan Kara continue; 220884d179dSJan Kara break; 221884d179dSJan Kara } 222884d179dSJan Kara if (cnt == MAXQUOTAS) 223884d179dSJan Kara continue; 224884d179dSJan Kara sb->s_count++; 225884d179dSJan Kara spin_unlock(&sb_lock); 226884d179dSJan Kara down_read(&sb->s_umount); 227850b201bSChristoph Hellwig if (sb->s_root) 228850b201bSChristoph Hellwig sync_quota_sb(sb, type); 229884d179dSJan Kara up_read(&sb->s_umount); 230884d179dSJan Kara spin_lock(&sb_lock); 231884d179dSJan Kara if (__put_super_and_need_restart(sb)) 232884d179dSJan Kara goto restart; 233884d179dSJan Kara } 234884d179dSJan Kara spin_unlock(&sb_lock); 235884d179dSJan Kara } 236884d179dSJan Kara 237*c411e5f6SChristoph Hellwig static int quota_quotaon(struct super_block *sb, int type, int cmd, qid_t id, 238268157baSJan Kara void __user *addr) 239884d179dSJan Kara { 240884d179dSJan Kara char *pathname; 241*c411e5f6SChristoph Hellwig int ret; 242884d179dSJan Kara 243268157baSJan Kara pathname = getname(addr); 244268157baSJan Kara if (IS_ERR(pathname)) 245884d179dSJan Kara return PTR_ERR(pathname); 246884d179dSJan Kara ret = sb->s_qcop->quota_on(sb, type, id, pathname, 0); 247884d179dSJan Kara putname(pathname); 248884d179dSJan Kara return ret; 249884d179dSJan Kara } 250884d179dSJan Kara 251*c411e5f6SChristoph Hellwig static int quota_getfmt(struct super_block *sb, int type, void __user *addr) 252*c411e5f6SChristoph Hellwig { 253884d179dSJan Kara __u32 fmt; 254884d179dSJan Kara 255884d179dSJan Kara down_read(&sb_dqopt(sb)->dqptr_sem); 256884d179dSJan Kara if (!sb_has_quota_active(sb, type)) { 257884d179dSJan Kara up_read(&sb_dqopt(sb)->dqptr_sem); 258884d179dSJan Kara return -ESRCH; 259884d179dSJan Kara } 260884d179dSJan Kara fmt = sb_dqopt(sb)->info[type].dqi_format->qf_fmt_id; 261884d179dSJan Kara up_read(&sb_dqopt(sb)->dqptr_sem); 262884d179dSJan Kara if (copy_to_user(addr, &fmt, sizeof(fmt))) 263884d179dSJan Kara return -EFAULT; 264884d179dSJan Kara return 0; 265884d179dSJan Kara } 266*c411e5f6SChristoph Hellwig 267*c411e5f6SChristoph Hellwig static int quota_getinfo(struct super_block *sb, int type, void __user *addr) 268*c411e5f6SChristoph Hellwig { 269884d179dSJan Kara struct if_dqinfo info; 270*c411e5f6SChristoph Hellwig int ret; 271884d179dSJan Kara 272268157baSJan Kara ret = sb->s_qcop->get_info(sb, type, &info); 273*c411e5f6SChristoph Hellwig if (!ret && copy_to_user(addr, &info, sizeof(info))) 274884d179dSJan Kara return -EFAULT; 275*c411e5f6SChristoph Hellwig return ret; 276884d179dSJan Kara } 277*c411e5f6SChristoph Hellwig 278*c411e5f6SChristoph Hellwig static int quota_setinfo(struct super_block *sb, int type, void __user *addr) 279*c411e5f6SChristoph Hellwig { 280884d179dSJan Kara struct if_dqinfo info; 281884d179dSJan Kara 282884d179dSJan Kara if (copy_from_user(&info, addr, sizeof(info))) 283884d179dSJan Kara return -EFAULT; 284884d179dSJan Kara return sb->s_qcop->set_info(sb, type, &info); 285884d179dSJan Kara } 286*c411e5f6SChristoph Hellwig 287*c411e5f6SChristoph Hellwig static int quota_getquota(struct super_block *sb, int type, qid_t id, 288*c411e5f6SChristoph Hellwig void __user *addr) 289*c411e5f6SChristoph Hellwig { 290884d179dSJan Kara struct if_dqblk idq; 291*c411e5f6SChristoph Hellwig int ret; 292884d179dSJan Kara 293268157baSJan Kara ret = sb->s_qcop->get_dqblk(sb, type, id, &idq); 294268157baSJan Kara if (ret) 295884d179dSJan Kara return ret; 296884d179dSJan Kara if (copy_to_user(addr, &idq, sizeof(idq))) 297884d179dSJan Kara return -EFAULT; 298884d179dSJan Kara return 0; 299884d179dSJan Kara } 300*c411e5f6SChristoph Hellwig 301*c411e5f6SChristoph Hellwig static int quota_setquota(struct super_block *sb, int type, qid_t id, 302*c411e5f6SChristoph Hellwig void __user *addr) 303*c411e5f6SChristoph Hellwig { 304884d179dSJan Kara struct if_dqblk idq; 305884d179dSJan Kara 306884d179dSJan Kara if (copy_from_user(&idq, addr, sizeof(idq))) 307884d179dSJan Kara return -EFAULT; 308884d179dSJan Kara return sb->s_qcop->set_dqblk(sb, type, id, &idq); 309884d179dSJan Kara } 310884d179dSJan Kara 311*c411e5f6SChristoph Hellwig static int quota_setxstate(struct super_block *sb, int cmd, void __user *addr) 312*c411e5f6SChristoph Hellwig { 313884d179dSJan Kara __u32 flags; 314884d179dSJan Kara 315884d179dSJan Kara if (copy_from_user(&flags, addr, sizeof(flags))) 316884d179dSJan Kara return -EFAULT; 317884d179dSJan Kara return sb->s_qcop->set_xstate(sb, flags, cmd); 318884d179dSJan Kara } 319884d179dSJan Kara 320*c411e5f6SChristoph Hellwig static int quota_getxstate(struct super_block *sb, void __user *addr) 321*c411e5f6SChristoph Hellwig { 322*c411e5f6SChristoph Hellwig struct fs_quota_stat fqs; 323*c411e5f6SChristoph Hellwig int ret; 324*c411e5f6SChristoph Hellwig 325*c411e5f6SChristoph Hellwig ret = sb->s_qcop->get_xstate(sb, &fqs); 326*c411e5f6SChristoph Hellwig if (!ret && copy_to_user(addr, &fqs, sizeof(fqs))) 327884d179dSJan Kara return -EFAULT; 328*c411e5f6SChristoph Hellwig return ret; 329884d179dSJan Kara } 330*c411e5f6SChristoph Hellwig 331*c411e5f6SChristoph Hellwig static int quota_setxquota(struct super_block *sb, int type, qid_t id, 332*c411e5f6SChristoph Hellwig void __user *addr) 333*c411e5f6SChristoph Hellwig { 334884d179dSJan Kara struct fs_disk_quota fdq; 335884d179dSJan Kara 336884d179dSJan Kara if (copy_from_user(&fdq, addr, sizeof(fdq))) 337884d179dSJan Kara return -EFAULT; 338884d179dSJan Kara return sb->s_qcop->set_xquota(sb, type, id, &fdq); 339884d179dSJan Kara } 340*c411e5f6SChristoph Hellwig 341*c411e5f6SChristoph Hellwig static int quota_getxquota(struct super_block *sb, int type, qid_t id, 342*c411e5f6SChristoph Hellwig void __user *addr) 343*c411e5f6SChristoph Hellwig { 344884d179dSJan Kara struct fs_disk_quota fdq; 345*c411e5f6SChristoph Hellwig int ret; 346884d179dSJan Kara 347268157baSJan Kara ret = sb->s_qcop->get_xquota(sb, type, id, &fdq); 348*c411e5f6SChristoph Hellwig if (!ret && copy_to_user(addr, &fdq, sizeof(fdq))) 349884d179dSJan Kara return -EFAULT; 350*c411e5f6SChristoph Hellwig return ret; 351884d179dSJan Kara } 352*c411e5f6SChristoph Hellwig 353*c411e5f6SChristoph Hellwig /* Copy parameters and call proper function */ 354*c411e5f6SChristoph Hellwig static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, 355*c411e5f6SChristoph Hellwig void __user *addr) 356*c411e5f6SChristoph Hellwig { 357*c411e5f6SChristoph Hellwig switch (cmd) { 358*c411e5f6SChristoph Hellwig case Q_QUOTAON: 359*c411e5f6SChristoph Hellwig return quota_quotaon(sb, type, cmd, id, addr); 360*c411e5f6SChristoph Hellwig case Q_QUOTAOFF: 361*c411e5f6SChristoph Hellwig return sb->s_qcop->quota_off(sb, type, 0); 362*c411e5f6SChristoph Hellwig case Q_GETFMT: 363*c411e5f6SChristoph Hellwig return quota_getfmt(sb, type, addr); 364*c411e5f6SChristoph Hellwig case Q_GETINFO: 365*c411e5f6SChristoph Hellwig return quota_getinfo(sb, type, addr); 366*c411e5f6SChristoph Hellwig case Q_SETINFO: 367*c411e5f6SChristoph Hellwig return quota_setinfo(sb, type, addr); 368*c411e5f6SChristoph Hellwig case Q_GETQUOTA: 369*c411e5f6SChristoph Hellwig return quota_getquota(sb, type, id, addr); 370*c411e5f6SChristoph Hellwig case Q_SETQUOTA: 371*c411e5f6SChristoph Hellwig return quota_setquota(sb, type, id, addr); 372*c411e5f6SChristoph Hellwig case Q_SYNC: 373*c411e5f6SChristoph Hellwig if (sb) 374*c411e5f6SChristoph Hellwig sync_quota_sb(sb, type); 375*c411e5f6SChristoph Hellwig else 376*c411e5f6SChristoph Hellwig sync_dquots(type); 377*c411e5f6SChristoph Hellwig return 0; 378*c411e5f6SChristoph Hellwig case Q_XQUOTAON: 379*c411e5f6SChristoph Hellwig case Q_XQUOTAOFF: 380*c411e5f6SChristoph Hellwig case Q_XQUOTARM: 381*c411e5f6SChristoph Hellwig return quota_setxstate(sb, cmd, addr); 382*c411e5f6SChristoph Hellwig case Q_XGETQSTAT: 383*c411e5f6SChristoph Hellwig return quota_getxstate(sb, addr); 384*c411e5f6SChristoph Hellwig case Q_XSETQLIM: 385*c411e5f6SChristoph Hellwig return quota_setxquota(sb, type, id, addr); 386*c411e5f6SChristoph Hellwig case Q_XGETQUOTA: 387*c411e5f6SChristoph Hellwig return quota_getxquota(sb, type, id, addr); 388884d179dSJan Kara case Q_XQUOTASYNC: 389884d179dSJan Kara return sb->s_qcop->quota_sync(sb, type); 390884d179dSJan Kara /* We never reach here unless validity check is broken */ 391884d179dSJan Kara default: 392884d179dSJan Kara BUG(); 393884d179dSJan Kara } 394*c411e5f6SChristoph Hellwig 395884d179dSJan Kara return 0; 396884d179dSJan Kara } 397884d179dSJan Kara 398884d179dSJan Kara /* 399884d179dSJan Kara * look up a superblock on which quota ops will be performed 400884d179dSJan Kara * - use the name of a block device to find the superblock thereon 401884d179dSJan Kara */ 4027a2435d8SJan Kara static struct super_block *quotactl_block(const char __user *special) 403884d179dSJan Kara { 404884d179dSJan Kara #ifdef CONFIG_BLOCK 405884d179dSJan Kara struct block_device *bdev; 406884d179dSJan Kara struct super_block *sb; 407884d179dSJan Kara char *tmp = getname(special); 408884d179dSJan Kara 409884d179dSJan Kara if (IS_ERR(tmp)) 410884d179dSJan Kara return ERR_CAST(tmp); 411884d179dSJan Kara bdev = lookup_bdev(tmp); 412884d179dSJan Kara putname(tmp); 413884d179dSJan Kara if (IS_ERR(bdev)) 414884d179dSJan Kara return ERR_CAST(bdev); 415884d179dSJan Kara sb = get_super(bdev); 416884d179dSJan Kara bdput(bdev); 417884d179dSJan Kara if (!sb) 418884d179dSJan Kara return ERR_PTR(-ENODEV); 419884d179dSJan Kara 420884d179dSJan Kara return sb; 421884d179dSJan Kara #else 422884d179dSJan Kara return ERR_PTR(-ENODEV); 423884d179dSJan Kara #endif 424884d179dSJan Kara } 425884d179dSJan Kara 426884d179dSJan Kara /* 427884d179dSJan Kara * This is the system call interface. This communicates with 428884d179dSJan Kara * the user-level programs. Currently this only supports diskquota 429884d179dSJan Kara * calls. Maybe we need to add the process quotas etc. in the future, 430884d179dSJan Kara * but we probably should use rlimits for that. 431884d179dSJan Kara */ 432884d179dSJan Kara SYSCALL_DEFINE4(quotactl, unsigned int, cmd, const char __user *, special, 433884d179dSJan Kara qid_t, id, void __user *, addr) 434884d179dSJan Kara { 435884d179dSJan Kara uint cmds, type; 436884d179dSJan Kara struct super_block *sb = NULL; 437884d179dSJan Kara int ret; 438884d179dSJan Kara 439884d179dSJan Kara cmds = cmd >> SUBCMDSHIFT; 440884d179dSJan Kara type = cmd & SUBCMDMASK; 441884d179dSJan Kara 442884d179dSJan Kara if (cmds != Q_SYNC || special) { 443884d179dSJan Kara sb = quotactl_block(special); 444884d179dSJan Kara if (IS_ERR(sb)) 445884d179dSJan Kara return PTR_ERR(sb); 446884d179dSJan Kara } 447884d179dSJan Kara 448884d179dSJan Kara ret = check_quotactl_valid(sb, type, cmds, id); 449884d179dSJan Kara if (ret >= 0) 450884d179dSJan Kara ret = do_quotactl(sb, type, cmds, id, addr); 451884d179dSJan Kara if (sb) 452884d179dSJan Kara drop_super(sb); 453884d179dSJan Kara 454884d179dSJan Kara return ret; 455884d179dSJan Kara } 456884d179dSJan Kara 457884d179dSJan Kara #if defined(CONFIG_COMPAT_FOR_U64_ALIGNMENT) 458884d179dSJan Kara /* 459884d179dSJan Kara * This code works only for 32 bit quota tools over 64 bit OS (x86_64, ia64) 460884d179dSJan Kara * and is necessary due to alignment problems. 461884d179dSJan Kara */ 462884d179dSJan Kara struct compat_if_dqblk { 463884d179dSJan Kara compat_u64 dqb_bhardlimit; 464884d179dSJan Kara compat_u64 dqb_bsoftlimit; 465884d179dSJan Kara compat_u64 dqb_curspace; 466884d179dSJan Kara compat_u64 dqb_ihardlimit; 467884d179dSJan Kara compat_u64 dqb_isoftlimit; 468884d179dSJan Kara compat_u64 dqb_curinodes; 469884d179dSJan Kara compat_u64 dqb_btime; 470884d179dSJan Kara compat_u64 dqb_itime; 471884d179dSJan Kara compat_uint_t dqb_valid; 472884d179dSJan Kara }; 473884d179dSJan Kara 474884d179dSJan Kara /* XFS structures */ 475884d179dSJan Kara struct compat_fs_qfilestat { 476884d179dSJan Kara compat_u64 dqb_bhardlimit; 477884d179dSJan Kara compat_u64 qfs_nblks; 478884d179dSJan Kara compat_uint_t qfs_nextents; 479884d179dSJan Kara }; 480884d179dSJan Kara 481884d179dSJan Kara struct compat_fs_quota_stat { 482884d179dSJan Kara __s8 qs_version; 483884d179dSJan Kara __u16 qs_flags; 484884d179dSJan Kara __s8 qs_pad; 485884d179dSJan Kara struct compat_fs_qfilestat qs_uquota; 486884d179dSJan Kara struct compat_fs_qfilestat qs_gquota; 487884d179dSJan Kara compat_uint_t qs_incoredqs; 488884d179dSJan Kara compat_int_t qs_btimelimit; 489884d179dSJan Kara compat_int_t qs_itimelimit; 490884d179dSJan Kara compat_int_t qs_rtbtimelimit; 491884d179dSJan Kara __u16 qs_bwarnlimit; 492884d179dSJan Kara __u16 qs_iwarnlimit; 493884d179dSJan Kara }; 494884d179dSJan Kara 495884d179dSJan Kara asmlinkage long sys32_quotactl(unsigned int cmd, const char __user *special, 496884d179dSJan Kara qid_t id, void __user *addr) 497884d179dSJan Kara { 498884d179dSJan Kara unsigned int cmds; 499884d179dSJan Kara struct if_dqblk __user *dqblk; 500884d179dSJan Kara struct compat_if_dqblk __user *compat_dqblk; 501884d179dSJan Kara struct fs_quota_stat __user *fsqstat; 502884d179dSJan Kara struct compat_fs_quota_stat __user *compat_fsqstat; 503884d179dSJan Kara compat_uint_t data; 504884d179dSJan Kara u16 xdata; 505884d179dSJan Kara long ret; 506884d179dSJan Kara 507884d179dSJan Kara cmds = cmd >> SUBCMDSHIFT; 508884d179dSJan Kara 509884d179dSJan Kara switch (cmds) { 510884d179dSJan Kara case Q_GETQUOTA: 511884d179dSJan Kara dqblk = compat_alloc_user_space(sizeof(struct if_dqblk)); 512884d179dSJan Kara compat_dqblk = addr; 513884d179dSJan Kara ret = sys_quotactl(cmd, special, id, dqblk); 514884d179dSJan Kara if (ret) 515884d179dSJan Kara break; 516884d179dSJan Kara if (copy_in_user(compat_dqblk, dqblk, sizeof(*compat_dqblk)) || 517884d179dSJan Kara get_user(data, &dqblk->dqb_valid) || 518884d179dSJan Kara put_user(data, &compat_dqblk->dqb_valid)) 519884d179dSJan Kara ret = -EFAULT; 520884d179dSJan Kara break; 521884d179dSJan Kara case Q_SETQUOTA: 522884d179dSJan Kara dqblk = compat_alloc_user_space(sizeof(struct if_dqblk)); 523884d179dSJan Kara compat_dqblk = addr; 524884d179dSJan Kara ret = -EFAULT; 525884d179dSJan Kara if (copy_in_user(dqblk, compat_dqblk, sizeof(*compat_dqblk)) || 526884d179dSJan Kara get_user(data, &compat_dqblk->dqb_valid) || 527884d179dSJan Kara put_user(data, &dqblk->dqb_valid)) 528884d179dSJan Kara break; 529884d179dSJan Kara ret = sys_quotactl(cmd, special, id, dqblk); 530884d179dSJan Kara break; 531884d179dSJan Kara case Q_XGETQSTAT: 532884d179dSJan Kara fsqstat = compat_alloc_user_space(sizeof(struct fs_quota_stat)); 533884d179dSJan Kara compat_fsqstat = addr; 534884d179dSJan Kara ret = sys_quotactl(cmd, special, id, fsqstat); 535884d179dSJan Kara if (ret) 536884d179dSJan Kara break; 537884d179dSJan Kara ret = -EFAULT; 538884d179dSJan Kara /* Copying qs_version, qs_flags, qs_pad */ 539884d179dSJan Kara if (copy_in_user(compat_fsqstat, fsqstat, 540884d179dSJan Kara offsetof(struct compat_fs_quota_stat, qs_uquota))) 541884d179dSJan Kara break; 542884d179dSJan Kara /* Copying qs_uquota */ 543884d179dSJan Kara if (copy_in_user(&compat_fsqstat->qs_uquota, 544884d179dSJan Kara &fsqstat->qs_uquota, 545884d179dSJan Kara sizeof(compat_fsqstat->qs_uquota)) || 546884d179dSJan Kara get_user(data, &fsqstat->qs_uquota.qfs_nextents) || 547884d179dSJan Kara put_user(data, &compat_fsqstat->qs_uquota.qfs_nextents)) 548884d179dSJan Kara break; 549884d179dSJan Kara /* Copying qs_gquota */ 550884d179dSJan Kara if (copy_in_user(&compat_fsqstat->qs_gquota, 551884d179dSJan Kara &fsqstat->qs_gquota, 552884d179dSJan Kara sizeof(compat_fsqstat->qs_gquota)) || 553884d179dSJan Kara get_user(data, &fsqstat->qs_gquota.qfs_nextents) || 554884d179dSJan Kara put_user(data, &compat_fsqstat->qs_gquota.qfs_nextents)) 555884d179dSJan Kara break; 556884d179dSJan Kara /* Copying the rest */ 557884d179dSJan Kara if (copy_in_user(&compat_fsqstat->qs_incoredqs, 558884d179dSJan Kara &fsqstat->qs_incoredqs, 559884d179dSJan Kara sizeof(struct compat_fs_quota_stat) - 560884d179dSJan Kara offsetof(struct compat_fs_quota_stat, qs_incoredqs)) || 561884d179dSJan Kara get_user(xdata, &fsqstat->qs_iwarnlimit) || 562884d179dSJan Kara put_user(xdata, &compat_fsqstat->qs_iwarnlimit)) 563884d179dSJan Kara break; 564884d179dSJan Kara ret = 0; 565884d179dSJan Kara break; 566884d179dSJan Kara default: 567884d179dSJan Kara ret = sys_quotactl(cmd, special, id, addr); 568884d179dSJan Kara } 569884d179dSJan Kara return ret; 570884d179dSJan Kara } 571884d179dSJan Kara #endif 57286e931a3SSteven Whitehouse 57386e931a3SSteven Whitehouse 57486e931a3SSteven Whitehouse #ifdef CONFIG_QUOTA_NETLINK_INTERFACE 57586e931a3SSteven Whitehouse 57686e931a3SSteven Whitehouse /* Netlink family structure for quota */ 57786e931a3SSteven Whitehouse static struct genl_family quota_genl_family = { 57886e931a3SSteven Whitehouse .id = GENL_ID_GENERATE, 57986e931a3SSteven Whitehouse .hdrsize = 0, 58086e931a3SSteven Whitehouse .name = "VFS_DQUOT", 58186e931a3SSteven Whitehouse .version = 1, 58286e931a3SSteven Whitehouse .maxattr = QUOTA_NL_A_MAX, 58386e931a3SSteven Whitehouse }; 58486e931a3SSteven Whitehouse 58586e931a3SSteven Whitehouse /** 58686e931a3SSteven Whitehouse * quota_send_warning - Send warning to userspace about exceeded quota 58786e931a3SSteven Whitehouse * @type: The quota type: USRQQUOTA, GRPQUOTA,... 58886e931a3SSteven Whitehouse * @id: The user or group id of the quota that was exceeded 58986e931a3SSteven Whitehouse * @dev: The device on which the fs is mounted (sb->s_dev) 59086e931a3SSteven Whitehouse * @warntype: The type of the warning: QUOTA_NL_... 59186e931a3SSteven Whitehouse * 59286e931a3SSteven Whitehouse * This can be used by filesystems (including those which don't use 59386e931a3SSteven Whitehouse * dquot) to send a message to userspace relating to quota limits. 59486e931a3SSteven Whitehouse * 59586e931a3SSteven Whitehouse */ 59686e931a3SSteven Whitehouse 59786e931a3SSteven Whitehouse void quota_send_warning(short type, unsigned int id, dev_t dev, 59886e931a3SSteven Whitehouse const char warntype) 59986e931a3SSteven Whitehouse { 60086e931a3SSteven Whitehouse static atomic_t seq; 60186e931a3SSteven Whitehouse struct sk_buff *skb; 60286e931a3SSteven Whitehouse void *msg_head; 60386e931a3SSteven Whitehouse int ret; 60486e931a3SSteven Whitehouse int msg_size = 4 * nla_total_size(sizeof(u32)) + 60586e931a3SSteven Whitehouse 2 * nla_total_size(sizeof(u64)); 60686e931a3SSteven Whitehouse 60786e931a3SSteven Whitehouse /* We have to allocate using GFP_NOFS as we are called from a 60886e931a3SSteven Whitehouse * filesystem performing write and thus further recursion into 60986e931a3SSteven Whitehouse * the fs to free some data could cause deadlocks. */ 61086e931a3SSteven Whitehouse skb = genlmsg_new(msg_size, GFP_NOFS); 61186e931a3SSteven Whitehouse if (!skb) { 61286e931a3SSteven Whitehouse printk(KERN_ERR 61386e931a3SSteven Whitehouse "VFS: Not enough memory to send quota warning.\n"); 61486e931a3SSteven Whitehouse return; 61586e931a3SSteven Whitehouse } 61686e931a3SSteven Whitehouse msg_head = genlmsg_put(skb, 0, atomic_add_return(1, &seq), 61786e931a3SSteven Whitehouse "a_genl_family, 0, QUOTA_NL_C_WARNING); 61886e931a3SSteven Whitehouse if (!msg_head) { 61986e931a3SSteven Whitehouse printk(KERN_ERR 62086e931a3SSteven Whitehouse "VFS: Cannot store netlink header in quota warning.\n"); 62186e931a3SSteven Whitehouse goto err_out; 62286e931a3SSteven Whitehouse } 62386e931a3SSteven Whitehouse ret = nla_put_u32(skb, QUOTA_NL_A_QTYPE, type); 62486e931a3SSteven Whitehouse if (ret) 62586e931a3SSteven Whitehouse goto attr_err_out; 62686e931a3SSteven Whitehouse ret = nla_put_u64(skb, QUOTA_NL_A_EXCESS_ID, id); 62786e931a3SSteven Whitehouse if (ret) 62886e931a3SSteven Whitehouse goto attr_err_out; 62986e931a3SSteven Whitehouse ret = nla_put_u32(skb, QUOTA_NL_A_WARNING, warntype); 63086e931a3SSteven Whitehouse if (ret) 63186e931a3SSteven Whitehouse goto attr_err_out; 63286e931a3SSteven Whitehouse ret = nla_put_u32(skb, QUOTA_NL_A_DEV_MAJOR, MAJOR(dev)); 63386e931a3SSteven Whitehouse if (ret) 63486e931a3SSteven Whitehouse goto attr_err_out; 63586e931a3SSteven Whitehouse ret = nla_put_u32(skb, QUOTA_NL_A_DEV_MINOR, MINOR(dev)); 63686e931a3SSteven Whitehouse if (ret) 63786e931a3SSteven Whitehouse goto attr_err_out; 63886e931a3SSteven Whitehouse ret = nla_put_u64(skb, QUOTA_NL_A_CAUSED_ID, current_uid()); 63986e931a3SSteven Whitehouse if (ret) 64086e931a3SSteven Whitehouse goto attr_err_out; 64186e931a3SSteven Whitehouse genlmsg_end(skb, msg_head); 64286e931a3SSteven Whitehouse 64386e931a3SSteven Whitehouse genlmsg_multicast(skb, 0, quota_genl_family.id, GFP_NOFS); 64486e931a3SSteven Whitehouse return; 64586e931a3SSteven Whitehouse attr_err_out: 64686e931a3SSteven Whitehouse printk(KERN_ERR "VFS: Not enough space to compose quota message!\n"); 64786e931a3SSteven Whitehouse err_out: 64886e931a3SSteven Whitehouse kfree_skb(skb); 64986e931a3SSteven Whitehouse } 65086e931a3SSteven Whitehouse EXPORT_SYMBOL(quota_send_warning); 65186e931a3SSteven Whitehouse 65286e931a3SSteven Whitehouse static int __init quota_init(void) 65386e931a3SSteven Whitehouse { 65486e931a3SSteven Whitehouse if (genl_register_family("a_genl_family) != 0) 65586e931a3SSteven Whitehouse printk(KERN_ERR 65686e931a3SSteven Whitehouse "VFS: Failed to create quota netlink interface.\n"); 65786e931a3SSteven Whitehouse return 0; 65886e931a3SSteven Whitehouse }; 65986e931a3SSteven Whitehouse 66086e931a3SSteven Whitehouse module_init(quota_init); 66186e931a3SSteven Whitehouse #endif 66286e931a3SSteven Whitehouse 663