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/kernel.h> 14#include <linux/security.h> 15#include <linux/syscalls.h> 16#include <linux/buffer_head.h> 17#include <linux/capability.h> 18#include <linux/quotaops.h> 19 20/* Check validity of generic quotactl commands */ 21static int generic_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id) 22{ 23 if (type >= MAXQUOTAS) 24 return -EINVAL; 25 if (!sb && cmd != Q_SYNC) 26 return -ENODEV; 27 /* Is operation supported? */ 28 if (sb && !sb->s_qcop) 29 return -ENOSYS; 30 31 switch (cmd) { 32 case Q_GETFMT: 33 break; 34 case Q_QUOTAON: 35 if (!sb->s_qcop->quota_on) 36 return -ENOSYS; 37 break; 38 case Q_QUOTAOFF: 39 if (!sb->s_qcop->quota_off) 40 return -ENOSYS; 41 break; 42 case Q_SETINFO: 43 if (!sb->s_qcop->set_info) 44 return -ENOSYS; 45 break; 46 case Q_GETINFO: 47 if (!sb->s_qcop->get_info) 48 return -ENOSYS; 49 break; 50 case Q_SETQUOTA: 51 if (!sb->s_qcop->set_dqblk) 52 return -ENOSYS; 53 break; 54 case Q_GETQUOTA: 55 if (!sb->s_qcop->get_dqblk) 56 return -ENOSYS; 57 break; 58 case Q_SYNC: 59 if (sb && !sb->s_qcop->quota_sync) 60 return -ENOSYS; 61 break; 62 default: 63 return -EINVAL; 64 } 65 66 /* Is quota turned on for commands which need it? */ 67 switch (cmd) { 68 case Q_GETFMT: 69 case Q_GETINFO: 70 case Q_QUOTAOFF: 71 case Q_SETINFO: 72 case Q_SETQUOTA: 73 case Q_GETQUOTA: 74 /* This is just informative test so we are satisfied without a lock */ 75 if (!sb_has_quota_enabled(sb, type)) 76 return -ESRCH; 77 } 78 79 /* Check privileges */ 80 if (cmd == Q_GETQUOTA) { 81 if (((type == USRQUOTA && current->euid != id) || 82 (type == GRPQUOTA && !in_egroup_p(id))) && 83 !capable(CAP_SYS_ADMIN)) 84 return -EPERM; 85 } 86 else if (cmd != Q_GETFMT && cmd != Q_SYNC && cmd != Q_GETINFO) 87 if (!capable(CAP_SYS_ADMIN)) 88 return -EPERM; 89 90 return 0; 91} 92 93/* Check validity of XFS Quota Manager commands */ 94static int xqm_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id) 95{ 96 if (type >= XQM_MAXQUOTAS) 97 return -EINVAL; 98 if (!sb) 99 return -ENODEV; 100 if (!sb->s_qcop) 101 return -ENOSYS; 102 103 switch (cmd) { 104 case Q_XQUOTAON: 105 case Q_XQUOTAOFF: 106 case Q_XQUOTARM: 107 if (!sb->s_qcop->set_xstate) 108 return -ENOSYS; 109 break; 110 case Q_XGETQSTAT: 111 if (!sb->s_qcop->get_xstate) 112 return -ENOSYS; 113 break; 114 case Q_XSETQLIM: 115 if (!sb->s_qcop->set_xquota) 116 return -ENOSYS; 117 break; 118 case Q_XGETQUOTA: 119 if (!sb->s_qcop->get_xquota) 120 return -ENOSYS; 121 break; 122 case Q_XQUOTASYNC: 123 if (!sb->s_qcop->quota_sync) 124 return -ENOSYS; 125 break; 126 default: 127 return -EINVAL; 128 } 129 130 /* Check privileges */ 131 if (cmd == Q_XGETQUOTA) { 132 if (((type == XQM_USRQUOTA && current->euid != id) || 133 (type == XQM_GRPQUOTA && !in_egroup_p(id))) && 134 !capable(CAP_SYS_ADMIN)) 135 return -EPERM; 136 } else if (cmd != Q_XGETQSTAT && cmd != Q_XQUOTASYNC) { 137 if (!capable(CAP_SYS_ADMIN)) 138 return -EPERM; 139 } 140 141 return 0; 142} 143 144static int check_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id) 145{ 146 int error; 147 148 if (XQM_COMMAND(cmd)) 149 error = xqm_quotactl_valid(sb, type, cmd, id); 150 else 151 error = generic_quotactl_valid(sb, type, cmd, id); 152 if (!error) 153 error = security_quotactl(cmd, type, id, sb); 154 return error; 155} 156 157static void quota_sync_sb(struct super_block *sb, int type) 158{ 159 int cnt; 160 161 sb->s_qcop->quota_sync(sb, type); 162 /* This is not very clever (and fast) but currently I don't know about 163 * any other simple way of getting quota data to disk and we must get 164 * them there for userspace to be visible... */ 165 if (sb->s_op->sync_fs) 166 sb->s_op->sync_fs(sb, 1); 167 sync_blockdev(sb->s_bdev); 168 169 /* 170 * Now when everything is written we can discard the pagecache so 171 * that userspace sees the changes. 172 */ 173 mutex_lock(&sb_dqopt(sb)->dqonoff_mutex); 174 for (cnt = 0; cnt < MAXQUOTAS; cnt++) { 175 if (type != -1 && cnt != type) 176 continue; 177 if (!sb_has_quota_enabled(sb, cnt)) 178 continue; 179 mutex_lock_nested(&sb_dqopt(sb)->files[cnt]->i_mutex, I_MUTEX_QUOTA); 180 truncate_inode_pages(&sb_dqopt(sb)->files[cnt]->i_data, 0); 181 mutex_unlock(&sb_dqopt(sb)->files[cnt]->i_mutex); 182 } 183 mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex); 184} 185 186void sync_dquots(struct super_block *sb, int type) 187{ 188 int cnt, dirty; 189 190 if (sb) { 191 if (sb->s_qcop->quota_sync) 192 quota_sync_sb(sb, type); 193 return; 194 } 195 196 spin_lock(&sb_lock); 197restart: 198 list_for_each_entry(sb, &super_blocks, s_list) { 199 /* This test just improves performance so it needn't be reliable... */ 200 for (cnt = 0, dirty = 0; cnt < MAXQUOTAS; cnt++) 201 if ((type == cnt || type == -1) && sb_has_quota_enabled(sb, cnt) 202 && info_any_dirty(&sb_dqopt(sb)->info[cnt])) 203 dirty = 1; 204 if (!dirty) 205 continue; 206 sb->s_count++; 207 spin_unlock(&sb_lock); 208 down_read(&sb->s_umount); 209 if (sb->s_root && sb->s_qcop->quota_sync) 210 quota_sync_sb(sb, type); 211 up_read(&sb->s_umount); 212 spin_lock(&sb_lock); 213 if (__put_super_and_need_restart(sb)) 214 goto restart; 215 } 216 spin_unlock(&sb_lock); 217} 218 219/* Copy parameters and call proper function */ 220static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, void __user *addr) 221{ 222 int ret; 223 224 switch (cmd) { 225 case Q_QUOTAON: { 226 char *pathname; 227 228 if (IS_ERR(pathname = getname(addr))) 229 return PTR_ERR(pathname); 230 ret = sb->s_qcop->quota_on(sb, type, id, pathname); 231 putname(pathname); 232 return ret; 233 } 234 case Q_QUOTAOFF: 235 return sb->s_qcop->quota_off(sb, type); 236 237 case Q_GETFMT: { 238 __u32 fmt; 239 240 down_read(&sb_dqopt(sb)->dqptr_sem); 241 if (!sb_has_quota_enabled(sb, type)) { 242 up_read(&sb_dqopt(sb)->dqptr_sem); 243 return -ESRCH; 244 } 245 fmt = sb_dqopt(sb)->info[type].dqi_format->qf_fmt_id; 246 up_read(&sb_dqopt(sb)->dqptr_sem); 247 if (copy_to_user(addr, &fmt, sizeof(fmt))) 248 return -EFAULT; 249 return 0; 250 } 251 case Q_GETINFO: { 252 struct if_dqinfo info; 253 254 if ((ret = sb->s_qcop->get_info(sb, type, &info))) 255 return ret; 256 if (copy_to_user(addr, &info, sizeof(info))) 257 return -EFAULT; 258 return 0; 259 } 260 case Q_SETINFO: { 261 struct if_dqinfo info; 262 263 if (copy_from_user(&info, addr, sizeof(info))) 264 return -EFAULT; 265 return sb->s_qcop->set_info(sb, type, &info); 266 } 267 case Q_GETQUOTA: { 268 struct if_dqblk idq; 269 270 if ((ret = sb->s_qcop->get_dqblk(sb, type, id, &idq))) 271 return ret; 272 if (copy_to_user(addr, &idq, sizeof(idq))) 273 return -EFAULT; 274 return 0; 275 } 276 case Q_SETQUOTA: { 277 struct if_dqblk idq; 278 279 if (copy_from_user(&idq, addr, sizeof(idq))) 280 return -EFAULT; 281 return sb->s_qcop->set_dqblk(sb, type, id, &idq); 282 } 283 case Q_SYNC: 284 sync_dquots(sb, type); 285 return 0; 286 287 case Q_XQUOTAON: 288 case Q_XQUOTAOFF: 289 case Q_XQUOTARM: { 290 __u32 flags; 291 292 if (copy_from_user(&flags, addr, sizeof(flags))) 293 return -EFAULT; 294 return sb->s_qcop->set_xstate(sb, flags, cmd); 295 } 296 case Q_XGETQSTAT: { 297 struct fs_quota_stat fqs; 298 299 if ((ret = sb->s_qcop->get_xstate(sb, &fqs))) 300 return ret; 301 if (copy_to_user(addr, &fqs, sizeof(fqs))) 302 return -EFAULT; 303 return 0; 304 } 305 case Q_XSETQLIM: { 306 struct fs_disk_quota fdq; 307 308 if (copy_from_user(&fdq, addr, sizeof(fdq))) 309 return -EFAULT; 310 return sb->s_qcop->set_xquota(sb, type, id, &fdq); 311 } 312 case Q_XGETQUOTA: { 313 struct fs_disk_quota fdq; 314 315 if ((ret = sb->s_qcop->get_xquota(sb, type, id, &fdq))) 316 return ret; 317 if (copy_to_user(addr, &fdq, sizeof(fdq))) 318 return -EFAULT; 319 return 0; 320 } 321 case Q_XQUOTASYNC: 322 return sb->s_qcop->quota_sync(sb, type); 323 /* We never reach here unless validity check is broken */ 324 default: 325 BUG(); 326 } 327 return 0; 328} 329 330/* 331 * look up a superblock on which quota ops will be performed 332 * - use the name of a block device to find the superblock thereon 333 */ 334static inline struct super_block *quotactl_block(const char __user *special) 335{ 336#ifdef CONFIG_BLOCK 337 struct block_device *bdev; 338 struct super_block *sb; 339 char *tmp = getname(special); 340 341 if (IS_ERR(tmp)) 342 return ERR_PTR(PTR_ERR(tmp)); 343 bdev = lookup_bdev(tmp); 344 putname(tmp); 345 if (IS_ERR(bdev)) 346 return ERR_PTR(PTR_ERR(bdev)); 347 sb = get_super(bdev); 348 bdput(bdev); 349 if (!sb) 350 return ERR_PTR(-ENODEV); 351 352 return sb; 353#else 354 return ERR_PTR(-ENODEV); 355#endif 356} 357 358/* 359 * This is the system call interface. This communicates with 360 * the user-level programs. Currently this only supports diskquota 361 * calls. Maybe we need to add the process quotas etc. in the future, 362 * but we probably should use rlimits for that. 363 */ 364asmlinkage long sys_quotactl(unsigned int cmd, const char __user *special, qid_t id, void __user *addr) 365{ 366 uint cmds, type; 367 struct super_block *sb = NULL; 368 int ret; 369 370 cmds = cmd >> SUBCMDSHIFT; 371 type = cmd & SUBCMDMASK; 372 373 if (cmds != Q_SYNC || special) { 374 sb = quotactl_block(special); 375 if (IS_ERR(sb)) 376 return PTR_ERR(sb); 377 } 378 379 ret = check_quotactl_valid(sb, type, cmds, id); 380 if (ret >= 0) 381 ret = do_quotactl(sb, type, cmds, id, addr); 382 if (sb) 383 drop_super(sb); 384 385 return ret; 386} 387