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