* [PATCH] compat: add compat functions for *at syscalls
@ 2006-02-06 23:56 Stephen Rothwell
2006-02-07 0:01 ` David S. Miller
0 siblings, 1 reply; 13+ messages in thread
From: Stephen Rothwell @ 2006-02-06 23:56 UTC (permalink / raw)
To: Andrew Morton; +Cc: LKML, Linus, DaveM, Andi Kleen
This adds compat version of all the remaining *at syscalls
so that the "dfd" arguments can be properly sign extended.
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---
arch/sparc64/kernel/systbls.S | 6 ++--
arch/x86_64/ia32/ia32entry.S | 20 +++++++------
fs/compat.c | 62 +++++++++++++++++++++++++++++++++++++++++
include/linux/compat.h | 22 +++++++++++++++
4 files changed, 97 insertions(+), 13 deletions(-)
I am not sure if sparc64 and x86_64 need these ... they will be needed
for powerpc.
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/
02d254f5a4be0abf7e661eba77e8548083d24ddc
diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S
index 2881faf..a2cc631 100644
--- a/arch/sparc64/kernel/systbls.S
+++ b/arch/sparc64/kernel/systbls.S
@@ -77,9 +77,9 @@ sys_call_table32:
/*270*/ .word sys32_io_submit, sys_io_cancel, compat_sys_io_getevents, sys32_mq_open, sys_mq_unlink
.word compat_sys_mq_timedsend, compat_sys_mq_timedreceive, compat_sys_mq_notify, compat_sys_mq_getsetattr, compat_sys_waitid
/*280*/ .word sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl, compat_sys_openat
- .word sys_mkdirat, sys_mknodat, sys_fchownat, compat_sys_futimesat, compat_sys_newfstatat
-/*285*/ .word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat
- .word sys_fchmodat, sys_faccessat, compat_sys_pselect6, compat_sys_ppoll
+ .word compat_sys_mkdirat, compat_sys_mknodat, compat_sys_fchownat, compat_sys_futimesat, compat_sys_newfstatat
+/*285*/ .word compat_sys_unlinkat, compat_sys_renameat, compat_sys_linkat, compat_sys_symlinkat, compat_sys_readlinkat
+ .word compat_sys_fchmodat, compat_sys_faccessat, compat_sys_pselect6, compat_sys_ppoll
#endif /* CONFIG_COMPAT */
diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S
index 067c0f4..2fe1c57 100644
--- a/arch/x86_64/ia32/ia32entry.S
+++ b/arch/x86_64/ia32/ia32entry.S
@@ -673,18 +673,18 @@ ia32_sys_call_table:
.quad sys_inotify_rm_watch
.quad sys_migrate_pages
.quad compat_sys_openat /* 295 */
- .quad sys_mkdirat
- .quad sys_mknodat
- .quad sys_fchownat
+ .quad compat_sys_mkdirat
+ .quad compat_sys_mknodat
+ .quad compat_sys_fchownat
.quad compat_sys_futimesat
.quad compat_sys_newfstatat /* 300 */
- .quad sys_unlinkat
- .quad sys_renameat
- .quad sys_linkat
- .quad sys_symlinkat
- .quad sys_readlinkat /* 305 */
- .quad sys_fchmodat
- .quad sys_faccessat
+ .quad compat_sys_unlinkat
+ .quad compat_sys_renameat
+ .quad compat_sys_linkat
+ .quad compat_sys_symlinkat
+ .quad compat_sys_readlinkat /* 305 */
+ .quad compat_sys_fchmodat
+ .quad compat_sys_faccessat
ia32_syscall_end:
.rept IA32_NR_syscalls-(ia32_syscall_end-ia32_sys_call_table)/8
.quad ni_syscall
diff --git a/fs/compat.c b/fs/compat.c
index 70c5af4..55141a9 100644
--- a/fs/compat.c
+++ b/fs/compat.c
@@ -1331,6 +1331,68 @@ compat_sys_openat(unsigned int dfd, cons
return do_sys_open(dfd, filename, flags, mode);
}
+asmlinkage long compat_sys_mkdirat(unsigned int dfd,
+ const char __user * pathname, int mode)
+{
+ return sys_mkdirat(dfd, pathname, mode);
+}
+
+asmlinkage long compat_sys_mknodat(unsigned int dfd,
+ const char __user *filename, int mode, unsigned dev)
+{
+ return sys_mknodat(dfd, filename, mode, dev);
+}
+
+asmlinkage long compat_sys_fchownat(unsigned int dfd,
+ const char __user *filename, uid_t user, gid_t group, int flag)
+{
+ return sys_fchownat(dfd, filename, user, group, flag);
+}
+
+asmlinkage long compat_sys_unlinkat(unsigned int dfd,
+ const char __user *pathname, int flag)
+{
+ return sys_unlinkat(dfd, pathname, flag);
+}
+
+asmlinkage long compat_sys_renameat(unsigned int olddfd,
+ const char __user *oldname, unsigned int newdfd,
+ const char __user *newname)
+{
+ return sys_renameat(olddfd, oldname, newdfd, newname);
+}
+
+asmlinkage long compat_sys_linkat(unsigned int olddfd,
+ const char __user *oldname, unsigned int newdfd,
+ const char __user *newname)
+{
+ return sys_linkat(olddfd, oldname, newdfd, newname);
+}
+
+asmlinkage long compat_sys_symlinkat(const char __user *oldname,
+ unsigned int newdfd, const char __user *newname)
+{
+ return sys_symlinkat(oldname, newdfd, newname);
+}
+
+asmlinkage long compat_sys_readlinkat(unsigned int dfd,
+ const char __user *path, char __user *buf, int bufsiz)
+{
+ return sys_readlinkat(dfd, path, buf, bufsiz);
+}
+
+asmlinkage long compat_sys_fchmodat(unsigned int dfd,
+ const char __user *filename, mode_t mode)
+{
+ return sys_fchmodat(dfd, filename, mode);
+}
+
+asmlinkage long compat_sys_faccessat(unsigned int dfd,
+ const char __user *filename, int mode)
+{
+ return sys_faccessat(dfd, filename, mode);
+}
+
/*
* compat_count() counts the number of arguments/envelopes. It is basically
* a copy of count() from fs/exec.c, except that it works with 32 bit argv
diff --git a/include/linux/compat.h b/include/linux/compat.h
index 2d7e7f1..b501201 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -168,6 +168,28 @@ asmlinkage long compat_sys_newfstatat(un
int flag);
asmlinkage long compat_sys_openat(unsigned int dfd, const char __user *filename,
int flags, int mode);
+asmlinkage long compat_sys_mkdirat(unsigned int dfd,
+ const char __user * pathname, int mode);
+asmlinkage long compat_sys_mknodat(unsigned int dfd,
+ const char __user *filename, int mode, unsigned dev);
+asmlinkage long compat_sys_fchownat(unsigned int dfd,
+ const char __user *filename, uid_t user, gid_t group, int flag);
+asmlinkage long compat_sys_unlinkat(unsigned int dfd,
+ const char __user *pathname, int flag);
+asmlinkage long compat_sys_renameat(unsigned int olddfd,
+ const char __user *oldname, unsigned int newdfd,
+ const char __user *newname);
+asmlinkage long compat_sys_linkat(unsigned int olddfd,
+ const char __user *oldname, unsigned int newdfd,
+ const char __user *newname);
+asmlinkage long compat_sys_symlinkat(const char __user *oldname,
+ unsigned int newdfd, const char __user *newname);
+asmlinkage long compat_sys_readlinkat(unsigned int dfd,
+ const char __user *path, char __user *buf, int bufsiz);
+asmlinkage long compat_sys_fchmodat(unsigned int dfd,
+ const char __user *filename, mode_t mode);
+asmlinkage long compat_sys_faccessat(unsigned int dfd,
+ const char __user *filename, int mode);
#endif /* CONFIG_COMPAT */
#endif /* _LINUX_COMPAT_H */
--
1.1.5
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH] compat: add compat functions for *at syscalls
2006-02-06 23:56 [PATCH] compat: add compat functions for *at syscalls Stephen Rothwell
@ 2006-02-07 0:01 ` David S. Miller
2006-02-07 0:27 ` Stephen Rothwell
` (2 more replies)
0 siblings, 3 replies; 13+ messages in thread
From: David S. Miller @ 2006-02-07 0:01 UTC (permalink / raw)
To: sfr; +Cc: akpm, linux-kernel, torvalds, ak
From: Stephen Rothwell <sfr@canb.auug.org.au>
Date: Tue, 7 Feb 2006 10:56:31 +1100
> This adds compat version of all the remaining *at syscalls
> so that the "dfd" arguments can be properly sign extended.
>
> Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
I do the sign extension with tiny stubs in arch/sparc64/kernel/sys32.S
so that the arg frobbing does not consume a stack frame, which is what
happens if you do this in C code.
We need to revisit this at some point and make a way for all
compat platforms to do this with a portable table of some kind
that expands a bunch of macros defined by the platform.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] compat: add compat functions for *at syscalls
2006-02-07 0:01 ` David S. Miller
@ 2006-02-07 0:27 ` Stephen Rothwell
2006-02-07 1:15 ` Linus Torvalds
2006-02-07 8:43 ` David S. Miller
2006-02-07 6:40 ` Stephen Rothwell
2006-02-07 9:25 ` Andi Kleen
2 siblings, 2 replies; 13+ messages in thread
From: Stephen Rothwell @ 2006-02-07 0:27 UTC (permalink / raw)
To: David S. Miller; +Cc: akpm, linux-kernel, torvalds, ak
On Mon, 06 Feb 2006 16:01:40 -0800 (PST) "David S. Miller" <davem@davemloft.net> wrote:
>
> I do the sign extension with tiny stubs in arch/sparc64/kernel/sys32.S
> so that the arg frobbing does not consume a stack frame, which is what
> happens if you do this in C code.
In which case you need to to stubs for all the *at syscalls.
> We need to revisit this at some point and make a way for all
> compat platforms to do this with a portable table of some kind
> that expands a bunch of macros defined by the platform.
*If* we do get is_compat_task(), what would be you reaction to something
like this:
diff --git a/fs/namei.c b/fs/namei.c
index faf61c3..83d6cd1 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1877,6 +1877,8 @@ asmlinkage long sys_mkdirat(int dfd, con
int error = 0;
char * tmp;
+ if (is_compat_task())
+ dfd = compat_sign_extend(dfd);
tmp = getname(pathname);
error = PTR_ERR(tmp);
if (!IS_ERR(tmp)) {
diff --git a/include/linux/compat.h b/include/linux/compat.h
index f9ca534..e6c9db6 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -162,4 +162,10 @@ int get_compat_sigevent(struct sigevent
const struct compat_sigevent __user *u_event);
#endif /* CONFIG_COMPAT */
+
+static inline int compat_sign_extend(long i)
+{
+ return i;
+}
+
#endif /* _LINUX_COMPAT_H */
On powerpc64, this is sufficient to get the 32 to 64 bit sign extension
we need done in place.
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH] compat: add compat functions for *at syscalls
2006-02-07 0:27 ` Stephen Rothwell
@ 2006-02-07 1:15 ` Linus Torvalds
2006-02-07 8:44 ` David S. Miller
2006-02-07 8:43 ` David S. Miller
1 sibling, 1 reply; 13+ messages in thread
From: Linus Torvalds @ 2006-02-07 1:15 UTC (permalink / raw)
To: Stephen Rothwell; +Cc: David S. Miller, akpm, linux-kernel, ak
On Tue, 7 Feb 2006, Stephen Rothwell wrote:
>
> *If* we do get is_compat_task(), what would be you reaction to something
> like this:
>
> diff --git a/fs/namei.c b/fs/namei.c
> index faf61c3..83d6cd1 100644
> --- a/fs/namei.c
> +++ b/fs/namei.c
> @@ -1877,6 +1877,8 @@ asmlinkage long sys_mkdirat(int dfd, con
> int error = 0;
> char * tmp;
>
> + if (is_compat_task())
> + dfd = compat_sign_extend(dfd);
Oh f*ck, why do people do ugly code like this?
That's just about the nastiest thing I've ever seen.
If you want to go this way, do it with
asmlinkage long sys_mkdirat(long __dfd, ..
{
int dfd = __dfd;
which is at least unconditional.
The thing is unconditionally doing the "skip upper bits" is _faster_ then
the conditional test to see if you even need it.
Conditionalizing code like this is EVIL and STUPID.
However, what I suspect David was actually suggesting was to just have
some trivial for just the compat functions. You can generate them
automatically based on
- function name
- signedness/unsignedness of each argument
with some preprocessor hackery.
So each architecture could have the following #defines:
#define SARG(x) "sext " x "," x // Whatever the architecture asm is for sign-extending a register
#define UARG(x) "zext " x "," x
#define JMP(x) "jmp " x
#define ARG1 "%r3"
#define ARG2 "%r4"
#define ARG3 "%r5"
...
and then there would be a generic helper header:
#define compat_fn1(n, x1) \
asm("compat_" ## n ":\n\t" \
x1(ARG1) "\n\t" \
JMP(##n))
#define compat_fn2(n, x1, x2) \
asm("compat_" ## n ":\n\t" \
x1(ARG1) "\n\t" \
x2(ARG2) "\n\t" \
JMP(##n))
#define compat_fn3(n, x1, x2) \
asm("compat_" ## n ":\n\t" \
x1(ARG1) "\n\t" \
x2(ARG2) "\n\t" \
x3(ARG3) "\n\t" \
JMP(##n))
... fn4..fn6 ..
compat_fn4(sys_semctl, SARG, SARG, SARG, UARG);
compat_fn6(sys_waitif, SARG, UARG, UARG, SARG, UARG);
..
you get the idea - automatically generated stub assembly functions that
zero-extend or sign-extend the arguments properly. Each architecture would
need just a minimal set of "helper defines" to create the per-architecture
assembly language.
(And no, I didn't test the above at all).
Linus
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] compat: add compat functions for *at syscalls
2006-02-07 0:01 ` David S. Miller
2006-02-07 0:27 ` Stephen Rothwell
@ 2006-02-07 6:40 ` Stephen Rothwell
2006-02-07 9:31 ` Heiko Carstens
2006-02-07 9:25 ` Andi Kleen
2 siblings, 1 reply; 13+ messages in thread
From: Stephen Rothwell @ 2006-02-07 6:40 UTC (permalink / raw)
To: David S. Miller; +Cc: akpm, linux-kernel, torvalds, ak, linuxppc64-dev, paulus
[-- Attachment #1: Type: text/plain, Size: 11071 bytes --]
On Mon, 06 Feb 2006 16:01:40 -0800 (PST) "David S. Miller" <davem@davemloft.net> wrote:
>
> From: Stephen Rothwell <sfr@canb.auug.org.au>
> Date: Tue, 7 Feb 2006 10:56:31 +1100
>
> > This adds compat version of all the remaining *at syscalls
> > so that the "dfd" arguments can be properly sign extended.
> >
> > Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
>
> I do the sign extension with tiny stubs in arch/sparc64/kernel/sys32.S
> so that the arg frobbing does not consume a stack frame, which is what
> happens if you do this in C code.
>
> We need to revisit this at some point and make a way for all
> compat platforms to do this with a portable table of some kind
> that expands a bunch of macros defined by the platform.
How about the following (modifiying Linus' suggestion and copying what
sparc64 already does)?
The assumption is that all arguments have been zero extended by the compat
syscall entry code, so we just sign extend those that need it.
I am not sure of the sparc64 code below, s390 doesn't seem to follow our
"all arguments are zero extended" assumption and x86_64 may not need any
of these wrappers anyway.
It may be that we would be better following Linus's suggestion of
generating stubs for all of the compat syscalls.
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/
Subject: [PATCH] compat: introduce kernel/compat_wrapper.S
and the necessary compat_wrapper.h with implementations
for powerpc and sparc64.
compat_wrapper.S builds wrappers for those syscalls that
require sign extension for some of their arguments.
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---
arch/sparc64/kernel/systbls.S | 6 +++---
include/asm-ia64/compat_wrapper.h | 15 +++++++++++++++
include/asm-mips/compat_wrapper.h | 15 +++++++++++++++
include/asm-parisc/compat_wrapper.h | 15 +++++++++++++++
include/asm-powerpc/compat_wrapper.h | 28 ++++++++++++++++++++++++++++
include/asm-s390/compat_wrapper.h | 15 +++++++++++++++
include/asm-sparc64/compat_wrapper.h | 33 +++++++++++++++++++++++++++++++++
include/asm-x86_64/compat_wrapper.h | 15 +++++++++++++++
include/linux/compat.h | 22 ++++++++++++++++++++++
kernel/Makefile | 2 +-
kernel/compat_wrapper.S | 18 ++++++++++++++++++
11 files changed, 180 insertions(+), 4 deletions(-)
create mode 100644 include/asm-ia64/compat_wrapper.h
create mode 100644 include/asm-mips/compat_wrapper.h
create mode 100644 include/asm-parisc/compat_wrapper.h
create mode 100644 include/asm-powerpc/compat_wrapper.h
create mode 100644 include/asm-s390/compat_wrapper.h
create mode 100644 include/asm-sparc64/compat_wrapper.h
create mode 100644 include/asm-x86_64/compat_wrapper.h
create mode 100644 kernel/compat_wrapper.S
1cffeae9ae628af849952cf90fbfca1d98befb97
diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S
index 2881faf..a2cc631 100644
--- a/arch/sparc64/kernel/systbls.S
+++ b/arch/sparc64/kernel/systbls.S
@@ -77,9 +77,9 @@ sys_call_table32:
/*270*/ .word sys32_io_submit, sys_io_cancel, compat_sys_io_getevents, sys32_mq_open, sys_mq_unlink
.word compat_sys_mq_timedsend, compat_sys_mq_timedreceive, compat_sys_mq_notify, compat_sys_mq_getsetattr, compat_sys_waitid
/*280*/ .word sys_ni_syscall, sys_add_key, sys_request_key, sys_keyctl, compat_sys_openat
- .word sys_mkdirat, sys_mknodat, sys_fchownat, compat_sys_futimesat, compat_sys_newfstatat
-/*285*/ .word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat
- .word sys_fchmodat, sys_faccessat, compat_sys_pselect6, compat_sys_ppoll
+ .word compat_sys_mkdirat, compat_sys_mknodat, compat_sys_fchownat, compat_sys_futimesat, compat_sys_newfstatat
+/*285*/ .word compat_sys_unlinkat, compat_sys_renameat, compat_sys_linkat, compat_sys_symlinkat, compat_sys_readlinkat
+ .word compat_sys_fchmodat, compat_sys_faccessat, compat_sys_pselect6, compat_sys_ppoll
#endif /* CONFIG_COMPAT */
diff --git a/include/asm-ia64/compat_wrapper.h b/include/asm-ia64/compat_wrapper.h
new file mode 100644
index 0000000..f82befc
--- /dev/null
+++ b/include/asm-ia64/compat_wrapper.h
@@ -0,0 +1,15 @@
+/*
+ * Definitions used to generate the sign extending stubs
+ * for compat syscalls
+ */
+
+#define ARG1
+#define ARG2
+#define ARG3
+#define ARG4
+#define ARG5
+#define ARG6
+
+#define compat_fn1(fn, arg)
+
+#define compat_fn2(fn, arg1, arg2)
diff --git a/include/asm-mips/compat_wrapper.h b/include/asm-mips/compat_wrapper.h
new file mode 100644
index 0000000..f82befc
--- /dev/null
+++ b/include/asm-mips/compat_wrapper.h
@@ -0,0 +1,15 @@
+/*
+ * Definitions used to generate the sign extending stubs
+ * for compat syscalls
+ */
+
+#define ARG1
+#define ARG2
+#define ARG3
+#define ARG4
+#define ARG5
+#define ARG6
+
+#define compat_fn1(fn, arg)
+
+#define compat_fn2(fn, arg1, arg2)
diff --git a/include/asm-parisc/compat_wrapper.h b/include/asm-parisc/compat_wrapper.h
new file mode 100644
index 0000000..f82befc
--- /dev/null
+++ b/include/asm-parisc/compat_wrapper.h
@@ -0,0 +1,15 @@
+/*
+ * Definitions used to generate the sign extending stubs
+ * for compat syscalls
+ */
+
+#define ARG1
+#define ARG2
+#define ARG3
+#define ARG4
+#define ARG5
+#define ARG6
+
+#define compat_fn1(fn, arg)
+
+#define compat_fn2(fn, arg1, arg2)
diff --git a/include/asm-powerpc/compat_wrapper.h b/include/asm-powerpc/compat_wrapper.h
new file mode 100644
index 0000000..9bc0669
--- /dev/null
+++ b/include/asm-powerpc/compat_wrapper.h
@@ -0,0 +1,28 @@
+/*
+ * Definitions used to generate the sign extending stubs
+ * for compat syscalls
+ *
+ * Copyright (C) 2006 Stephen Rothwell, IBM Corp
+ */
+
+#define ARG1 %r3
+#define ARG2 %r4
+#define ARG3 %r5
+#define ARG4 %r6
+#define ARG5 %r7
+#define ARG6 %r8
+
+#define compat_fn1(fn, arg) \
+ .text; \
+ .global .compat_sys_ ## fn; \
+.compat_sys_ ## fn: \
+ extsw arg, arg; \
+ b .sys_ ## fn
+
+#define compat_fn2(fn, arg1, arg2) \
+ .text; \
+ .global .compat_sys_ ## fn; \
+.compat_sys_ ## fn: \
+ extsw arg1, arg1; \
+ extsw arg2, arg2; \
+ b .sys_ ## fn
diff --git a/include/asm-s390/compat_wrapper.h b/include/asm-s390/compat_wrapper.h
new file mode 100644
index 0000000..f82befc
--- /dev/null
+++ b/include/asm-s390/compat_wrapper.h
@@ -0,0 +1,15 @@
+/*
+ * Definitions used to generate the sign extending stubs
+ * for compat syscalls
+ */
+
+#define ARG1
+#define ARG2
+#define ARG3
+#define ARG4
+#define ARG5
+#define ARG6
+
+#define compat_fn1(fn, arg)
+
+#define compat_fn2(fn, arg1, arg2)
diff --git a/include/asm-sparc64/compat_wrapper.h b/include/asm-sparc64/compat_wrapper.h
new file mode 100644
index 0000000..42afb2c
--- /dev/null
+++ b/include/asm-sparc64/compat_wrapper.h
@@ -0,0 +1,33 @@
+/*
+ * Definitions used to generate the sign extending stubs
+ * for compat syscalls
+ *
+ * Copyright (C) 2006 Stephen Rothwell, IBM Corp
+ * Based on arch/sparc64/kernel/sys32.S
+ */
+
+#define ARG1 %o0
+#define ARG2 %o1
+#define ARG3 %o2
+#define ARG4 %o3
+#define ARG5 %o4
+#define ARG6 %o5
+
+#define compat_fn1(fn, arg) \
+ .text; \
+ .align 32; \
+ .globl compat_sys_ ## fn; \
+compat_sys_ ## fn: \
+ sethi %hi(sys_ ## fn), %g1; \
+ jmpl %g1 + %lo(sys_ ## fn), %g0; \
+ sra arg, 0, arg
+
+#define compat_fn2(fn, arg1, arg2) \
+ .text; \
+ .align 32; \
+ .globl compat_sys_ ## fn; \
+compat_sys_ ## fn: \
+ sethi %hi(sys_ ## fn), %g1; \
+ sra arg1, 0, arg1; \
+ jmpl %g1 + %lo(sys_ ## fn), %g0; \
+ sra arg2, 0, arg2
diff --git a/include/asm-x86_64/compat_wrapper.h b/include/asm-x86_64/compat_wrapper.h
new file mode 100644
index 0000000..f82befc
--- /dev/null
+++ b/include/asm-x86_64/compat_wrapper.h
@@ -0,0 +1,15 @@
+/*
+ * Definitions used to generate the sign extending stubs
+ * for compat syscalls
+ */
+
+#define ARG1
+#define ARG2
+#define ARG3
+#define ARG4
+#define ARG5
+#define ARG6
+
+#define compat_fn1(fn, arg)
+
+#define compat_fn2(fn, arg1, arg2)
diff --git a/include/linux/compat.h b/include/linux/compat.h
index 2d7e7f1..b501201 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -168,6 +168,28 @@ asmlinkage long compat_sys_newfstatat(un
int flag);
asmlinkage long compat_sys_openat(unsigned int dfd, const char __user *filename,
int flags, int mode);
+asmlinkage long compat_sys_mkdirat(unsigned int dfd,
+ const char __user * pathname, int mode);
+asmlinkage long compat_sys_mknodat(unsigned int dfd,
+ const char __user *filename, int mode, unsigned dev);
+asmlinkage long compat_sys_fchownat(unsigned int dfd,
+ const char __user *filename, uid_t user, gid_t group, int flag);
+asmlinkage long compat_sys_unlinkat(unsigned int dfd,
+ const char __user *pathname, int flag);
+asmlinkage long compat_sys_renameat(unsigned int olddfd,
+ const char __user *oldname, unsigned int newdfd,
+ const char __user *newname);
+asmlinkage long compat_sys_linkat(unsigned int olddfd,
+ const char __user *oldname, unsigned int newdfd,
+ const char __user *newname);
+asmlinkage long compat_sys_symlinkat(const char __user *oldname,
+ unsigned int newdfd, const char __user *newname);
+asmlinkage long compat_sys_readlinkat(unsigned int dfd,
+ const char __user *path, char __user *buf, int bufsiz);
+asmlinkage long compat_sys_fchmodat(unsigned int dfd,
+ const char __user *filename, mode_t mode);
+asmlinkage long compat_sys_faccessat(unsigned int dfd,
+ const char __user *filename, int mode);
#endif /* CONFIG_COMPAT */
#endif /* _LINUX_COMPAT_H */
diff --git a/kernel/Makefile b/kernel/Makefile
index 4ae0fbd..a0679c4 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -22,7 +22,7 @@ obj-$(CONFIG_KALLSYMS) += kallsyms.o
obj-$(CONFIG_PM) += power/
obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
obj-$(CONFIG_KEXEC) += kexec.o
-obj-$(CONFIG_COMPAT) += compat.o
+obj-$(CONFIG_COMPAT) += compat.o compat_wrapper.o
obj-$(CONFIG_CPUSETS) += cpuset.o
obj-$(CONFIG_IKCONFIG) += configs.o
obj-$(CONFIG_STOP_MACHINE) += stop_machine.o
diff --git a/kernel/compat_wrapper.S b/kernel/compat_wrapper.S
new file mode 100644
index 0000000..da009eb
--- /dev/null
+++ b/kernel/compat_wrapper.S
@@ -0,0 +1,18 @@
+/*
+ * Copyright (C) 2006 Stephen Rothwell, IBM Corp
+ *
+ * this file will generate compat_ wrapper functions for
+ * syscalls that need sign extension for some of their arguments
+ */
+#include <asm/compat_wrapper.h>
+
+compat_fn1(mkdirat, ARG1)
+compat_fn1(mknodat, ARG1)
+compat_fn1(fchownat, ARG1)
+compat_fn1(unlinkat, ARG1)
+compat_fn2(renameat, ARG1, ARG3)
+compat_fn2(linkat, ARG1, ARG3)
+compat_fn1(symlinkat, ARG2)
+compat_fn1(readlinkat, ARG1)
+compat_fn1(fchmodat, ARG1)
+compat_fn1(faccessat, ARG1)
--
1.1.5
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH] compat: add compat functions for *at syscalls
2006-02-07 0:27 ` Stephen Rothwell
2006-02-07 1:15 ` Linus Torvalds
@ 2006-02-07 8:43 ` David S. Miller
2006-02-07 9:39 ` Andi Kleen
1 sibling, 1 reply; 13+ messages in thread
From: David S. Miller @ 2006-02-07 8:43 UTC (permalink / raw)
To: sfr; +Cc: akpm, linux-kernel, torvalds, ak
From: Stephen Rothwell <sfr@canb.auug.org.au>
Date: Tue, 7 Feb 2006 11:27:13 +1100
> *If* we do get is_compat_task(), what would be you reaction to something
> like this:
...
> + if (is_compat_task())
> + dfd = compat_sign_extend(dfd);
A load and a test is more expensive than the assembler
stubs where we _know_ we are compat.
The alternative suggestions get less and less efficient :-) My whole
desire is to optimize this as much as possible, without the overhead
of an extra stack frame or "is_compat_task()" kinds of runtime tests.
Really, the way to do this is to have a description header file, that
does stuff like:
SIGN1(STUB_NAME, REAL_SYSCALL, ARG1_TO_EXTEND)
SIGN2(STUB_NAME, REAL_SYSCALL, ARG1_TO_EXTEND, ARG2_TO_EXTEND)
etc. etc. for each syscall that only needs sign extension compat
handling, and the platform provides definitions of these macros which
expand the above as appropriate. Use arch/sparc64/kernel/sys32.S as a
guide.
So for sys_exit_group you'd list something like:
SIGN1(sys32_exit_group, sys_exit_group, ARG0)
"ARG0" would get defined to whatever register mnemonic the
first argument to a function gets passed into, ARG1 to the
second, etc. So on Sparc64 that would be:
#define ARG0 %o0
#define ARG1 %o1
#define ARG2 %o2
#define ARG3 %o3
#define ARG4 %o4
#define ARG5 %o5
and you'd use "sys32_exit_group" in the compat syscall table. The
SIGN1 definition on sparc64 would be exactly what it is right now
in that sys32.S file.
Such a header can be use to generate stubs on every platform.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] compat: add compat functions for *at syscalls
2006-02-07 1:15 ` Linus Torvalds
@ 2006-02-07 8:44 ` David S. Miller
0 siblings, 0 replies; 13+ messages in thread
From: David S. Miller @ 2006-02-07 8:44 UTC (permalink / raw)
To: torvalds; +Cc: sfr, akpm, linux-kernel, ak
From: Linus Torvalds <torvalds@osdl.org>
Date: Mon, 6 Feb 2006 17:15:23 -0800 (PST)
> Oh f*ck, why do people do ugly code like this?
>
> That's just about the nastiest thing I've ever seen.
I totally agree.
>
> However, what I suspect David was actually suggesting was to just have
> some trivial for just the compat functions. You can generate them
> automatically based on
> - function name
> - signedness/unsignedness of each argument
> with some preprocessor hackery.
>
> So each architecture could have the following #defines:
Exactly.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] compat: add compat functions for *at syscalls
2006-02-07 0:01 ` David S. Miller
2006-02-07 0:27 ` Stephen Rothwell
2006-02-07 6:40 ` Stephen Rothwell
@ 2006-02-07 9:25 ` Andi Kleen
2 siblings, 0 replies; 13+ messages in thread
From: Andi Kleen @ 2006-02-07 9:25 UTC (permalink / raw)
To: David S. Miller; +Cc: sfr, akpm, linux-kernel, torvalds
On Tuesday 07 February 2006 01:01, David S. Miller wrote:
> From: Stephen Rothwell <sfr@canb.auug.org.au>
> Date: Tue, 7 Feb 2006 10:56:31 +1100
>
> > This adds compat version of all the remaining *at syscalls
> > so that the "dfd" arguments can be properly sign extended.
> >
> > Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
>
> I do the sign extension with tiny stubs in arch/sparc64/kernel/sys32.S
> so that the arg frobbing does not consume a stack frame, which is what
> happens if you do this in C code.
To be honest - do you really think that matters? Even a Niagara will
go through that in no time @)
And on x86-64 it should be as efficient as an equivalent assembly function.
-Andi
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] compat: add compat functions for *at syscalls
2006-02-07 6:40 ` Stephen Rothwell
@ 2006-02-07 9:31 ` Heiko Carstens
2006-02-07 13:29 ` Heiko Carstens
0 siblings, 1 reply; 13+ messages in thread
From: Heiko Carstens @ 2006-02-07 9:31 UTC (permalink / raw)
To: Stephen Rothwell
Cc: David S. Miller, akpm, linux-kernel, torvalds, ak, linuxppc64-dev,
paulus
> How about the following (modifiying Linus' suggestion and copying what
> sparc64 already does)?
>
> The assumption is that all arguments have been zero extended by the compat
> syscall entry code, so we just sign extend those that need it.
>
> I am not sure of the sparc64 code below, s390 doesn't seem to follow our
> "all arguments are zero extended" assumption and x86_64 may not need any
> of these wrappers anyway.
On s390 we do already sign extension for int/long and zero extension for
the unsigned parameters. Even though I wasn't aware that we should do zero
extension for _all_ parameters of the compat system calls, regardless of
their type.
In addition we must do pointer conversion to 64 bit, since the compat tasks
have the most significant bit set (to distinguish between 24- and 31-bit
addressing mode).
Therefore I think Linus' suggestion with having something like
compat_fn6(sys_waitif, SARG, UARG, UARG, SARG, UARG);
would be better. Just that we would need something for pointers as well.
And to make things just a bit more complicated: only the first five
parameters are in registers. Number six and the following are already on
the stack. E.g. the compat wrapper for the futex syscall would need extra
assembly code to do conversion on the stack.
Maybe having defines like SARG1..SARG6 that would define assembly code
instead of the register would do the job.
Thanks,
Heiko
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] compat: add compat functions for *at syscalls
2006-02-07 8:43 ` David S. Miller
@ 2006-02-07 9:39 ` Andi Kleen
2006-02-07 10:56 ` David S. Miller
0 siblings, 1 reply; 13+ messages in thread
From: Andi Kleen @ 2006-02-07 9:39 UTC (permalink / raw)
To: David S. Miller; +Cc: sfr, akpm, linux-kernel, torvalds
On Tuesday 07 February 2006 09:43, David S. Miller wrote:
>
> The alternative suggestions get less and less efficient :-) My whole
> desire is to optimize this as much as possible, without the overhead
> of an extra stack frame or "is_compat_task()" kinds of runtime tests.
My impression is you're doing a lot of ugly code here just to
work around some pecularity of the sparc gcc.
-Andi
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] compat: add compat functions for *at syscalls
2006-02-07 9:39 ` Andi Kleen
@ 2006-02-07 10:56 ` David S. Miller
0 siblings, 0 replies; 13+ messages in thread
From: David S. Miller @ 2006-02-07 10:56 UTC (permalink / raw)
To: ak; +Cc: sfr, akpm, linux-kernel, torvalds
From: Andi Kleen <ak@suse.de>
Date: Tue, 7 Feb 2006 10:39:52 +0100
> My impression is you're doing a lot of ugly code here just to
> work around some pecularity of the sparc gcc.
No, I'm simply sign extending arguments that need to
be signed. PPC and other platforms do this too, just with
C code. Actually I think s390x uses assembler stubs as well.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] compat: add compat functions for *at syscalls
2006-02-07 9:31 ` Heiko Carstens
@ 2006-02-07 13:29 ` Heiko Carstens
2006-02-07 22:57 ` David S. Miller
0 siblings, 1 reply; 13+ messages in thread
From: Heiko Carstens @ 2006-02-07 13:29 UTC (permalink / raw)
To: Stephen Rothwell
Cc: David S. Miller, akpm, linux-kernel, torvalds, ak, linuxppc64-dev,
paulus
> Therefore I think Linus' suggestion with having something like
>
> compat_fn6(sys_waitif, SARG, UARG, UARG, SARG, UARG);
>
> would be better. Just that we would need something for pointers as well.
> And to make things just a bit more complicated: only the first five
> parameters are in registers. Number six and the following are already on
> the stack. E.g. the compat wrapper for the futex syscall would need extra
> assembly code to do conversion on the stack.
>
> Maybe having defines like SARG1..SARG6 that would define assembly code
> instead of the register would do the job.
Ah, stupid me... the SARG define defines assembly code of course. Just
that we would need different defines for arguments that are in registers
or on the stack. Is s390 the only architecture that has argument six on
the stack?
Heiko
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH] compat: add compat functions for *at syscalls
2006-02-07 13:29 ` Heiko Carstens
@ 2006-02-07 22:57 ` David S. Miller
0 siblings, 0 replies; 13+ messages in thread
From: David S. Miller @ 2006-02-07 22:57 UTC (permalink / raw)
To: heiko.carstens
Cc: sfr, akpm, linux-kernel, torvalds, ak, linuxppc64-dev, paulus
From: Heiko Carstens <heiko.carstens@de.ibm.com>
Date: Tue, 7 Feb 2006 14:29:49 +0100
> Ah, stupid me... the SARG define defines assembly code of course. Just
> that we would need different defines for arguments that are in registers
> or on the stack. Is s390 the only architecture that has argument six on
> the stack?
If I remember correctly, o32 mips binaries put arg 6 on the stack
too.
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2006-02-07 22:57 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-02-06 23:56 [PATCH] compat: add compat functions for *at syscalls Stephen Rothwell
2006-02-07 0:01 ` David S. Miller
2006-02-07 0:27 ` Stephen Rothwell
2006-02-07 1:15 ` Linus Torvalds
2006-02-07 8:44 ` David S. Miller
2006-02-07 8:43 ` David S. Miller
2006-02-07 9:39 ` Andi Kleen
2006-02-07 10:56 ` David S. Miller
2006-02-07 6:40 ` Stephen Rothwell
2006-02-07 9:31 ` Heiko Carstens
2006-02-07 13:29 ` Heiko Carstens
2006-02-07 22:57 ` David S. Miller
2006-02-07 9:25 ` Andi Kleen
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox