Commit 681569ac authored by Hirokazu Takata's avatar Hirokazu Takata Committed by Linus Torvalds

[PATCH] m32r: employ new kernel API/ABI

We, Linux/M32R project members, decided to change the kernel API/ABI.  This
modification is not small, but if we don't change it now, perhaps we have
no chance to change them hereafter.

* Why change the m32r kernel API/ABI?
- The m32r port has many old-style syscall interfaces,
  because we made m32r port refering to the other traditional archs.
  Some old syscalls are no longer used or can be safely removed
  by upgrading the GNU C library.
- To make the m32r kernel more secure, it is preferable to prevent
  stack region from being executed. (e.g. stack overflow)

* API/ABI changes
- include/asm-m32r/unistd.h: Upgrade to the new kernel API.
- arch/m32r/entry.S: Minimum update to the new ABI.
- Don't use UID16 syscalls.
- To make stack noexecutable:
  1) Don't use trampoline for signal handlers for kernel space (cf. sparc64):
    sys_signal: remove.
    sys_sigaction, sys_rt_sigaction: use glibc's restorer.
  2) Don't generate trampoline code by GCC in userspace:
    Support non-executable stack by the m32r gcc.
    --> done (for gcc-3.4.3/gcc-4.0)

* New userland
- This modification does *not* keep backward compatibility.
  So we have been prepared new userland, based on the new API/ABI.
  Already, more than 200 new Debian deb binary packages are available
  on the Linux/M32R site:
  http://debian.linux-m32r.org/dists/04_ordovician/ (for this new ABI)
Signed-off-by: default avatarNIIBE Yutaka <gniibe@fsij.org>
Signed-off-by: default avatarHirokazu Takata <takata@linux-m32r.org>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 67166365
......@@ -14,7 +14,7 @@ config SBUS
config UID16
bool
default y
default n
config GENERIC_ISA_DMA
bool
......
......@@ -725,25 +725,25 @@ ENTRY(sys_call_table)
.long sys_time
.long sys_mknod
.long sys_chmod /* 15 */
.long sys_lchown
.long sys_ni_syscall /* lchown16 syscall holder */
.long sys_ni_syscall /* old break syscall holder */
.long sys_stat
.long sys_ni_syscall /* old stat syscall holder */
.long sys_lseek
.long sys_getpid /* 20 */
.long sys_mount
.long sys_oldumount
.long sys_setuid
.long sys_getuid
.long sys_ni_syscall /* setuid16 syscall holder */
.long sys_ni_syscall /* getuid16 syscall holder */
.long sys_stime /* 25 */
.long sys_ptrace
.long sys_alarm
.long sys_fstat
.long sys_ni_syscall /* old fstat syscall holder */
.long sys_pause
.long sys_utime /* 30 */
.long sys_cacheflush /* for M32R */ /* old stty syscall holder */
.long sys_ni_syscall /* old stty syscall holder */
.long sys_cachectl /* for M32R */ /* old gtty syscall holder */
.long sys_access
.long sys_nice
.long sys_ni_syscall /* nice syscall holder */
.long sys_ni_syscall /* 35 - old ftime syscall holder */
.long sys_sync
.long sys_kill
......@@ -755,17 +755,17 @@ ENTRY(sys_call_table)
.long sys_times
.long sys_ni_syscall /* old prof syscall holder */
.long sys_brk /* 45 */
.long sys_setgid
.long sys_getgid
.long sys_signal
.long sys_geteuid
.long sys_getegid /* 50 */
.long sys_ni_syscall /* setgid16 syscall holder */
.long sys_getgid /* will be unused */
.long sys_ni_syscall /* signal syscall holder */
.long sys_ni_syscall /* geteuid16 syscall holder */
.long sys_ni_syscall /* 50 - getegid16 syscall holder */
.long sys_acct
.long sys_umount /* recycled never used phys() */
.long sys_ni_syscall /* old lock syscall holder */
.long sys_ioctl
.long sys_fcntl /* 55 */
.long sys_ni_syscall /* old mpx syscall holder */
.long sys_fcntl /* 55 - will be unused */
.long sys_ni_syscall /* mpx syscall holder */
.long sys_setpgid
.long sys_ni_syscall /* old ulimit syscall holder */
.long sys_ni_syscall /* sys_olduname */
......@@ -776,41 +776,41 @@ ENTRY(sys_call_table)
.long sys_getppid
.long sys_getpgrp /* 65 */
.long sys_setsid
.long sys_sigaction
.long sys_sgetmask
.long sys_ssetmask
.long sys_setreuid /* 70 */
.long sys_setregid
.long sys_sigsuspend
.long sys_sigpending
.long sys_ni_syscall /* sigaction syscall holder */
.long sys_ni_syscall /* sgetmask syscall holder */
.long sys_ni_syscall /* ssetmask syscall holder */
.long sys_ni_syscall /* 70 - setreuid16 syscall holder */
.long sys_ni_syscall /* setregid16 syscall holder */
.long sys_ni_syscall /* sigsuspend syscall holder */
.long sys_ni_syscall /* sigpending syscall holder */
.long sys_sethostname
.long sys_setrlimit /* 75 */
.long sys_getrlimit
.long sys_getrlimit/*will be unused*/
.long sys_getrusage
.long sys_gettimeofday
.long sys_settimeofday
.long sys_getgroups /* 80 */
.long sys_setgroups
.long sys_ni_syscall /* 80 - getgroups16 syscall holder */
.long sys_ni_syscall /* setgroups16 syscall holder */
.long sys_ni_syscall /* sys_oldselect */
.long sys_symlink
.long sys_lstat
.long sys_ni_syscall /* old lstat syscall holder */
.long sys_readlink /* 85 */
.long sys_uselib
.long sys_swapon
.long sys_reboot
.long old_readdir
.long sys_ni_syscall /* readdir syscall holder */
.long sys_ni_syscall /* 90 - old_mmap syscall holder */
.long sys_munmap
.long sys_truncate
.long sys_ftruncate
.long sys_fchmod
.long sys_fchown /* 95 */
.long sys_ni_syscall /* 95 - fchwon16 syscall holder */
.long sys_getpriority
.long sys_setpriority
.long sys_ni_syscall /* old profil syscall holder */
.long sys_statfs
.long sys_fstatfs /* 100 */
.long sys_ni_syscall /* ioperm */
.long sys_ni_syscall /* ioperm syscall holder */
.long sys_socketcall
.long sys_syslog
.long sys_setitimer
......@@ -818,37 +818,37 @@ ENTRY(sys_call_table)
.long sys_newstat
.long sys_newlstat
.long sys_newfstat
.long sys_uname
.long sys_ni_syscall /* 110 - iopl */
.long sys_ni_syscall /* old uname syscall holder */
.long sys_ni_syscall /* 110 - iopl syscall holder */
.long sys_vhangup
.long sys_ni_syscall /* for idle */
.long sys_ni_syscall /* for vm86old */
.long sys_ni_syscall /* idle syscall holder */
.long sys_ni_syscall /* vm86old syscall holder */
.long sys_wait4
.long sys_swapoff /* 115 */
.long sys_sysinfo
.long sys_ipc
.long sys_fsync
.long sys_sigreturn
.long sys_ni_syscall /* sigreturn syscall holder */
.long sys_clone /* 120 */
.long sys_setdomainname
.long sys_newuname
.long sys_ni_syscall /* sys_modify_ldt */
.long sys_ni_syscall /* modify_ldt syscall holder */
.long sys_adjtimex
.long sys_mprotect /* 125 */
.long sys_sigprocmask
.long sys_ni_syscall /* sys_create_module */
.long sys_ni_syscall /* sigprocmask syscall holder */
.long sys_ni_syscall /* create_module syscall holder */
.long sys_init_module
.long sys_delete_module
.long sys_ni_syscall /* 130 sys_get_kernel_syms */
.long sys_ni_syscall /* 130 - get_kernel_syms */
.long sys_quotactl
.long sys_getpgid
.long sys_fchdir
.long sys_bdflush
.long sys_sysfs /* 135 */
.long sys_personality
.long sys_ni_syscall /* for afs_syscall */
.long sys_setfsuid
.long sys_setfsgid
.long sys_ni_syscall /* afs_syscall syscall holder */
.long sys_ni_syscall /* setfsuid16 syscall holder */
.long sys_ni_syscall /* setfsgid16 syscall holder */
.long sys_llseek /* 140 */
.long sys_getdents
.long sys_select
......@@ -873,10 +873,10 @@ ENTRY(sys_call_table)
.long sys_sched_rr_get_interval
.long sys_nanosleep
.long sys_mremap
.long sys_setresuid
.long sys_getresuid /* 165 */
.long sys_tas /* vm86 */
.long sys_ni_syscall /* sys_query_module */
.long sys_ni_syscall /* setresuid16 syscall holder */
.long sys_ni_syscall /* 165 - getresuid16 syscall holder */
.long sys_tas /* vm86 syscall holder */
.long sys_ni_syscall /* query_module syscall holder */
.long sys_poll
.long sys_nfsservctl
.long sys_setresgid /* 170 */
......@@ -891,7 +891,7 @@ ENTRY(sys_call_table)
.long sys_rt_sigsuspend
.long sys_pread64 /* 180 */
.long sys_pwrite64
.long sys_chown
.long sys_ni_syscall /* chown16 syscall holder */
.long sys_getcwd
.long sys_capget
.long sys_capset /* 185 */
......
......@@ -33,32 +33,6 @@
int do_signal(struct pt_regs *, sigset_t *);
/*
* Atomically swap in the new signal mask, and wait for a signal.
*/
asmlinkage int
sys_sigsuspend(old_sigset_t mask, unsigned long r1,
unsigned long r2, unsigned long r3, unsigned long r4,
unsigned long r5, unsigned long r6, struct pt_regs regs)
{
sigset_t saveset;
mask &= _BLOCKABLE;
spin_lock_irq(&current->sighand->siglock);
saveset = current->blocked;
siginitset(&current->blocked, mask);
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
regs.r0 = -EINTR;
while (1) {
current->state = TASK_INTERRUPTIBLE;
schedule();
if (do_signal(&regs, &saveset))
return regs.r0;
}
}
asmlinkage int
sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize,
unsigned long r2, unsigned long r3, unsigned long r4,
......@@ -89,38 +63,6 @@ sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize,
}
}
asmlinkage int
sys_sigaction(int sig, const struct old_sigaction __user *act,
struct old_sigaction __user *oact)
{
struct k_sigaction new_ka, old_ka;
int ret;
if (act) {
old_sigset_t mask;
if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
__get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
__get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
return -EFAULT;
__get_user(new_ka.sa.sa_flags, &act->sa_flags);
__get_user(mask, &act->sa_mask);
siginitset(&new_ka.sa.sa_mask, mask);
}
ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
if (!ret && oact) {
if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
__put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
__put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
return -EFAULT;
__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
}
return ret;
}
asmlinkage int
sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
unsigned long r2, unsigned long r3, unsigned long r4,
......@@ -134,26 +76,14 @@ sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
* Do a signal return; undo the signal stack.
*/
struct sigframe
{
// char *pretcode;
int sig;
struct sigcontext sc;
// struct _fpstate fpstate;
unsigned long extramask[_NSIG_WORDS-1];
char retcode[4];
};
struct rt_sigframe
{
// char *pretcode;
int sig;
struct siginfo *pinfo;
void *puc;
struct siginfo info;
struct ucontext uc;
// struct _fpstate fpstate;
char retcode[8];
};
static int
......@@ -207,38 +137,6 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
return err;
}
asmlinkage int
sys_sigreturn(unsigned long r0, unsigned long r1,
unsigned long r2, unsigned long r3, unsigned long r4,
unsigned long r5, unsigned long r6, struct pt_regs regs)
{
struct sigframe __user *frame = (struct sigframe __user *)regs.spu;
sigset_t set;
int result;
if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
goto badframe;
if (__get_user(set.sig[0], &frame->sc.oldmask)
|| (_NSIG_WORDS > 1
&& __copy_from_user(&set.sig[1], &frame->extramask,
sizeof(frame->extramask))))
goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
spin_lock_irq(&current->sighand->siglock);
current->blocked = set;
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
if (restore_sigcontext(&regs, &frame->sc, &result))
goto badframe;
return result;
badframe:
force_sig(SIGSEGV, current);
return 0;
}
asmlinkage int
sys_rt_sigreturn(unsigned long r0, unsigned long r1,
unsigned long r2, unsigned long r3, unsigned long r4,
......@@ -342,71 +240,6 @@ get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
return (void __user *)((sp - frame_size) & -8ul);
}
static void setup_frame(int sig, struct k_sigaction *ka,
sigset_t *set, struct pt_regs *regs)
{
struct sigframe __user *frame;
int err = 0;
int signal;
frame = get_sigframe(ka, regs->spu, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv;
signal = current_thread_info()->exec_domain
&& current_thread_info()->exec_domain->signal_invmap
&& sig < 32
? current_thread_info()->exec_domain->signal_invmap[sig]
: sig;
err |= __put_user(signal, &frame->sig);
if (err)
goto give_sigsegv;
err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
if (err)
goto give_sigsegv;
if (_NSIG_WORDS > 1) {
err |= __copy_to_user(frame->extramask, &set->sig[1],
sizeof(frame->extramask));
if (err)
goto give_sigsegv;
}
if (ka->sa.sa_flags & SA_RESTORER)
regs->lr = (unsigned long)ka->sa.sa_restorer;
else {
/* This is : ldi r7, #__NR_sigreturn ; trap #2 */
unsigned long code = 0x670010f2 | (__NR_sigreturn << 16);
regs->lr = (unsigned long)frame->retcode;
err |= __put_user(code, (long __user *)(frame->retcode+0));
if (err)
goto give_sigsegv;
flush_cache_sigtramp((unsigned long)frame->retcode);
}
/* Set up registers for signal handler */
regs->spu = (unsigned long)frame;
regs->r0 = signal; /* Arg for signal handler */
regs->r1 = (unsigned long)&frame->sc;
regs->bpc = (unsigned long)ka->sa.sa_handler;
set_fs(USER_DS);
#if DEBUG_SIG
printk("SIG deliver (%s:%d): sp=%p pc=%p\n",
current->comm, current->pid, frame, regs->pc);
#endif
return;
give_sigsegv:
force_sigsegv(sig, current);
}
static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *set, struct pt_regs *regs)
{
......@@ -448,20 +281,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
goto give_sigsegv;
/* Set up to return from userspace. */
if (ka->sa.sa_flags & SA_RESTORER)
regs->lr = (unsigned long)ka->sa.sa_restorer;
else {
/* This is : ldi r7, #__NR_rt_sigreturn ; trap #2 */
unsigned long code1 = 0x97f00000 | (__NR_rt_sigreturn);
unsigned long code2 = 0x10f2f000;
regs->lr = (unsigned long)frame->retcode;
err |= __put_user(code1, (long __user *)(frame->retcode+0));
err |= __put_user(code2, (long __user *)(frame->retcode+4));
if (err)
goto give_sigsegv;
flush_cache_sigtramp((unsigned long)frame->retcode);
}
regs->lr = (unsigned long)ka->sa.sa_restorer;
/* Set up registers for signal handler */
regs->spu = (unsigned long)frame;
......@@ -519,10 +339,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
}
/* Set up the stack frame */
if (ka->sa.sa_flags & SA_SIGINFO)
setup_rt_frame(sig, ka, info, oldset, regs);
else
setup_frame(sig, ka, oldset, regs);
setup_rt_frame(sig, ka, info, oldset, regs);
if (!(ka->sa.sa_flags & SA_NODEFER)) {
spin_lock_irq(&current->sighand->siglock);
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment