--- 25-akpm/include/asm-generic/compat_signal.h | 25 ++++ 25-akpm/include/linux/compat.h | 18 +- 25-akpm/include/linux/compat_siginfo.h | 170 ++++++++++++++++++++++++++++ 25-akpm/kernel/Makefile | 2 25-akpm/kernel/compat_signal.c | 124 ++++++++++++++++++++ 25-akpm/kernel/signal.c | 7 + 6 files changed, 339 insertions(+), 7 deletions(-) diff -puN /dev/null include/asm-generic/compat_signal.h --- /dev/null Thu Apr 11 07:25:15 2002 +++ 25-akpm/include/asm-generic/compat_signal.h Thu Jan 29 15:22:04 2004 @@ -0,0 +1,25 @@ +#ifndef _ASM_GENERIC_COMPAT_SIGNAL_H +#define _ASM_GENERIC_COMPAT_SIGNAL_H + +#ifndef __ASSEMBLY__ +#include + +typedef compat_uptr_t compat_sighandler_t; + +typedef struct compat_sigaltstack { + compat_uptr_t ss_sp; + compat_int_t ss_flags; + compat_size_t ss_size; +} compat_stack_t; + +/* Most things should be clean enough to redefine this at will, if care + is taken to make libc match. */ + +struct compat_sigaction { + compat_sighandler_t sa_handler; + compat_uint_t sa_flags; + compat_sigset_t sa_mask; /* mask last for extensibility */ +}; + +#endif /* !__ASSEMBLY__ */ +#endif /* !_ASM_GENERIC_COMPAT_SIGNAL_H */ diff -puN include/linux/compat.h~compat-signal-noarch-2004-01-29 include/linux/compat.h --- 25/include/linux/compat.h~compat-signal-noarch-2004-01-29 Thu Jan 29 15:22:04 2004 +++ 25-akpm/include/linux/compat.h Thu Jan 29 15:22:04 2004 @@ -6,15 +6,26 @@ */ #include -#ifdef CONFIG_COMPAT +#ifndef CONFIG_COMPAT + +/* Non-native task requiring compat... doesn't exist */ +#define is_compat_task(x) 0 + +#else #include #include /* for HZ */ +#include /* Conditional process compat */ #include #define compat_jiffies_to_clock_t(x) \ (((unsigned long)(x) * COMPAT_USER_HZ) / HZ) +/* Non-native task requiring compat */ +#ifndef HAVE_ARCH_IS_COMPAT_TASK +#define is_compat_task(x) (x->personality == PER_LINUX32) +#endif + struct compat_itimerspec { struct compat_timespec it_interval; struct compat_timespec it_value; @@ -83,10 +94,5 @@ struct compat_dirent { char d_name[256]; }; -typedef union compat_sigval { - compat_int_t sival_int; - compat_uptr_t sival_ptr; -} compat_sigval_t; - #endif /* CONFIG_COMPAT */ #endif /* _LINUX_COMPAT_H */ diff -puN /dev/null include/linux/compat_siginfo.h --- /dev/null Thu Apr 11 07:25:15 2002 +++ 25-akpm/include/linux/compat_siginfo.h Thu Jan 29 15:22:04 2004 @@ -0,0 +1,170 @@ +#ifndef _ASM_GENERIC_COMPAT_SIGINFO_H +#define _ASM_GENERIC_COMPAT_SIGINFO_H + +#include +#include + +#ifndef CONFIG_COMPAT + +/* No compatibility layer required, add empty definitions for the compiler */ + +typedef struct compat_siginfo{ +} compat_siginfo_t; + +static inline int compat_copy_siginfo_to_user(compat_siginfo_t __user *to, + struct siginfo *from) +{ + return -1; +} + +#else + +#include +#include + +/* compat view of sigval_t */ +typedef union compat_sigval { + compat_int_t sival_int; + compat_uptr_t sival_ptr; +} compat_sigval_t; + +/* + * This is the size (including padding) of the part of the + * struct siginfo that is before the union. + */ +#ifndef __ARCH_SI_COMPAT_PREAMBLE_SIZE +#define __ARCH_SI_COMPAT_PREAMBLE_SIZE (3 * sizeof(int)) +#endif + +#define SI_COMPAT_MAX_SIZE 128 +#ifndef SI_COMPAT_PAD_SIZE +#define SI_COMPAT_PAD_SIZE ((SI_COMPAT_MAX_SIZE - __ARCH_SI_COMPAT_PREAMBLE_SIZE) / sizeof(int)) +#endif + +/* 32-bit view of si.uid_t */ +#ifndef __ARCH_SI_COMPAT_UID_T +#define __ARCH_SI_COMPAT_UID_T compat_uid_t +#endif + +/* 32-bit view of si.band_t */ +#ifndef __ARCH_SI_COMPAT_BAND_T +#define __ARCH_SI_COMPAT_BAND_T compat_int_t +#endif + +#ifndef HAVE_ARCH_COMPAT_SIGINFO_T + +/* Compat view of siginfo_t */ +typedef struct compat_siginfo { + compat_int_t si_signo; + compat_int_t si_errno; + compat_int_t si_code; + + union { + compat_int_t _pad[SI_COMPAT_PAD_SIZE]; + + /* kill() */ + struct { + compat_pid_t _pid; /* sender's pid */ + __ARCH_SI_COMPAT_UID_T _uid; /* sender's uid */ + } _kill; + + /* POSIX.1b timers */ + struct { + compat_timer_t _tid; /* timer id */ + compat_int_t _overrun; /* overrun count */ + char _pad[sizeof( __ARCH_SI_UID_T) - sizeof(int)]; + compat_sigval_t _sigval; /* same as below */ + compat_int_t _sys_private; /* not to be passed to user */ + } _timer; + + /* POSIX.1b signals */ + struct { + compat_pid_t _pid; /* sender's pid */ + __ARCH_SI_COMPAT_UID_T _uid; /* sender's uid */ + compat_sigval_t _sigval; + } _rt; + + /* SIGCHLD */ + struct { + compat_pid_t _pid; /* which child */ + __ARCH_SI_COMPAT_UID_T _uid; /* sender's uid */ + compat_int_t _status; /* exit code */ + compat_clock_t _utime; + compat_clock_t _stime; + } _sigchld; + + /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */ + struct { + compat_uptr_t _addr; /* faulting insn/memory ref. */ +#ifdef __ARCH_SI_COMPAT_TRAPNO + compat_int_t _trapno; /* TRAP # which caused the signal */ +#endif + } _sigfault; + + /* SIGPOLL */ + struct { + __ARCH_SI_COMPAT_BAND_T _band; /* POLL_IN, POLL_OUT, POLL_MSG */ + compat_int_t _fd; + } _sigpoll; + } _sifields; +} compat_siginfo_t; +#endif /* !HAVE_ARCH_COMPAT_SIGINFO_T */ + +#ifdef __ARCH_SI_COMPAT_TRAPNO +#define si_trapno _sifields._sigfault._trapno +#endif + +/* + * sigevent definitions + * + * It seems likely that SIGEV_THREAD will have to be handled from + * userspace, libpthread transmuting it to SIGEV_SIGNAL, which the + * thread manager then catches and does the appropriate nonsense. + * However, everything is written out here so as to not get lost. + */ + +#define SIGEV_COMPAT_MAX_SIZE 64 +#ifndef SIGEV_COMPAT_PAD_SIZE +#define SIGEV_COMPAT_PAD_SIZE ((SIGEV_COMPAT_MAX_SIZE/sizeof(int)) - 3) +#endif + +#ifndef HAVE_ARCH_COMPAT_SIGEVENT_T + +/* 32-bit view of sigevent_t */ +typedef struct compat_sigevent { + compat_sigval_t sigev_value; + compat_int_t sigev_signo; + compat_int_t sigev_notify; + union { + compat_int_t _pad[SIGEV_COMPAT_PAD_SIZE]; + compat_int_t _tid; + + struct { + compat_uptr_t _function; + compat_uptr_t _attribute; /* really pthread_attr_t */ + } _sigev_thread; + } _sigev_un; +} compat_sigevent_t; + +#endif /* HAVE_ARCH_COMPAT_SIGEVENT_T */ + +#ifndef HAVE_ARCH_COMPAT_COPY_SIGINFO + +#include + +static inline void compat_copy_siginfo(struct compat_siginfo *to, struct compat_siginfo *from) +{ + if (from->si_code < 0) + memcpy(to, from, sizeof(*to)); + else + /* _sigchld is currently the largest know union member */ + memcpy(to, from, __ARCH_SI_COMPAT_PREAMBLE_SIZE + sizeof(from->_sifields._sigchld)); +} + +#endif /* !HAVE_ARCH_COMPAT_COPY_SIGINFO */ + +extern int compat_copy_siginfo_to_user(compat_siginfo_t __user *to, struct siginfo *from); + +#endif /* CONFIG_COMPAT */ +#endif /* _ASM_GENERIC_COMPAT_SIGINFO_H */ + diff -puN /dev/null kernel/compat_signal.c --- /dev/null Thu Apr 11 07:25:15 2002 +++ 25-akpm/kernel/compat_signal.c Thu Jan 29 15:22:04 2004 @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2003 Carlos O'Donell + * + * 2003-12-20 Carlos O'Donell + * Copied linux/kernel/compat_signal.c (copy_siginfo_to_user) + * and modified to use compat_siginfo_t for thunking down to + * 32-bit userspace from a 64-bit kernel. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or + * NON INFRINGEMENT. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include +#include +#include +#include + +#ifndef HAVE_ARCH_COMPAT_COPY_SIGINFO_TO_USER + +int compat_copy_siginfo_to_user(compat_siginfo_t __user *to, siginfo_t *from) +{ + int err; + compat_siginfo_t compat_from; + + if (!access_ok (VERIFY_WRITE, to, sizeof(compat_siginfo_t))) + return -EFAULT; + + /* + * If you change compat_siginfo_t structure *or* siginfo_t, + * please be sure this code is fixed accordingly. + * It should never copy any pad contained in the structure + * to avoid security leaks, but must copy the generic + * 3 ints plus the relevant union member. + */ + + /* Convert structure, don't leak anything in the copy */ + memset(&compat_from,'\0',sizeof(compat_siginfo_t)); + compat_from.si_signo = (compat_int_t)(from->si_signo); + compat_from.si_errno = (compat_int_t)(from->si_errno); + compat_from.si_code = (compat_int_t)(from->si_code); + + if (from->si_code < 0) + return __copy_to_user(to, &compat_from, sizeof(compat_siginfo_t)) + ? -EFAULT : 0; + + err = __put_user(compat_from.si_signo, &to->si_signo); + err |= __put_user(compat_from.si_errno, &to->si_errno); + err |= __put_user(compat_from.si_code, &to->si_code); + + switch (from->si_code & __SI_MASK) { + case __SI_KILL: + compat_from.si_pid = (compat_pid_t)(from->si_pid); + compat_from.si_uid = (__ARCH_SI_COMPAT_UID_T)(from->si_uid); + err |= __put_user(compat_from.si_pid, &to->si_pid); + err |= __put_user(compat_from.si_uid, &to->si_uid); + break; + case __SI_TIMER: + compat_from.si_pid = (compat_timer_t)(from->si_tid); + compat_from.si_overrun = (compat_int_t)(from->si_overrun); + compat_from.si_ptr = (compat_uptr_t)((u64)(from->si_ptr) & 0xffffffffUL); + err |= __put_user(compat_from.si_tid, &to->si_tid); + err |= __put_user(compat_from.si_overrun, &to->si_overrun); + err |= __put_user(compat_from.si_ptr, &to->si_ptr); + break; + case __SI_POLL: + compat_from.si_band = (__ARCH_SI_COMPAT_BAND_T)(from->si_band); + compat_from.si_fd = (compat_int_t)(from->si_fd); + err |= __put_user(compat_from.si_band, &to->si_band); + err |= __put_user(compat_from.si_fd, &to->si_fd); + break; + case __SI_FAULT: + compat_from.si_addr = (compat_uptr_t)((u64)(from->si_addr) & 0xffffffffUL); + err |= __put_user(compat_from.si_addr, &to->si_addr); +#ifdef __ARCH_SI_COMPAT_TRAPNO + compat_from.si_trapno = (compat_int_t)(from->si_addr); + err |= __put_user(compat_from.si_trapno, &to->si_trapno); +#endif + break; + case __SI_CHLD: + compat_from.si_pid = (compat_pid_t)(from->si_pid); + compat_from.si_uid = (__ARCH_SI_COMPAT_UID_T)(from->si_uid); + compat_from.si_status = (compat_int_t)(from->si_status); + compat_from.si_utime = (compat_clock_t)(from->si_utime); + compat_from.si_stime = (compat_clock_t)(from->si_stime); + err |= __put_user(compat_from.si_pid, &to->si_pid); + err |= __put_user(compat_from.si_uid, &to->si_uid); + err |= __put_user(compat_from.si_status, &to->si_status); + err |= __put_user(compat_from.si_utime, &to->si_utime); + err |= __put_user(compat_from.si_stime, &to->si_stime); + break; + case __SI_RT: /* This is not generated by the kernel as of now. */ + compat_from.si_pid = (compat_pid_t)(from->si_pid); + compat_from.si_uid = (__ARCH_SI_COMPAT_UID_T)(from->si_uid); + compat_from.si_int = (compat_int_t)(from->si_int); + compat_from.si_ptr = (compat_uptr_t)((u64)(from->si_ptr) & 0xffffffffUL); + err |= __put_user(compat_from.si_pid, &to->si_pid); + err |= __put_user(compat_from.si_uid, &to->si_uid); + err |= __put_user(compat_from.si_int, &to->si_int); + err |= __put_user(compat_from.si_ptr, &to->si_ptr); + break; + default: /* this is just in case for now ... */ + compat_from.si_pid = (compat_pid_t)(from->si_pid); + compat_from.si_uid = (__ARCH_SI_COMPAT_UID_T)(from->si_uid); + err |= __put_user(compat_from.si_pid, &to->si_pid); + err |= __put_user(compat_from.si_uid, &to->si_uid); + break; + } + return err; +} + +#endif diff -puN kernel/Makefile~compat-signal-noarch-2004-01-29 kernel/Makefile --- 25/kernel/Makefile~compat-signal-noarch-2004-01-29 Thu Jan 29 15:22:04 2004 +++ 25-akpm/kernel/Makefile Thu Jan 29 15:22:04 2004 @@ -17,7 +17,7 @@ obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_KALLSYMS) += kallsyms.o obj-$(CONFIG_PM) += power/ obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o -obj-$(CONFIG_COMPAT) += compat.o +obj-$(CONFIG_COMPAT) += compat.o compat_signal.o obj-$(CONFIG_IKCONFIG) += configs.o obj-$(CONFIG_IKCONFIG_PROC) += configs.o diff -puN kernel/signal.c~compat-signal-noarch-2004-01-29 kernel/signal.c --- 25/kernel/signal.c~compat-signal-noarch-2004-01-29 Thu Jan 29 15:22:04 2004 +++ 25-akpm/kernel/signal.c Thu Jan 29 15:22:04 2004 @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -2006,6 +2007,12 @@ int copy_siginfo_to_user(siginfo_t __use if (from->si_code < 0) return __copy_to_user(to, from, sizeof(siginfo_t)) ? -EFAULT : 0; + + /* Use compat_siginfo_t with 32-bit signals */ + if(is_compat_task(current)){ + return compat_copy_siginfo_to_user((compat_siginfo_t __user *)to,from); + } + /* * If you change siginfo_t structure, please be sure * this code is fixed accordingly. _