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