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/capability.h> 17 #include <linux/quotaops.h> 18 #include <linux/types.h> 19 #include <linux/writeback.h> 20 21 static int check_quotactl_permission(struct super_block *sb, int type, int cmd, 22 qid_t id) 23 { 24 switch (cmd) { 25 /* these commands do not require any special privilegues */ 26 case Q_GETFMT: 27 case Q_SYNC: 28 case Q_GETINFO: 29 case Q_XGETQSTAT: 30 case Q_XQUOTASYNC: 31 break; 32 /* allow to query information for dquots we "own" */ 33 case Q_GETQUOTA: 34 case Q_XGETQUOTA: 35 if ((type == USRQUOTA && current_euid() == id) || 36 (type == GRPQUOTA && in_egroup_p(id))) 37 break; 38 /*FALLTHROUGH*/ 39 default: 40 if (!capable(CAP_SYS_ADMIN)) 41 return -EPERM; 42 } 43 44 return security_quotactl(cmd, type, id, sb); 45 } 46 47 static void quota_sync_one(struct super_block *sb, void *arg) 48 { 49 if (sb->s_qcop && sb->s_qcop->quota_sync) 50 sb->s_qcop->quota_sync(sb, *(int *)arg, 1); 51 } 52 53 static int quota_sync_all(int type) 54 { 55 int ret; 56 57 if (type >= MAXQUOTAS) 58 return -EINVAL; 59 ret = security_quotactl(Q_SYNC, type, 0, NULL); 60 if (!ret) 61 iterate_supers(quota_sync_one, &type); 62 return ret; 63 } 64 65 static int quota_quotaon(struct super_block *sb, int type, int cmd, qid_t id, 66 struct path *path) 67 { 68 if (!sb->s_qcop->quota_on && !sb->s_qcop->quota_on_meta) 69 return -ENOSYS; 70 if (sb->s_qcop->quota_on_meta) 71 return sb->s_qcop->quota_on_meta(sb, type, id); 72 if (IS_ERR(path)) 73 return PTR_ERR(path); 74 return sb->s_qcop->quota_on(sb, type, id, path); 75 } 76 77 static int quota_getfmt(struct super_block *sb, int type, void __user *addr) 78 { 79 __u32 fmt; 80 81 down_read(&sb_dqopt(sb)->dqptr_sem); 82 if (!sb_has_quota_active(sb, type)) { 83 up_read(&sb_dqopt(sb)->dqptr_sem); 84 return -ESRCH; 85 } 86 fmt = sb_dqopt(sb)->info[type].dqi_format->qf_fmt_id; 87 up_read(&sb_dqopt(sb)->dqptr_sem); 88 if (copy_to_user(addr, &fmt, sizeof(fmt))) 89 return -EFAULT; 90 return 0; 91 } 92 93 static int quota_getinfo(struct super_block *sb, int type, void __user *addr) 94 { 95 struct if_dqinfo info; 96 int ret; 97 98 if (!sb->s_qcop->get_info) 99 return -ENOSYS; 100 ret = sb->s_qcop->get_info(sb, type, &info); 101 if (!ret && copy_to_user(addr, &info, sizeof(info))) 102 return -EFAULT; 103 return ret; 104 } 105 106 static int quota_setinfo(struct super_block *sb, int type, void __user *addr) 107 { 108 struct if_dqinfo info; 109 110 if (copy_from_user(&info, addr, sizeof(info))) 111 return -EFAULT; 112 if (!sb->s_qcop->set_info) 113 return -ENOSYS; 114 return sb->s_qcop->set_info(sb, type, &info); 115 } 116 117 static void copy_to_if_dqblk(struct if_dqblk *dst, struct fs_disk_quota *src) 118 { 119 dst->dqb_bhardlimit = src->d_blk_hardlimit; 120 dst->dqb_bsoftlimit = src->d_blk_softlimit; 121 dst->dqb_curspace = src->d_bcount; 122 dst->dqb_ihardlimit = src->d_ino_hardlimit; 123 dst->dqb_isoftlimit = src->d_ino_softlimit; 124 dst->dqb_curinodes = src->d_icount; 125 dst->dqb_btime = src->d_btimer; 126 dst->dqb_itime = src->d_itimer; 127 dst->dqb_valid = QIF_ALL; 128 } 129 130 static int quota_getquota(struct super_block *sb, int type, qid_t id, 131 void __user *addr) 132 { 133 struct fs_disk_quota fdq; 134 struct if_dqblk idq; 135 int ret; 136 137 if (!sb->s_qcop->get_dqblk) 138 return -ENOSYS; 139 ret = sb->s_qcop->get_dqblk(sb, type, id, &fdq); 140 if (ret) 141 return ret; 142 copy_to_if_dqblk(&idq, &fdq); 143 if (copy_to_user(addr, &idq, sizeof(idq))) 144 return -EFAULT; 145 return 0; 146 } 147 148 static void copy_from_if_dqblk(struct fs_disk_quota *dst, struct if_dqblk *src) 149 { 150 dst->d_blk_hardlimit = src->dqb_bhardlimit; 151 dst->d_blk_softlimit = src->dqb_bsoftlimit; 152 dst->d_bcount = src->dqb_curspace; 153 dst->d_ino_hardlimit = src->dqb_ihardlimit; 154 dst->d_ino_softlimit = src->dqb_isoftlimit; 155 dst->d_icount = src->dqb_curinodes; 156 dst->d_btimer = src->dqb_btime; 157 dst->d_itimer = src->dqb_itime; 158 159 dst->d_fieldmask = 0; 160 if (src->dqb_valid & QIF_BLIMITS) 161 dst->d_fieldmask |= FS_DQ_BSOFT | FS_DQ_BHARD; 162 if (src->dqb_valid & QIF_SPACE) 163 dst->d_fieldmask |= FS_DQ_BCOUNT; 164 if (src->dqb_valid & QIF_ILIMITS) 165 dst->d_fieldmask |= FS_DQ_ISOFT | FS_DQ_IHARD; 166 if (src->dqb_valid & QIF_INODES) 167 dst->d_fieldmask |= FS_DQ_ICOUNT; 168 if (src->dqb_valid & QIF_BTIME) 169 dst->d_fieldmask |= FS_DQ_BTIMER; 170 if (src->dqb_valid & QIF_ITIME) 171 dst->d_fieldmask |= FS_DQ_ITIMER; 172 } 173 174 static int quota_setquota(struct super_block *sb, int type, qid_t id, 175 void __user *addr) 176 { 177 struct fs_disk_quota fdq; 178 struct if_dqblk idq; 179 180 if (copy_from_user(&idq, addr, sizeof(idq))) 181 return -EFAULT; 182 if (!sb->s_qcop->set_dqblk) 183 return -ENOSYS; 184 copy_from_if_dqblk(&fdq, &idq); 185 return sb->s_qcop->set_dqblk(sb, type, id, &fdq); 186 } 187 188 static int quota_setxstate(struct super_block *sb, int cmd, void __user *addr) 189 { 190 __u32 flags; 191 192 if (copy_from_user(&flags, addr, sizeof(flags))) 193 return -EFAULT; 194 if (!sb->s_qcop->set_xstate) 195 return -ENOSYS; 196 return sb->s_qcop->set_xstate(sb, flags, cmd); 197 } 198 199 static int quota_getxstate(struct super_block *sb, void __user *addr) 200 { 201 struct fs_quota_stat fqs; 202 int ret; 203 204 if (!sb->s_qcop->get_xstate) 205 return -ENOSYS; 206 ret = sb->s_qcop->get_xstate(sb, &fqs); 207 if (!ret && copy_to_user(addr, &fqs, sizeof(fqs))) 208 return -EFAULT; 209 return ret; 210 } 211 212 static int quota_setxquota(struct super_block *sb, int type, qid_t id, 213 void __user *addr) 214 { 215 struct fs_disk_quota fdq; 216 217 if (copy_from_user(&fdq, addr, sizeof(fdq))) 218 return -EFAULT; 219 if (!sb->s_qcop->set_dqblk) 220 return -ENOSYS; 221 return sb->s_qcop->set_dqblk(sb, type, id, &fdq); 222 } 223 224 static int quota_getxquota(struct super_block *sb, int type, qid_t id, 225 void __user *addr) 226 { 227 struct fs_disk_quota fdq; 228 int ret; 229 230 if (!sb->s_qcop->get_dqblk) 231 return -ENOSYS; 232 ret = sb->s_qcop->get_dqblk(sb, type, id, &fdq); 233 if (!ret && copy_to_user(addr, &fdq, sizeof(fdq))) 234 return -EFAULT; 235 return ret; 236 } 237 238 /* Copy parameters and call proper function */ 239 static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, 240 void __user *addr, struct path *path) 241 { 242 int ret; 243 244 if (type >= (XQM_COMMAND(cmd) ? XQM_MAXQUOTAS : MAXQUOTAS)) 245 return -EINVAL; 246 if (!sb->s_qcop) 247 return -ENOSYS; 248 249 ret = check_quotactl_permission(sb, type, cmd, id); 250 if (ret < 0) 251 return ret; 252 253 switch (cmd) { 254 case Q_QUOTAON: 255 return quota_quotaon(sb, type, cmd, id, path); 256 case Q_QUOTAOFF: 257 if (!sb->s_qcop->quota_off) 258 return -ENOSYS; 259 return sb->s_qcop->quota_off(sb, type); 260 case Q_GETFMT: 261 return quota_getfmt(sb, type, addr); 262 case Q_GETINFO: 263 return quota_getinfo(sb, type, addr); 264 case Q_SETINFO: 265 return quota_setinfo(sb, type, addr); 266 case Q_GETQUOTA: 267 return quota_getquota(sb, type, id, addr); 268 case Q_SETQUOTA: 269 return quota_setquota(sb, type, id, addr); 270 case Q_SYNC: 271 if (!sb->s_qcop->quota_sync) 272 return -ENOSYS; 273 return sb->s_qcop->quota_sync(sb, type, 1); 274 case Q_XQUOTAON: 275 case Q_XQUOTAOFF: 276 case Q_XQUOTARM: 277 return quota_setxstate(sb, cmd, addr); 278 case Q_XGETQSTAT: 279 return quota_getxstate(sb, addr); 280 case Q_XSETQLIM: 281 return quota_setxquota(sb, type, id, addr); 282 case Q_XGETQUOTA: 283 return quota_getxquota(sb, type, id, addr); 284 case Q_XQUOTASYNC: 285 /* caller already holds s_umount */ 286 if (sb->s_flags & MS_RDONLY) 287 return -EROFS; 288 writeback_inodes_sb(sb, WB_REASON_SYNC); 289 return 0; 290 default: 291 return -EINVAL; 292 } 293 } 294 295 /* 296 * look up a superblock on which quota ops will be performed 297 * - use the name of a block device to find the superblock thereon 298 */ 299 static struct super_block *quotactl_block(const char __user *special) 300 { 301 #ifdef CONFIG_BLOCK 302 struct block_device *bdev; 303 struct super_block *sb; 304 char *tmp = getname(special); 305 306 if (IS_ERR(tmp)) 307 return ERR_CAST(tmp); 308 bdev = lookup_bdev(tmp); 309 putname(tmp); 310 if (IS_ERR(bdev)) 311 return ERR_CAST(bdev); 312 sb = get_super(bdev); 313 bdput(bdev); 314 if (!sb) 315 return ERR_PTR(-ENODEV); 316 317 return sb; 318 #else 319 return ERR_PTR(-ENODEV); 320 #endif 321 } 322 323 /* 324 * This is the system call interface. This communicates with 325 * the user-level programs. Currently this only supports diskquota 326 * calls. Maybe we need to add the process quotas etc. in the future, 327 * but we probably should use rlimits for that. 328 */ 329 SYSCALL_DEFINE4(quotactl, unsigned int, cmd, const char __user *, special, 330 qid_t, id, void __user *, addr) 331 { 332 uint cmds, type; 333 struct super_block *sb = NULL; 334 struct path path, *pathp = NULL; 335 int ret; 336 337 cmds = cmd >> SUBCMDSHIFT; 338 type = cmd & SUBCMDMASK; 339 340 /* 341 * As a special case Q_SYNC can be called without a specific device. 342 * It will iterate all superblocks that have quota enabled and call 343 * the sync action on each of them. 344 */ 345 if (!special) { 346 if (cmds == Q_SYNC) 347 return quota_sync_all(type); 348 return -ENODEV; 349 } 350 351 /* 352 * Path for quotaon has to be resolved before grabbing superblock 353 * because that gets s_umount sem which is also possibly needed by path 354 * resolution (think about autofs) and thus deadlocks could arise. 355 */ 356 if (cmds == Q_QUOTAON) { 357 ret = user_path_at(AT_FDCWD, addr, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &path); 358 if (ret) 359 pathp = ERR_PTR(ret); 360 else 361 pathp = &path; 362 } 363 364 sb = quotactl_block(special); 365 if (IS_ERR(sb)) { 366 ret = PTR_ERR(sb); 367 goto out; 368 } 369 370 ret = do_quotactl(sb, type, cmds, id, addr, pathp); 371 372 drop_super(sb); 373 out: 374 if (pathp && !IS_ERR(pathp)) 375 path_put(pathp); 376 return ret; 377 } 378