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