Commit | Line | Data |
---|---|---|
b2441318 | 1 | // SPDX-License-Identifier: GPL-2.0 |
5582c76f CH |
2 | |
3 | #include <linux/syscalls.h> | |
4 | #include <linux/compat.h> | |
5 | #include <linux/quotaops.h> | |
6 | ||
7 | /* | |
8 | * This code works only for 32 bit quota tools over 64 bit OS (x86_64, ia64) | |
9 | * and is necessary due to alignment problems. | |
10 | */ | |
11 | struct compat_if_dqblk { | |
12 | compat_u64 dqb_bhardlimit; | |
13 | compat_u64 dqb_bsoftlimit; | |
14 | compat_u64 dqb_curspace; | |
15 | compat_u64 dqb_ihardlimit; | |
16 | compat_u64 dqb_isoftlimit; | |
17 | compat_u64 dqb_curinodes; | |
18 | compat_u64 dqb_btime; | |
19 | compat_u64 dqb_itime; | |
20 | compat_uint_t dqb_valid; | |
21 | }; | |
22 | ||
23 | /* XFS structures */ | |
24 | struct compat_fs_qfilestat { | |
25 | compat_u64 dqb_bhardlimit; | |
26 | compat_u64 qfs_nblks; | |
27 | compat_uint_t qfs_nextents; | |
28 | }; | |
29 | ||
30 | struct compat_fs_quota_stat { | |
31 | __s8 qs_version; | |
32 | __u16 qs_flags; | |
33 | __s8 qs_pad; | |
34 | struct compat_fs_qfilestat qs_uquota; | |
35 | struct compat_fs_qfilestat qs_gquota; | |
36 | compat_uint_t qs_incoredqs; | |
37 | compat_int_t qs_btimelimit; | |
38 | compat_int_t qs_itimelimit; | |
39 | compat_int_t qs_rtbtimelimit; | |
40 | __u16 qs_bwarnlimit; | |
41 | __u16 qs_iwarnlimit; | |
42 | }; | |
43 | ||
44 | asmlinkage long sys32_quotactl(unsigned int cmd, const char __user *special, | |
45 | qid_t id, void __user *addr) | |
46 | { | |
47 | unsigned int cmds; | |
48 | struct if_dqblk __user *dqblk; | |
49 | struct compat_if_dqblk __user *compat_dqblk; | |
50 | struct fs_quota_stat __user *fsqstat; | |
51 | struct compat_fs_quota_stat __user *compat_fsqstat; | |
52 | compat_uint_t data; | |
53 | u16 xdata; | |
54 | long ret; | |
55 | ||
56 | cmds = cmd >> SUBCMDSHIFT; | |
57 | ||
58 | switch (cmds) { | |
59 | case Q_GETQUOTA: | |
60 | dqblk = compat_alloc_user_space(sizeof(struct if_dqblk)); | |
61 | compat_dqblk = addr; | |
62 | ret = sys_quotactl(cmd, special, id, dqblk); | |
63 | if (ret) | |
64 | break; | |
65 | if (copy_in_user(compat_dqblk, dqblk, sizeof(*compat_dqblk)) || | |
66 | get_user(data, &dqblk->dqb_valid) || | |
67 | put_user(data, &compat_dqblk->dqb_valid)) | |
68 | ret = -EFAULT; | |
69 | break; | |
70 | case Q_SETQUOTA: | |
71 | dqblk = compat_alloc_user_space(sizeof(struct if_dqblk)); | |
72 | compat_dqblk = addr; | |
73 | ret = -EFAULT; | |
74 | if (copy_in_user(dqblk, compat_dqblk, sizeof(*compat_dqblk)) || | |
75 | get_user(data, &compat_dqblk->dqb_valid) || | |
76 | put_user(data, &dqblk->dqb_valid)) | |
77 | break; | |
78 | ret = sys_quotactl(cmd, special, id, dqblk); | |
79 | break; | |
80 | case Q_XGETQSTAT: | |
81 | fsqstat = compat_alloc_user_space(sizeof(struct fs_quota_stat)); | |
82 | compat_fsqstat = addr; | |
83 | ret = sys_quotactl(cmd, special, id, fsqstat); | |
84 | if (ret) | |
85 | break; | |
86 | ret = -EFAULT; | |
87 | /* Copying qs_version, qs_flags, qs_pad */ | |
88 | if (copy_in_user(compat_fsqstat, fsqstat, | |
89 | offsetof(struct compat_fs_quota_stat, qs_uquota))) | |
90 | break; | |
91 | /* Copying qs_uquota */ | |
92 | if (copy_in_user(&compat_fsqstat->qs_uquota, | |
93 | &fsqstat->qs_uquota, | |
94 | sizeof(compat_fsqstat->qs_uquota)) || | |
95 | get_user(data, &fsqstat->qs_uquota.qfs_nextents) || | |
96 | put_user(data, &compat_fsqstat->qs_uquota.qfs_nextents)) | |
97 | break; | |
98 | /* Copying qs_gquota */ | |
99 | if (copy_in_user(&compat_fsqstat->qs_gquota, | |
100 | &fsqstat->qs_gquota, | |
101 | sizeof(compat_fsqstat->qs_gquota)) || | |
102 | get_user(data, &fsqstat->qs_gquota.qfs_nextents) || | |
103 | put_user(data, &compat_fsqstat->qs_gquota.qfs_nextents)) | |
104 | break; | |
105 | /* Copying the rest */ | |
106 | if (copy_in_user(&compat_fsqstat->qs_incoredqs, | |
107 | &fsqstat->qs_incoredqs, | |
108 | sizeof(struct compat_fs_quota_stat) - | |
109 | offsetof(struct compat_fs_quota_stat, qs_incoredqs)) || | |
110 | get_user(xdata, &fsqstat->qs_iwarnlimit) || | |
111 | put_user(xdata, &compat_fsqstat->qs_iwarnlimit)) | |
112 | break; | |
113 | ret = 0; | |
114 | break; | |
115 | default: | |
116 | ret = sys_quotactl(cmd, special, id, addr); | |
117 | } | |
118 | return ret; | |
119 | } |