Commit 8b39a57e authored by Linus Torvalds's avatar Linus Torvalds

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

Pull uaccess/coredump updates from Al Viro:
 "set_fs() removal in coredump-related area - mostly Christoph's
  stuff..."

* 'work.set_fs-exec' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
  binfmt_elf_fdpic: remove the set_fs(KERNEL_DS) in elf_fdpic_core_dump
  binfmt_elf: remove the set_fs(KERNEL_DS) in elf_core_dump
  binfmt_elf: remove the set_fs in fill_siginfo_note
  signal: refactor copy_siginfo_to_user32
  powerpc/spufs: simplify spufs core dumping
  powerpc/spufs: stop using access_ok
  powerpc/spufs: fix copy_to_user while atomic
parents 062ea674 38cdabb7
...@@ -21,22 +21,6 @@ ...@@ -21,22 +21,6 @@
#include "spufs.h" #include "spufs.h"
static ssize_t do_coredump_read(int num, struct spu_context *ctx, void *buffer,
size_t size, loff_t *off)
{
u64 data;
int ret;
if (spufs_coredump_read[num].read)
return spufs_coredump_read[num].read(ctx, buffer, size, off);
data = spufs_coredump_read[num].get(ctx);
ret = snprintf(buffer, size, "0x%.16llx", data);
if (ret >= size)
return size;
return ++ret; /* count trailing NULL */
}
static int spufs_ctx_note_size(struct spu_context *ctx, int dfd) static int spufs_ctx_note_size(struct spu_context *ctx, int dfd)
{ {
int i, sz, total = 0; int i, sz, total = 0;
...@@ -118,58 +102,43 @@ int spufs_coredump_extra_notes_size(void) ...@@ -118,58 +102,43 @@ int spufs_coredump_extra_notes_size(void)
static int spufs_arch_write_note(struct spu_context *ctx, int i, static int spufs_arch_write_note(struct spu_context *ctx, int i,
struct coredump_params *cprm, int dfd) struct coredump_params *cprm, int dfd)
{ {
loff_t pos = 0; size_t sz = spufs_coredump_read[i].size;
int sz, rc, total = 0; char fullname[80];
const int bufsz = PAGE_SIZE;
char *name;
char fullname[80], *buf;
struct elf_note en; struct elf_note en;
size_t skip; size_t ret;
buf = (void *)get_zeroed_page(GFP_KERNEL);
if (!buf)
return -ENOMEM;
name = spufs_coredump_read[i].name; sprintf(fullname, "SPU/%d/%s", dfd, spufs_coredump_read[i].name);
sz = spufs_coredump_read[i].size;
sprintf(fullname, "SPU/%d/%s", dfd, name);
en.n_namesz = strlen(fullname) + 1; en.n_namesz = strlen(fullname) + 1;
en.n_descsz = sz; en.n_descsz = sz;
en.n_type = NT_SPU; en.n_type = NT_SPU;
if (!dump_emit(cprm, &en, sizeof(en))) if (!dump_emit(cprm, &en, sizeof(en)))
goto Eio; return -EIO;
if (!dump_emit(cprm, fullname, en.n_namesz)) if (!dump_emit(cprm, fullname, en.n_namesz))
goto Eio; return -EIO;
if (!dump_align(cprm, 4)) if (!dump_align(cprm, 4))
goto Eio; return -EIO;
do { if (spufs_coredump_read[i].dump) {
rc = do_coredump_read(i, ctx, buf, bufsz, &pos); ret = spufs_coredump_read[i].dump(ctx, cprm);
if (rc > 0) { if (ret < 0)
if (!dump_emit(cprm, buf, rc)) return ret;
goto Eio; } else {
total += rc; char buf[32];
}
} while (rc == bufsz && total < sz); ret = snprintf(buf, sizeof(buf), "0x%.16llx",
spufs_coredump_read[i].get(ctx));
if (rc < 0) if (ret >= sizeof(buf))
goto out; return sizeof(buf);
skip = roundup(cprm->pos - total + sz, 4) - cprm->pos; /* count trailing the NULL: */
if (!dump_skip(cprm, skip)) if (!dump_emit(cprm, buf, ret + 1))
goto Eio; return -EIO;
}
rc = 0;
out: if (!dump_skip(cprm, roundup(cprm->pos - ret + sz, 4) - cprm->pos))
free_page((unsigned long)buf); return -EIO;
return rc; return 0;
Eio:
free_page((unsigned long)buf);
return -EIO;
} }
int spufs_coredump_extra_notes_write(struct coredump_params *cprm) int spufs_coredump_extra_notes_write(struct coredump_params *cprm)
......
This diff is collapsed.
...@@ -337,8 +337,7 @@ void spufs_dma_callback(struct spu *spu, int type); ...@@ -337,8 +337,7 @@ void spufs_dma_callback(struct spu *spu, int type);
extern struct spu_coredump_calls spufs_coredump_calls; extern struct spu_coredump_calls spufs_coredump_calls;
struct spufs_coredump_reader { struct spufs_coredump_reader {
char *name; char *name;
ssize_t (*read)(struct spu_context *ctx, ssize_t (*dump)(struct spu_context *ctx, struct coredump_params *cprm);
char __user *buffer, size_t size, loff_t *pos);
u64 (*get)(struct spu_context *ctx); u64 (*get)(struct spu_context *ctx);
size_t size; size_t size;
}; };
......
...@@ -350,7 +350,7 @@ int ia32_setup_rt_frame(int sig, struct ksignal *ksig, ...@@ -350,7 +350,7 @@ int ia32_setup_rt_frame(int sig, struct ksignal *ksig,
unsafe_put_user(*(__u64 *)set, (__u64 *)&frame->uc.uc_sigmask, Efault); unsafe_put_user(*(__u64 *)set, (__u64 *)&frame->uc.uc_sigmask, Efault);
user_access_end(); user_access_end();
if (__copy_siginfo_to_user32(&frame->info, &ksig->info, false)) if (__copy_siginfo_to_user32(&frame->info, &ksig->info))
return -EFAULT; return -EFAULT;
/* Set up registers for signal handler */ /* Set up registers for signal handler */
......
...@@ -214,7 +214,11 @@ static inline bool in_compat_syscall(void) ...@@ -214,7 +214,11 @@ static inline bool in_compat_syscall(void)
#endif #endif
struct compat_siginfo; struct compat_siginfo;
int __copy_siginfo_to_user32(struct compat_siginfo __user *to,
const kernel_siginfo_t *from, bool x32_ABI); #ifdef CONFIG_X86_X32_ABI
int copy_siginfo_to_user32(struct compat_siginfo __user *to,
const kernel_siginfo_t *from);
#define copy_siginfo_to_user32 copy_siginfo_to_user32
#endif /* CONFIG_X86_X32_ABI */
#endif /* _ASM_X86_COMPAT_H */ #endif /* _ASM_X86_COMPAT_H */
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include <asm/vm86.h> #include <asm/vm86.h>
#ifdef CONFIG_X86_64 #ifdef CONFIG_X86_64
#include <linux/compat.h>
#include <asm/proto.h> #include <asm/proto.h>
#include <asm/ia32_unistd.h> #include <asm/ia32_unistd.h>
#endif /* CONFIG_X86_64 */ #endif /* CONFIG_X86_64 */
...@@ -511,6 +512,31 @@ static int __setup_rt_frame(int sig, struct ksignal *ksig, ...@@ -511,6 +512,31 @@ static int __setup_rt_frame(int sig, struct ksignal *ksig,
} }
#endif /* CONFIG_X86_32 */ #endif /* CONFIG_X86_32 */
#ifdef CONFIG_X86_X32_ABI
static int x32_copy_siginfo_to_user(struct compat_siginfo __user *to,
const struct kernel_siginfo *from)
{
struct compat_siginfo new;
copy_siginfo_to_external32(&new, from);
if (from->si_signo == SIGCHLD) {
new._sifields._sigchld_x32._utime = from->si_utime;
new._sifields._sigchld_x32._stime = from->si_stime;
}
if (copy_to_user(to, &new, sizeof(struct compat_siginfo)))
return -EFAULT;
return 0;
}
int copy_siginfo_to_user32(struct compat_siginfo __user *to,
const struct kernel_siginfo *from)
{
if (in_x32_syscall())
return x32_copy_siginfo_to_user(to, from);
return __copy_siginfo_to_user32(to, from);
}
#endif /* CONFIG_X86_X32_ABI */
static int x32_setup_rt_frame(struct ksignal *ksig, static int x32_setup_rt_frame(struct ksignal *ksig,
compat_sigset_t *set, compat_sigset_t *set,
struct pt_regs *regs) struct pt_regs *regs)
...@@ -543,7 +569,7 @@ static int x32_setup_rt_frame(struct ksignal *ksig, ...@@ -543,7 +569,7 @@ static int x32_setup_rt_frame(struct ksignal *ksig,
user_access_end(); user_access_end();
if (ksig->ka.sa.sa_flags & SA_SIGINFO) { if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
if (__copy_siginfo_to_user32(&frame->info, &ksig->info, true)) if (x32_copy_siginfo_to_user(&frame->info, &ksig->info))
return -EFAULT; return -EFAULT;
} }
......
...@@ -1488,7 +1488,6 @@ static unsigned long vma_dump_size(struct vm_area_struct *vma, ...@@ -1488,7 +1488,6 @@ static unsigned long vma_dump_size(struct vm_area_struct *vma,
vma->vm_pgoff == 0 && (vma->vm_flags & VM_READ)) { vma->vm_pgoff == 0 && (vma->vm_flags & VM_READ)) {
u32 __user *header = (u32 __user *) vma->vm_start; u32 __user *header = (u32 __user *) vma->vm_start;
u32 word; u32 word;
mm_segment_t fs = get_fs();
/* /*
* Doing it this way gets the constant folded by GCC. * Doing it this way gets the constant folded by GCC.
*/ */
...@@ -1501,14 +1500,8 @@ static unsigned long vma_dump_size(struct vm_area_struct *vma, ...@@ -1501,14 +1500,8 @@ static unsigned long vma_dump_size(struct vm_area_struct *vma,
magic.elfmag[EI_MAG1] = ELFMAG1; magic.elfmag[EI_MAG1] = ELFMAG1;
magic.elfmag[EI_MAG2] = ELFMAG2; magic.elfmag[EI_MAG2] = ELFMAG2;
magic.elfmag[EI_MAG3] = ELFMAG3; magic.elfmag[EI_MAG3] = ELFMAG3;
/*
* Switch to the user "segment" for get_user(),
* then put back what elf_core_dump() had in place.
*/
set_fs(USER_DS);
if (unlikely(get_user(word, header))) if (unlikely(get_user(word, header)))
word = 0; word = 0;
set_fs(fs);
if (word == magic.cmp) if (word == magic.cmp)
return PAGE_SIZE; return PAGE_SIZE;
} }
...@@ -1689,10 +1682,7 @@ static void fill_auxv_note(struct memelfnote *note, struct mm_struct *mm) ...@@ -1689,10 +1682,7 @@ static void fill_auxv_note(struct memelfnote *note, struct mm_struct *mm)
static void fill_siginfo_note(struct memelfnote *note, user_siginfo_t *csigdata, static void fill_siginfo_note(struct memelfnote *note, user_siginfo_t *csigdata,
const kernel_siginfo_t *siginfo) const kernel_siginfo_t *siginfo)
{ {
mm_segment_t old_fs = get_fs(); copy_siginfo_to_external(csigdata, siginfo);
set_fs(KERNEL_DS);
copy_siginfo_to_user((user_siginfo_t __user *) csigdata, siginfo);
set_fs(old_fs);
fill_note(note, "CORE", NT_SIGINFO, sizeof(*csigdata), csigdata); fill_note(note, "CORE", NT_SIGINFO, sizeof(*csigdata), csigdata);
} }
...@@ -2319,7 +2309,6 @@ static void fill_extnum_info(struct elfhdr *elf, struct elf_shdr *shdr4extnum, ...@@ -2319,7 +2309,6 @@ static void fill_extnum_info(struct elfhdr *elf, struct elf_shdr *shdr4extnum,
static int elf_core_dump(struct coredump_params *cprm) static int elf_core_dump(struct coredump_params *cprm)
{ {
int has_dumped = 0; int has_dumped = 0;
mm_segment_t fs;
int segs, i; int segs, i;
size_t vma_data_size = 0; size_t vma_data_size = 0;
struct vm_area_struct *vma, *gate_vma; struct vm_area_struct *vma, *gate_vma;
...@@ -2368,13 +2357,10 @@ static int elf_core_dump(struct coredump_params *cprm) ...@@ -2368,13 +2357,10 @@ static int elf_core_dump(struct coredump_params *cprm)
* notes. This also sets up the file header. * notes. This also sets up the file header.
*/ */
if (!fill_note_info(&elf, e_phnum, &info, cprm->siginfo, cprm->regs)) if (!fill_note_info(&elf, e_phnum, &info, cprm->siginfo, cprm->regs))
goto cleanup; goto end_coredump;
has_dumped = 1; has_dumped = 1;
fs = get_fs();
set_fs(KERNEL_DS);
offset += sizeof(elf); /* Elf header */ offset += sizeof(elf); /* Elf header */
offset += segs * sizeof(struct elf_phdr); /* Program headers */ offset += segs * sizeof(struct elf_phdr); /* Program headers */
...@@ -2502,9 +2488,6 @@ static int elf_core_dump(struct coredump_params *cprm) ...@@ -2502,9 +2488,6 @@ static int elf_core_dump(struct coredump_params *cprm)
} }
end_coredump: end_coredump:
set_fs(fs);
cleanup:
free_note_info(&info); free_note_info(&info);
kfree(shdr4extnum); kfree(shdr4extnum);
kvfree(vma_filesz); kvfree(vma_filesz);
......
...@@ -1549,7 +1549,6 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm) ...@@ -1549,7 +1549,6 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
{ {
#define NUM_NOTES 6 #define NUM_NOTES 6
int has_dumped = 0; int has_dumped = 0;
mm_segment_t fs;
int segs; int segs;
int i; int i;
struct vm_area_struct *vma; struct vm_area_struct *vma;
...@@ -1589,31 +1588,31 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm) ...@@ -1589,31 +1588,31 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
/* alloc memory for large data structures: too large to be on stack */ /* alloc memory for large data structures: too large to be on stack */
elf = kmalloc(sizeof(*elf), GFP_KERNEL); elf = kmalloc(sizeof(*elf), GFP_KERNEL);
if (!elf) if (!elf)
goto cleanup; goto end_coredump;
prstatus = kzalloc(sizeof(*prstatus), GFP_KERNEL); prstatus = kzalloc(sizeof(*prstatus), GFP_KERNEL);
if (!prstatus) if (!prstatus)
goto cleanup; goto end_coredump;
psinfo = kmalloc(sizeof(*psinfo), GFP_KERNEL); psinfo = kmalloc(sizeof(*psinfo), GFP_KERNEL);
if (!psinfo) if (!psinfo)
goto cleanup; goto end_coredump;
notes = kmalloc_array(NUM_NOTES, sizeof(struct memelfnote), notes = kmalloc_array(NUM_NOTES, sizeof(struct memelfnote),
GFP_KERNEL); GFP_KERNEL);
if (!notes) if (!notes)
goto cleanup; goto end_coredump;
fpu = kmalloc(sizeof(*fpu), GFP_KERNEL); fpu = kmalloc(sizeof(*fpu), GFP_KERNEL);
if (!fpu) if (!fpu)
goto cleanup; goto end_coredump;
#ifdef ELF_CORE_COPY_XFPREGS #ifdef ELF_CORE_COPY_XFPREGS
xfpu = kmalloc(sizeof(*xfpu), GFP_KERNEL); xfpu = kmalloc(sizeof(*xfpu), GFP_KERNEL);
if (!xfpu) if (!xfpu)
goto cleanup; goto end_coredump;
#endif #endif
for (ct = current->mm->core_state->dumper.next; for (ct = current->mm->core_state->dumper.next;
ct; ct = ct->next) { ct; ct = ct->next) {
tmp = kzalloc(sizeof(*tmp), GFP_KERNEL); tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
if (!tmp) if (!tmp)
goto cleanup; goto end_coredump;
tmp->thread = ct->task; tmp->thread = ct->task;
list_add(&tmp->list, &thread_list); list_add(&tmp->list, &thread_list);
...@@ -1678,9 +1677,6 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm) ...@@ -1678,9 +1677,6 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
"LINUX", ELF_CORE_XFPREG_TYPE, sizeof(*xfpu), xfpu); "LINUX", ELF_CORE_XFPREG_TYPE, sizeof(*xfpu), xfpu);
#endif #endif
fs = get_fs();
set_fs(KERNEL_DS);
offset += sizeof(*elf); /* Elf header */ offset += sizeof(*elf); /* Elf header */
offset += segs * sizeof(struct elf_phdr); /* Program headers */ offset += segs * sizeof(struct elf_phdr); /* Program headers */
...@@ -1788,9 +1784,6 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm) ...@@ -1788,9 +1784,6 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
} }
end_coredump: end_coredump:
set_fs(fs);
cleanup:
while (!list_empty(&thread_list)) { while (!list_empty(&thread_list)) {
struct list_head *tmp = thread_list.next; struct list_head *tmp = thread_list.next;
list_del(tmp); list_del(tmp);
......
...@@ -43,7 +43,7 @@ ...@@ -43,7 +43,7 @@
*/ */
#define user_long_t compat_long_t #define user_long_t compat_long_t
#define user_siginfo_t compat_siginfo_t #define user_siginfo_t compat_siginfo_t
#define copy_siginfo_to_user copy_siginfo_to_user32 #define copy_siginfo_to_external copy_siginfo_to_external32
/* /*
* The machine-dependent core note format types are defined in elfcore-compat.h, * The machine-dependent core note format types are defined in elfcore-compat.h,
......
...@@ -402,8 +402,15 @@ long compat_get_bitmap(unsigned long *mask, const compat_ulong_t __user *umask, ...@@ -402,8 +402,15 @@ long compat_get_bitmap(unsigned long *mask, const compat_ulong_t __user *umask,
unsigned long bitmap_size); unsigned long bitmap_size);
long compat_put_bitmap(compat_ulong_t __user *umask, unsigned long *mask, long compat_put_bitmap(compat_ulong_t __user *umask, unsigned long *mask,
unsigned long bitmap_size); unsigned long bitmap_size);
int copy_siginfo_from_user32(kernel_siginfo_t *to, const struct compat_siginfo __user *from); void copy_siginfo_to_external32(struct compat_siginfo *to,
int copy_siginfo_to_user32(struct compat_siginfo __user *to, const kernel_siginfo_t *from); const struct kernel_siginfo *from);
int copy_siginfo_from_user32(kernel_siginfo_t *to,
const struct compat_siginfo __user *from);
int __copy_siginfo_to_user32(struct compat_siginfo __user *to,
const kernel_siginfo_t *from);
#ifndef copy_siginfo_to_user32
#define copy_siginfo_to_user32 __copy_siginfo_to_user32
#endif
int get_compat_sigevent(struct sigevent *event, int get_compat_sigevent(struct sigevent *event,
const struct compat_sigevent __user *u_event); const struct compat_sigevent __user *u_event);
......
...@@ -24,6 +24,14 @@ static inline void clear_siginfo(kernel_siginfo_t *info) ...@@ -24,6 +24,14 @@ static inline void clear_siginfo(kernel_siginfo_t *info)
#define SI_EXPANSION_SIZE (sizeof(struct siginfo) - sizeof(struct kernel_siginfo)) #define SI_EXPANSION_SIZE (sizeof(struct siginfo) - sizeof(struct kernel_siginfo))
static inline void copy_siginfo_to_external(siginfo_t *to,
const kernel_siginfo_t *from)
{
memcpy(to, from, sizeof(*from));
memset(((char *)to) + sizeof(struct kernel_siginfo), 0,
SI_EXPANSION_SIZE);
}
int copy_siginfo_to_user(siginfo_t __user *to, const kernel_siginfo_t *from); int copy_siginfo_to_user(siginfo_t __user *to, const kernel_siginfo_t *from);
int copy_siginfo_from_user(kernel_siginfo_t *to, const siginfo_t __user *from); int copy_siginfo_from_user(kernel_siginfo_t *to, const siginfo_t __user *from);
......
...@@ -3235,94 +3235,94 @@ int copy_siginfo_from_user(kernel_siginfo_t *to, const siginfo_t __user *from) ...@@ -3235,94 +3235,94 @@ int copy_siginfo_from_user(kernel_siginfo_t *to, const siginfo_t __user *from)
} }
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
int copy_siginfo_to_user32(struct compat_siginfo __user *to, /**
const struct kernel_siginfo *from) * copy_siginfo_to_external32 - copy a kernel siginfo into a compat user siginfo
#if defined(CONFIG_X86_X32_ABI) || defined(CONFIG_IA32_EMULATION) * @to: compat siginfo destination
{ * @from: kernel siginfo source
return __copy_siginfo_to_user32(to, from, in_x32_syscall()); *
} * Note: This function does not work properly for the SIGCHLD on x32, but
int __copy_siginfo_to_user32(struct compat_siginfo __user *to, * fortunately it doesn't have to. The only valid callers for this function are
const struct kernel_siginfo *from, bool x32_ABI) * copy_siginfo_to_user32, which is overriden for x32 and the coredump code.
#endif * The latter does not care because SIGCHLD will never cause a coredump.
*/
void copy_siginfo_to_external32(struct compat_siginfo *to,
const struct kernel_siginfo *from)
{ {
struct compat_siginfo new; memset(to, 0, sizeof(*to));
memset(&new, 0, sizeof(new));
new.si_signo = from->si_signo; to->si_signo = from->si_signo;
new.si_errno = from->si_errno; to->si_errno = from->si_errno;
new.si_code = from->si_code; to->si_code = from->si_code;
switch(siginfo_layout(from->si_signo, from->si_code)) { switch(siginfo_layout(from->si_signo, from->si_code)) {
case SIL_KILL: case SIL_KILL:
new.si_pid = from->si_pid; to->si_pid = from->si_pid;
new.si_uid = from->si_uid; to->si_uid = from->si_uid;
break; break;
case SIL_TIMER: case SIL_TIMER:
new.si_tid = from->si_tid; to->si_tid = from->si_tid;
new.si_overrun = from->si_overrun; to->si_overrun = from->si_overrun;
new.si_int = from->si_int; to->si_int = from->si_int;
break; break;
case SIL_POLL: case SIL_POLL:
new.si_band = from->si_band; to->si_band = from->si_band;
new.si_fd = from->si_fd; to->si_fd = from->si_fd;
break; break;
case SIL_FAULT: case SIL_FAULT:
new.si_addr = ptr_to_compat(from->si_addr); to->si_addr = ptr_to_compat(from->si_addr);
#ifdef __ARCH_SI_TRAPNO #ifdef __ARCH_SI_TRAPNO
new.si_trapno = from->si_trapno; to->si_trapno = from->si_trapno;
#endif #endif
break; break;
case SIL_FAULT_MCEERR: case SIL_FAULT_MCEERR:
new.si_addr = ptr_to_compat(from->si_addr); to->si_addr = ptr_to_compat(from->si_addr);
#ifdef __ARCH_SI_TRAPNO #ifdef __ARCH_SI_TRAPNO
new.si_trapno = from->si_trapno; to->si_trapno = from->si_trapno;
#endif #endif
new.si_addr_lsb = from->si_addr_lsb; to->si_addr_lsb = from->si_addr_lsb;
break; break;
case SIL_FAULT_BNDERR: case SIL_FAULT_BNDERR:
new.si_addr = ptr_to_compat(from->si_addr); to->si_addr = ptr_to_compat(from->si_addr);
#ifdef __ARCH_SI_TRAPNO #ifdef __ARCH_SI_TRAPNO
new.si_trapno = from->si_trapno; to->si_trapno = from->si_trapno;
#endif #endif
new.si_lower = ptr_to_compat(from->si_lower); to->si_lower = ptr_to_compat(from->si_lower);
new.si_upper = ptr_to_compat(from->si_upper); to->si_upper = ptr_to_compat(from->si_upper);
break; break;
case SIL_FAULT_PKUERR: case SIL_FAULT_PKUERR:
new.si_addr = ptr_to_compat(from->si_addr); to->si_addr = ptr_to_compat(from->si_addr);
#ifdef __ARCH_SI_TRAPNO #ifdef __ARCH_SI_TRAPNO
new.si_trapno = from->si_trapno; to->si_trapno = from->si_trapno;
#endif #endif
new.si_pkey = from->si_pkey; to->si_pkey = from->si_pkey;
break; break;
case SIL_CHLD: case SIL_CHLD:
new.si_pid = from->si_pid; to->si_pid = from->si_pid;
new.si_uid = from->si_uid; to->si_uid = from->si_uid;
new.si_status = from->si_status; to->si_status = from->si_status;
#ifdef CONFIG_X86_X32_ABI to->si_utime = from->si_utime;
if (x32_ABI) { to->si_stime = from->si_stime;
new._sifields._sigchld_x32._utime = from->si_utime;
new._sifields._sigchld_x32._stime = from->si_stime;
} else
#endif
{
new.si_utime = from->si_utime;
new.si_stime = from->si_stime;
}
break; break;
case SIL_RT: case SIL_RT:
new.si_pid = from->si_pid; to->si_pid = from->si_pid;
new.si_uid = from->si_uid; to->si_uid = from->si_uid;
new.si_int = from->si_int; to->si_int = from->si_int;
break; break;
case SIL_SYS: case SIL_SYS:
new.si_call_addr = ptr_to_compat(from->si_call_addr); to->si_call_addr = ptr_to_compat(from->si_call_addr);
new.si_syscall = from->si_syscall; to->si_syscall = from->si_syscall;
new.si_arch = from->si_arch; to->si_arch = from->si_arch;
break; break;
} }
}
int __copy_siginfo_to_user32(struct compat_siginfo __user *to,
const struct kernel_siginfo *from)
{
struct compat_siginfo new;
copy_siginfo_to_external32(&new, from);
if (copy_to_user(to, &new, sizeof(struct compat_siginfo))) if (copy_to_user(to, &new, sizeof(struct compat_siginfo)))
return -EFAULT; return -EFAULT;
return 0; return 0;
} }
......
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