History

Merge branch 'work.quota-compat' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull compat quotactl cleanups from Al Viro: "More Christoph's compat cleanups: quotactl(2)" * 'work.quota-compat' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: quota: simplify the quotactl compat handling compat: add a compat_need_64bit_alignment_fixup() helper compat: lift compat_s64 and compat_u64 to <asm-generic/compat.h>

Linus Torvalds committed 6 years ago

Commit e18afa52 parents 85ed13e 80bdad317 files · +113 −159Browse files

Unified · Split

17 files
  1. arch/arm64/include/asm/compat.h +0 −2
  2. arch/mips/include/asm/compat.h +0 −2
  3. arch/parisc/include/asm/compat.h +0 −2
  4. arch/powerpc/include/asm/compat.h +0 −2
  5. arch/s390/include/asm/compat.h +0 −2
  6. arch/sparc/include/asm/compat.h +1 −2
  7. arch/x86/entry/syscalls/syscall_32.tbl +1 −1
  8. arch/x86/include/asm/compat.h +1 −2
  9. fs/quota/Kconfig +0 −5
  10. fs/quota/Makefile +0 −1
  11. fs/quota/compat.c +0 −120
  12. fs/quota/compat.h +34 −0
  13. fs/quota/quota.c +59 −14
  14. include/asm-generic/compat.h +8 −0
  15. include/linux/compat.h +9 −0
  16. include/linux/quotaops.h +0 −3
  17. kernel/sys_ni.c +0 −1
arch/arm64/include/asm/compat.h+0−2
@@ -35,8 +35,6 @@ typedef s32 compat_nlink_t; · 34 unmodified lines
35typedef u16 compat_ipc_pid_t;35typedef u16 compat_ipc_pid_t;
36typedef u32 compat_caddr_t;36typedef u32 compat_caddr_t;
37typedef __kernel_fsid_t compat_fsid_t;37typedef __kernel_fsid_t compat_fsid_t;
38typedef s64 compat_s64;
39typedef u64 compat_u64;
40 38
41struct compat_stat {39struct compat_stat {
42#ifdef __AARCH64EB__40#ifdef __AARCH64EB__
arch/mips/include/asm/compat.h+0−2
@@ -26,8 +26,6 @@ typedef s32 compat_caddr_t; · 25 unmodified lines
26typedef struct {26typedef struct {
27 s32 val[2];27 s32 val[2];
28} compat_fsid_t;28} compat_fsid_t;
29typedef s64 compat_s64;
30typedef u64 compat_u64;
31 29
32struct compat_stat {30struct compat_stat {
33 compat_dev_t st_dev;31 compat_dev_t st_dev;
arch/parisc/include/asm/compat.h+0−2
@@ -22,8 +22,6 @@ typedef u32 compat_dev_t; · 21 unmodified lines
22typedef u16 compat_nlink_t;22typedef u16 compat_nlink_t;
23typedef u16 compat_ipc_pid_t;23typedef u16 compat_ipc_pid_t;
24typedef u32 compat_caddr_t;24typedef u32 compat_caddr_t;
25typedef s64 compat_s64;
26typedef u64 compat_u64;
27 25
28struct compat_stat {26struct compat_stat {
29 compat_dev_t st_dev; /* dev_t is 32 bits on parisc */27 compat_dev_t st_dev; /* dev_t is 32 bits on parisc */
arch/powerpc/include/asm/compat.h+0−2
@@ -27,8 +27,6 @@ typedef s16 compat_nlink_t; · 26 unmodified lines
27typedef u16 compat_ipc_pid_t;27typedef u16 compat_ipc_pid_t;
28typedef u32 compat_caddr_t;28typedef u32 compat_caddr_t;
29typedef __kernel_fsid_t compat_fsid_t;29typedef __kernel_fsid_t compat_fsid_t;
30typedef s64 compat_s64;
31typedef u64 compat_u64;
32 30
33struct compat_stat {31struct compat_stat {
34 compat_dev_t st_dev;32 compat_dev_t st_dev;
arch/s390/include/asm/compat.h+0−2
@@ -63,8 +63,6 @@ typedef u16 compat_nlink_t; · 62 unmodified lines
63typedef u16 compat_ipc_pid_t;63typedef u16 compat_ipc_pid_t;
64typedef u32 compat_caddr_t;64typedef u32 compat_caddr_t;
65typedef __kernel_fsid_t compat_fsid_t;65typedef __kernel_fsid_t compat_fsid_t;
66typedef s64 compat_s64;
67typedef u64 compat_u64;
68 66
69typedef struct {67typedef struct {
70 u32 mask;68 u32 mask;
arch/sparc/include/asm/compat.h+1−2
@@ -21,8 +21,7 @@ typedef s16 compat_nlink_t; · 20 unmodified lines
21typedef u16 compat_ipc_pid_t;21typedef u16 compat_ipc_pid_t;
22typedef u32 compat_caddr_t;22typedef u32 compat_caddr_t;
23typedef __kernel_fsid_t compat_fsid_t;23typedef __kernel_fsid_t compat_fsid_t;
24typedef s64 compat_s64;24
25typedef u64 compat_u64;
26struct compat_stat {25struct compat_stat {
27 compat_dev_t st_dev;26 compat_dev_t st_dev;
28 compat_ino_t st_ino;27 compat_ino_t st_ino;
arch/x86/entry/syscalls/syscall_32.tbl+1−1
@@ -142,7 +142,7 @@ · 141 unmodified lines
142128 i386 init_module sys_init_module142128 i386 init_module sys_init_module
143129 i386 delete_module sys_delete_module143129 i386 delete_module sys_delete_module
144130 i386 get_kernel_syms144130 i386 get_kernel_syms
145131 i386 quotactl sys_quotactl compat_sys_quotactl32145131 i386 quotactl sys_quotactl
146132 i386 getpgid sys_getpgid146132 i386 getpgid sys_getpgid
147133 i386 fchdir sys_fchdir147133 i386 fchdir sys_fchdir
148134 i386 bdflush sys_bdflush148134 i386 bdflush sys_bdflush
arch/x86/include/asm/compat.h+1−2
@@ -27,8 +27,6 @@ typedef u16 compat_nlink_t; · 26 unmodified lines
27typedef u16 compat_ipc_pid_t;27typedef u16 compat_ipc_pid_t;
28typedef u32 compat_caddr_t;28typedef u32 compat_caddr_t;
29typedef __kernel_fsid_t compat_fsid_t;29typedef __kernel_fsid_t compat_fsid_t;
30typedef s64 __attribute__((aligned(4))) compat_s64;
31typedef u64 __attribute__((aligned(4))) compat_u64;
32 30
33struct compat_stat {31struct compat_stat {
34 compat_dev_t st_dev;32 compat_dev_t st_dev;
@@ -211,6 +209,7 @@ static inline bool in_compat_syscall(void) · 176 unmodified lines
211 return in_32bit_syscall();209 return in_32bit_syscall();
212}210}
213#define in_compat_syscall in_compat_syscall /* override the generic impl */211#define in_compat_syscall in_compat_syscall /* override the generic impl */
212#define compat_need_64bit_alignment_fixup in_ia32_syscall
214#endif213#endif
215 214
216struct compat_siginfo;215struct compat_siginfo;
fs/quota/Kconfig+0−5
@@ -70,8 +70,3 @@ config QFMT_V2 · 69 unmodified lines
70config QUOTACTL70config QUOTACTL
71 bool71 bool
72 default n72 default n
73
74config QUOTACTL_COMPAT
75 bool
76 depends on QUOTACTL && COMPAT_FOR_U64_ALIGNMENT
77 default y
fs/quota/Makefile+0−1
@@ -4,5 +4,4 @@ obj-$(CONFIG_QFMT_V1) += quota_v1.o · 3 unmodified lines
4obj-$(CONFIG_QFMT_V2) += quota_v2.o4obj-$(CONFIG_QFMT_V2) += quota_v2.o
5obj-$(CONFIG_QUOTA_TREE) += quota_tree.o5obj-$(CONFIG_QUOTA_TREE) += quota_tree.o
6obj-$(CONFIG_QUOTACTL) += quota.o kqid.o6obj-$(CONFIG_QUOTACTL) += quota.o kqid.o
7obj-$(CONFIG_QUOTACTL_COMPAT) += compat.o
8obj-$(CONFIG_QUOTA_NETLINK_INTERFACE) += netlink.o7obj-$(CONFIG_QUOTA_NETLINK_INTERFACE) += netlink.o
fs/quota/compat.c+0−120
@@ -1,120 +0,0 @@
1// SPDX-License-Identifier: GPL-2.0
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 */
11struct 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 */
24struct compat_fs_qfilestat {
25 compat_u64 dqb_bhardlimit;
26 compat_u64 qfs_nblks;
27 compat_uint_t qfs_nextents;
28};
29
30struct 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
44COMPAT_SYSCALL_DEFINE4(quotactl32, unsigned int, cmd,
45 const char __user *, special, qid_t, id,
46 void __user *, addr)
47{
48 unsigned int cmds;
49 struct if_dqblk __user *dqblk;
50 struct compat_if_dqblk __user *compat_dqblk;
51 struct fs_quota_stat __user *fsqstat;
52 struct compat_fs_quota_stat __user *compat_fsqstat;
53 compat_uint_t data;
54 u16 xdata;
55 long ret;
56
57 cmds = cmd >> SUBCMDSHIFT;
58
59 switch (cmds) {
60 case Q_GETQUOTA:
61 dqblk = compat_alloc_user_space(sizeof(struct if_dqblk));
62 compat_dqblk = addr;
63 ret = kernel_quotactl(cmd, special, id, dqblk);
64 if (ret)
65 break;
66 if (copy_in_user(compat_dqblk, dqblk, sizeof(*compat_dqblk)) ||
67 get_user(data, &dqblk->dqb_valid) ||
68 put_user(data, &compat_dqblk->dqb_valid))
69 ret = -EFAULT;
70 break;
71 case Q_SETQUOTA:
72 dqblk = compat_alloc_user_space(sizeof(struct if_dqblk));
73 compat_dqblk = addr;
74 ret = -EFAULT;
75 if (copy_in_user(dqblk, compat_dqblk, sizeof(*compat_dqblk)) ||
76 get_user(data, &compat_dqblk->dqb_valid) ||
77 put_user(data, &dqblk->dqb_valid))
78 break;
79 ret = kernel_quotactl(cmd, special, id, dqblk);
80 break;
81 case Q_XGETQSTAT:
82 fsqstat = compat_alloc_user_space(sizeof(struct fs_quota_stat));
83 compat_fsqstat = addr;
84 ret = kernel_quotactl(cmd, special, id, fsqstat);
85 if (ret)
86 break;
87 ret = -EFAULT;
88 /* Copying qs_version, qs_flags, qs_pad */
89 if (copy_in_user(compat_fsqstat, fsqstat,
90 offsetof(struct compat_fs_quota_stat, qs_uquota)))
91 break;
92 /* Copying qs_uquota */
93 if (copy_in_user(&compat_fsqstat->qs_uquota,
94 &fsqstat->qs_uquota,
95 sizeof(compat_fsqstat->qs_uquota)) ||
96 get_user(data, &fsqstat->qs_uquota.qfs_nextents) ||
97 put_user(data, &compat_fsqstat->qs_uquota.qfs_nextents))
98 break;
99 /* Copying qs_gquota */
100 if (copy_in_user(&compat_fsqstat->qs_gquota,
101 &fsqstat->qs_gquota,
102 sizeof(compat_fsqstat->qs_gquota)) ||
103 get_user(data, &fsqstat->qs_gquota.qfs_nextents) ||
104 put_user(data, &compat_fsqstat->qs_gquota.qfs_nextents))
105 break;
106 /* Copying the rest */
107 if (copy_in_user(&compat_fsqstat->qs_incoredqs,
108 &fsqstat->qs_incoredqs,
109 sizeof(struct compat_fs_quota_stat) -
110 offsetof(struct compat_fs_quota_stat, qs_incoredqs)) ||
111 get_user(xdata, &fsqstat->qs_iwarnlimit) ||
112 put_user(xdata, &compat_fsqstat->qs_iwarnlimit))
113 break;
114 ret = 0;
115 break;
116 default:
117 ret = kernel_quotactl(cmd, special, id, addr);
118 }
119 return ret;
120}
fs/quota/compat.h+34−0
@@ -0,0 +1,34 @@
1// SPDX-License-Identifier: GPL-2.0
2#include <linux/compat.h>
3
4struct compat_if_dqblk {
5 compat_u64 dqb_bhardlimit;
6 compat_u64 dqb_bsoftlimit;
7 compat_u64 dqb_curspace;
8 compat_u64 dqb_ihardlimit;
9 compat_u64 dqb_isoftlimit;
10 compat_u64 dqb_curinodes;
11 compat_u64 dqb_btime;
12 compat_u64 dqb_itime;
13 compat_uint_t dqb_valid;
14};
15
16struct compat_fs_qfilestat {
17 compat_u64 dqb_bhardlimit;
18 compat_u64 qfs_nblks;
19 compat_uint_t qfs_nextents;
20};
21
22struct compat_fs_quota_stat {
23 __s8 qs_version;
24 __u16 qs_flags;
25 __s8 qs_pad;
26 struct compat_fs_qfilestat qs_uquota;
27 struct compat_fs_qfilestat qs_gquota;
28 compat_uint_t qs_incoredqs;
29 compat_int_t qs_btimelimit;
30 compat_int_t qs_itimelimit;
31 compat_int_t qs_rtbtimelimit;
32 __u16 qs_bwarnlimit;
33 __u16 qs_iwarnlimit;
34};
fs/quota/quota.c+59−14
@@ -19,6 +19,7 @@ · 18 unmodified lines
19#include <linux/types.h>19#include <linux/types.h>
20#include <linux/writeback.h>20#include <linux/writeback.h>
21#include <linux/nospec.h>21#include <linux/nospec.h>
22#include "compat.h"
22 23
23static int check_quotactl_permission(struct super_block *sb, int type, int cmd,24static int check_quotactl_permission(struct super_block *sb, int type, int cmd,
24 qid_t id)25 qid_t id)
@@ -211,8 +212,18 @@ static int quota_getquota(struct super_block *sb, int type, qid_t id, · 186 unmodified lines
211 if (ret)212 if (ret)
212 return ret;213 return ret;
213 copy_to_if_dqblk(&idq, &fdq);214 copy_to_if_dqblk(&idq, &fdq);
214 if (copy_to_user(addr, &idq, sizeof(idq)))215
215 return -EFAULT;216 if (compat_need_64bit_alignment_fixup()) {
217 struct compat_if_dqblk __user *compat_dqblk = addr;
218
219 if (copy_to_user(compat_dqblk, &idq, sizeof(*compat_dqblk)))
220 return -EFAULT;
221 if (put_user(idq.dqb_valid, &compat_dqblk->dqb_valid))
222 return -EFAULT;
223 } else {
224 if (copy_to_user(addr, &idq, sizeof(idq)))
225 return -EFAULT;
226 }
216 return 0;227 return 0;
217}228}
218 229
@@ -277,8 +288,16 @@ static int quota_setquota(struct super_block *sb, int type, qid_t id, · 58 unmodified lines
277 struct if_dqblk idq;288 struct if_dqblk idq;
278 struct kqid qid;289 struct kqid qid;
279 290
280 if (copy_from_user(&idq, addr, sizeof(idq)))291 if (compat_need_64bit_alignment_fixup()) {
281 return -EFAULT;292 struct compat_if_dqblk __user *compat_dqblk = addr;
293
294 if (copy_from_user(&idq, compat_dqblk, sizeof(*compat_dqblk)) ||
295 get_user(idq.dqb_valid, &compat_dqblk->dqb_valid))
296 return -EFAULT;
297 } else {
298 if (copy_from_user(&idq, addr, sizeof(idq)))
299 return -EFAULT;
300 }
282 if (!sb->s_qcop->set_dqblk)301 if (!sb->s_qcop->set_dqblk)
283 return -ENOSYS;302 return -ENOSYS;
284 qid = make_kqid(current_user_ns(), type, id);303 qid = make_kqid(current_user_ns(), type, id);
@@ -382,6 +401,33 @@ static int quota_getstate(struct super_block *sb, int type, · 97 unmodified lines
382 return 0;401 return 0;
383}402}
384 403
404static int compat_copy_fs_qfilestat(struct compat_fs_qfilestat __user *to,
405 struct fs_qfilestat *from)
406{
407 if (copy_to_user(to, from, sizeof(*to)) ||
408 put_user(from->qfs_nextents, &to->qfs_nextents))
409 return -EFAULT;
410 return 0;
411}
412
413static int compat_copy_fs_quota_stat(struct compat_fs_quota_stat __user *to,
414 struct fs_quota_stat *from)
415{
416 if (put_user(from->qs_version, &to->qs_version) ||
417 put_user(from->qs_flags, &to->qs_flags) ||
418 put_user(from->qs_pad, &to->qs_pad) ||
419 compat_copy_fs_qfilestat(&to->qs_uquota, &from->qs_uquota) ||
420 compat_copy_fs_qfilestat(&to->qs_gquota, &from->qs_gquota) ||
421 put_user(from->qs_incoredqs, &to->qs_incoredqs) ||
422 put_user(from->qs_btimelimit, &to->qs_btimelimit) ||
423 put_user(from->qs_itimelimit, &to->qs_itimelimit) ||
424 put_user(from->qs_rtbtimelimit, &to->qs_rtbtimelimit) ||
425 put_user(from->qs_bwarnlimit, &to->qs_bwarnlimit) ||
426 put_user(from->qs_iwarnlimit, &to->qs_iwarnlimit))
427 return -EFAULT;
428 return 0;
429}
430
385static int quota_getxstate(struct super_block *sb, int type, void __user *addr)431static int quota_getxstate(struct super_block *sb, int type, void __user *addr)
386{432{
387 struct fs_quota_stat fqs;433 struct fs_quota_stat fqs;
@@ -390,9 +436,14 @@ static int quota_getxstate(struct super_block *sb, int type, void __user *addr) · 2 unmodified lines
390 if (!sb->s_qcop->get_state)436 if (!sb->s_qcop->get_state)
391 return -ENOSYS;437 return -ENOSYS;
392 ret = quota_getstate(sb, type, &fqs);438 ret = quota_getstate(sb, type, &fqs);
393 if (!ret && copy_to_user(addr, &fqs, sizeof(fqs)))439 if (ret)
440 return ret;
441
442 if (compat_need_64bit_alignment_fixup())
443 return compat_copy_fs_quota_stat(addr, &fqs);
444 if (copy_to_user(addr, &fqs, sizeof(fqs)))
394 return -EFAULT;445 return -EFAULT;
395 return ret;446 return 0;
396}447}
397 448
398static int quota_getstatev(struct super_block *sb, int type,449static int quota_getstatev(struct super_block *sb, int type,
@@ -816,8 +867,8 @@ static struct super_block *quotactl_block(const char __user *special, int cmd) · 417 unmodified lines
816 * calls. Maybe we need to add the process quotas etc. in the future,867 * calls. Maybe we need to add the process quotas etc. in the future,
817 * but we probably should use rlimits for that.868 * but we probably should use rlimits for that.
818 */869 */
819int kernel_quotactl(unsigned int cmd, const char __user *special,870SYSCALL_DEFINE4(quotactl, unsigned int, cmd, const char __user *, special,
820 qid_t id, void __user *addr)871 qid_t, id, void __user *, addr)
821{872{
822 uint cmds, type;873 uint cmds, type;
823 struct super_block *sb = NULL;874 struct super_block *sb = NULL;
@@ -871,9 +922,3 @@ out: · 47 unmodified lines
871 path_put(pathp);922 path_put(pathp);
872 return ret;923 return ret;
873}924}
874
875SYSCALL_DEFINE4(quotactl, unsigned int, cmd, const char __user *, special,
876 qid_t, id, void __user *, addr)
877{
878 return kernel_quotactl(cmd, special, id, addr);
879}
include/asm-generic/compat.h+8−0
@@ -22,4 +22,12 @@ typedef u32 compat_ulong_t; · 21 unmodified lines
22typedef u32 compat_uptr_t;22typedef u32 compat_uptr_t;
23typedef u32 compat_aio_context_t;23typedef u32 compat_aio_context_t;
24 24
25#ifdef CONFIG_COMPAT_FOR_U64_ALIGNMENT
26typedef s64 __attribute__((aligned(4))) compat_s64;
27typedef u64 __attribute__((aligned(4))) compat_u64;
28#else
29typedef s64 compat_s64;
30typedef u64 compat_u64;
31#endif
32
25#endif33#endif
include/linux/compat.h+9−0
@@ -910,6 +910,15 @@ static inline bool in_compat_syscall(void) { return false; } · 909 unmodified lines
910 910
911#endif /* CONFIG_COMPAT */911#endif /* CONFIG_COMPAT */
912 912
913/*
914 * Some legacy ABIs like the i386 one use less than natural alignment for 64-bit
915 * types, and will need special compat treatment for that. Most architectures
916 * don't need that special handling even for compat syscalls.
917 */
918#ifndef compat_need_64bit_alignment_fixup
919#define compat_need_64bit_alignment_fixup() false
920#endif
921
913/*922/*
914 * A pointer passed in from user mode. This should not923 * A pointer passed in from user mode. This should not
915 * be used for syscall parameters, just declare them924 * be used for syscall parameters, just declare them
include/linux/quotaops.h+0−3
@@ -27,9 +27,6 @@ static inline bool is_quota_modification(struct inode *inode, struct iattr *ia) · 26 unmodified lines
27 (ia->ia_valid & ATTR_GID && !gid_eq(ia->ia_gid, inode->i_gid));27 (ia->ia_valid & ATTR_GID && !gid_eq(ia->ia_gid, inode->i_gid));
28}28}
29 29
30int kernel_quotactl(unsigned int cmd, const char __user *special,
31 qid_t id, void __user *addr);
32
33#if defined(CONFIG_QUOTA)30#if defined(CONFIG_QUOTA)
34 31
35#define quota_error(sb, fmt, args...) \32#define quota_error(sb, fmt, args...) \
kernel/sys_ni.c+0−1
@@ -369,7 +369,6 @@ COND_SYSCALL_COMPAT(fanotify_mark); · 368 unmodified lines
369/* x86 */369/* x86 */
370COND_SYSCALL(vm86old);370COND_SYSCALL(vm86old);
371COND_SYSCALL(modify_ldt);371COND_SYSCALL(modify_ldt);
372COND_SYSCALL_COMPAT(quotactl32);
373COND_SYSCALL(vm86);372COND_SYSCALL(vm86);
374COND_SYSCALL(kexec_file_load);373COND_SYSCALL(kexec_file_load);
375 374