1 // SPDX-License-Identifier: GPL-2.0
3 #include <linux/syscalls.h>
4 #include <linux/compat.h>
5 #include <linux/quotaops.h>
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.
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
;
20 compat_uint_t dqb_valid
;
24 struct compat_fs_qfilestat
{
25 compat_u64 dqb_bhardlimit
;
27 compat_uint_t qfs_nextents
;
30 struct compat_fs_quota_stat
{
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
;
44 asmlinkage
long sys32_quotactl(unsigned int cmd
, const char __user
*special
,
45 qid_t id
, void __user
*addr
)
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
;
56 cmds
= cmd
>> SUBCMDSHIFT
;
60 dqblk
= compat_alloc_user_space(sizeof(struct if_dqblk
));
62 ret
= sys_quotactl(cmd
, special
, id
, dqblk
);
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
))
71 dqblk
= compat_alloc_user_space(sizeof(struct if_dqblk
));
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
))
78 ret
= sys_quotactl(cmd
, special
, id
, dqblk
);
81 fsqstat
= compat_alloc_user_space(sizeof(struct fs_quota_stat
));
82 compat_fsqstat
= addr
;
83 ret
= sys_quotactl(cmd
, special
, id
, fsqstat
);
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
)))
91 /* Copying qs_uquota */
92 if (copy_in_user(&compat_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
))
98 /* Copying qs_gquota */
99 if (copy_in_user(&compat_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
))
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
))
116 ret
= sys_quotactl(cmd
, special
, id
, addr
);