mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2024-12-29 09:12:07 +00:00
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
This commit is contained in:
commit
8b39a57e96
@ -21,22 +21,6 @@
|
||||
|
||||
#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)
|
||||
{
|
||||
int i, sz, total = 0;
|
||||
@ -118,58 +102,43 @@ int spufs_coredump_extra_notes_size(void)
|
||||
static int spufs_arch_write_note(struct spu_context *ctx, int i,
|
||||
struct coredump_params *cprm, int dfd)
|
||||
{
|
||||
loff_t pos = 0;
|
||||
int sz, rc, total = 0;
|
||||
const int bufsz = PAGE_SIZE;
|
||||
char *name;
|
||||
char fullname[80], *buf;
|
||||
size_t sz = spufs_coredump_read[i].size;
|
||||
char fullname[80];
|
||||
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;
|
||||
sz = spufs_coredump_read[i].size;
|
||||
|
||||
sprintf(fullname, "SPU/%d/%s", dfd, name);
|
||||
sprintf(fullname, "SPU/%d/%s", dfd, spufs_coredump_read[i].name);
|
||||
en.n_namesz = strlen(fullname) + 1;
|
||||
en.n_descsz = sz;
|
||||
en.n_type = NT_SPU;
|
||||
|
||||
if (!dump_emit(cprm, &en, sizeof(en)))
|
||||
goto Eio;
|
||||
|
||||
return -EIO;
|
||||
if (!dump_emit(cprm, fullname, en.n_namesz))
|
||||
goto Eio;
|
||||
|
||||
return -EIO;
|
||||
if (!dump_align(cprm, 4))
|
||||
goto Eio;
|
||||
return -EIO;
|
||||
|
||||
do {
|
||||
rc = do_coredump_read(i, ctx, buf, bufsz, &pos);
|
||||
if (rc > 0) {
|
||||
if (!dump_emit(cprm, buf, rc))
|
||||
goto Eio;
|
||||
total += rc;
|
||||
}
|
||||
} while (rc == bufsz && total < sz);
|
||||
if (spufs_coredump_read[i].dump) {
|
||||
ret = spufs_coredump_read[i].dump(ctx, cprm);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
} else {
|
||||
char buf[32];
|
||||
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
ret = snprintf(buf, sizeof(buf), "0x%.16llx",
|
||||
spufs_coredump_read[i].get(ctx));
|
||||
if (ret >= sizeof(buf))
|
||||
return sizeof(buf);
|
||||
|
||||
skip = roundup(cprm->pos - total + sz, 4) - cprm->pos;
|
||||
if (!dump_skip(cprm, skip))
|
||||
goto Eio;
|
||||
/* count trailing the NULL: */
|
||||
if (!dump_emit(cprm, buf, ret + 1))
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
out:
|
||||
free_page((unsigned long)buf);
|
||||
return rc;
|
||||
Eio:
|
||||
free_page((unsigned long)buf);
|
||||
return -EIO;
|
||||
if (!dump_skip(cprm, roundup(cprm->pos - ret + sz, 4) - cprm->pos))
|
||||
return -EIO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int spufs_coredump_extra_notes_write(struct coredump_params *cprm)
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#undef DEBUG
|
||||
|
||||
#include <linux/coredump.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/ioctl.h>
|
||||
#include <linux/export.h>
|
||||
@ -129,6 +130,14 @@ static ssize_t spufs_attr_write(struct file *file, const char __user *buf,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t spufs_dump_emit(struct coredump_params *cprm, void *buf,
|
||||
size_t size)
|
||||
{
|
||||
if (!dump_emit(cprm, buf, size))
|
||||
return -EIO;
|
||||
return size;
|
||||
}
|
||||
|
||||
#define DEFINE_SPUFS_SIMPLE_ATTRIBUTE(__fops, __get, __set, __fmt) \
|
||||
static int __fops ## _open(struct inode *inode, struct file *file) \
|
||||
{ \
|
||||
@ -172,12 +181,9 @@ spufs_mem_release(struct inode *inode, struct file *file)
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
__spufs_mem_read(struct spu_context *ctx, char __user *buffer,
|
||||
size_t size, loff_t *pos)
|
||||
spufs_mem_dump(struct spu_context *ctx, struct coredump_params *cprm)
|
||||
{
|
||||
char *local_store = ctx->ops->get_ls(ctx);
|
||||
return simple_read_from_buffer(buffer, size, pos, local_store,
|
||||
LS_SIZE);
|
||||
return spufs_dump_emit(cprm, ctx->ops->get_ls(ctx), LS_SIZE);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
@ -190,7 +196,8 @@ spufs_mem_read(struct file *file, char __user *buffer,
|
||||
ret = spu_acquire(ctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = __spufs_mem_read(ctx, buffer, size, pos);
|
||||
ret = simple_read_from_buffer(buffer, size, pos, ctx->ops->get_ls(ctx),
|
||||
LS_SIZE);
|
||||
spu_release(ctx);
|
||||
|
||||
return ret;
|
||||
@ -459,12 +466,10 @@ spufs_regs_open(struct inode *inode, struct file *file)
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
__spufs_regs_read(struct spu_context *ctx, char __user *buffer,
|
||||
size_t size, loff_t *pos)
|
||||
spufs_regs_dump(struct spu_context *ctx, struct coredump_params *cprm)
|
||||
{
|
||||
struct spu_lscsa *lscsa = ctx->csa.lscsa;
|
||||
return simple_read_from_buffer(buffer, size, pos,
|
||||
lscsa->gprs, sizeof lscsa->gprs);
|
||||
return spufs_dump_emit(cprm, ctx->csa.lscsa->gprs,
|
||||
sizeof(ctx->csa.lscsa->gprs));
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
@ -482,7 +487,8 @@ spufs_regs_read(struct file *file, char __user *buffer,
|
||||
ret = spu_acquire_saved(ctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = __spufs_regs_read(ctx, buffer, size, pos);
|
||||
ret = simple_read_from_buffer(buffer, size, pos, ctx->csa.lscsa->gprs,
|
||||
sizeof(ctx->csa.lscsa->gprs));
|
||||
spu_release_saved(ctx);
|
||||
return ret;
|
||||
}
|
||||
@ -517,12 +523,10 @@ static const struct file_operations spufs_regs_fops = {
|
||||
};
|
||||
|
||||
static ssize_t
|
||||
__spufs_fpcr_read(struct spu_context *ctx, char __user * buffer,
|
||||
size_t size, loff_t * pos)
|
||||
spufs_fpcr_dump(struct spu_context *ctx, struct coredump_params *cprm)
|
||||
{
|
||||
struct spu_lscsa *lscsa = ctx->csa.lscsa;
|
||||
return simple_read_from_buffer(buffer, size, pos,
|
||||
&lscsa->fpcr, sizeof(lscsa->fpcr));
|
||||
return spufs_dump_emit(cprm, &ctx->csa.lscsa->fpcr,
|
||||
sizeof(ctx->csa.lscsa->fpcr));
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
@ -535,7 +539,8 @@ spufs_fpcr_read(struct file *file, char __user * buffer,
|
||||
ret = spu_acquire_saved(ctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = __spufs_fpcr_read(ctx, buffer, size, pos);
|
||||
ret = simple_read_from_buffer(buffer, size, pos, &ctx->csa.lscsa->fpcr,
|
||||
sizeof(ctx->csa.lscsa->fpcr));
|
||||
spu_release_saved(ctx);
|
||||
return ret;
|
||||
}
|
||||
@ -590,17 +595,12 @@ static ssize_t spufs_mbox_read(struct file *file, char __user *buf,
|
||||
size_t len, loff_t *pos)
|
||||
{
|
||||
struct spu_context *ctx = file->private_data;
|
||||
u32 mbox_data, __user *udata;
|
||||
u32 mbox_data, __user *udata = (void __user *)buf;
|
||||
ssize_t count;
|
||||
|
||||
if (len < 4)
|
||||
return -EINVAL;
|
||||
|
||||
if (!access_ok(buf, len))
|
||||
return -EFAULT;
|
||||
|
||||
udata = (void __user *)buf;
|
||||
|
||||
count = spu_acquire(ctx);
|
||||
if (count)
|
||||
return count;
|
||||
@ -616,7 +616,7 @@ static ssize_t spufs_mbox_read(struct file *file, char __user *buf,
|
||||
* but still need to return the data we have
|
||||
* read successfully so far.
|
||||
*/
|
||||
ret = __put_user(mbox_data, udata);
|
||||
ret = put_user(mbox_data, udata);
|
||||
if (ret) {
|
||||
if (!count)
|
||||
count = -EFAULT;
|
||||
@ -698,17 +698,12 @@ static ssize_t spufs_ibox_read(struct file *file, char __user *buf,
|
||||
size_t len, loff_t *pos)
|
||||
{
|
||||
struct spu_context *ctx = file->private_data;
|
||||
u32 ibox_data, __user *udata;
|
||||
u32 ibox_data, __user *udata = (void __user *)buf;
|
||||
ssize_t count;
|
||||
|
||||
if (len < 4)
|
||||
return -EINVAL;
|
||||
|
||||
if (!access_ok(buf, len))
|
||||
return -EFAULT;
|
||||
|
||||
udata = (void __user *)buf;
|
||||
|
||||
count = spu_acquire(ctx);
|
||||
if (count)
|
||||
goto out;
|
||||
@ -727,7 +722,7 @@ static ssize_t spufs_ibox_read(struct file *file, char __user *buf,
|
||||
}
|
||||
|
||||
/* if we can't write at all, return -EFAULT */
|
||||
count = __put_user(ibox_data, udata);
|
||||
count = put_user(ibox_data, udata);
|
||||
if (count)
|
||||
goto out_unlock;
|
||||
|
||||
@ -741,7 +736,7 @@ static ssize_t spufs_ibox_read(struct file *file, char __user *buf,
|
||||
* but still need to return the data we have
|
||||
* read successfully so far.
|
||||
*/
|
||||
ret = __put_user(ibox_data, udata);
|
||||
ret = put_user(ibox_data, udata);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
@ -836,17 +831,13 @@ static ssize_t spufs_wbox_write(struct file *file, const char __user *buf,
|
||||
size_t len, loff_t *pos)
|
||||
{
|
||||
struct spu_context *ctx = file->private_data;
|
||||
u32 wbox_data, __user *udata;
|
||||
u32 wbox_data, __user *udata = (void __user *)buf;
|
||||
ssize_t count;
|
||||
|
||||
if (len < 4)
|
||||
return -EINVAL;
|
||||
|
||||
udata = (void __user *)buf;
|
||||
if (!access_ok(buf, len))
|
||||
return -EFAULT;
|
||||
|
||||
if (__get_user(wbox_data, udata))
|
||||
if (get_user(wbox_data, udata))
|
||||
return -EFAULT;
|
||||
|
||||
count = spu_acquire(ctx);
|
||||
@ -873,7 +864,7 @@ static ssize_t spufs_wbox_write(struct file *file, const char __user *buf,
|
||||
/* write as much as possible */
|
||||
for (count = 4, udata++; (count + 4) <= len; count += 4, udata++) {
|
||||
int ret;
|
||||
ret = __get_user(wbox_data, udata);
|
||||
ret = get_user(wbox_data, udata);
|
||||
if (ret)
|
||||
break;
|
||||
|
||||
@ -967,28 +958,26 @@ spufs_signal1_release(struct inode *inode, struct file *file)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t __spufs_signal1_read(struct spu_context *ctx, char __user *buf,
|
||||
size_t len, loff_t *pos)
|
||||
static ssize_t spufs_signal1_dump(struct spu_context *ctx,
|
||||
struct coredump_params *cprm)
|
||||
{
|
||||
int ret = 0;
|
||||
u32 data;
|
||||
if (!ctx->csa.spu_chnlcnt_RW[3])
|
||||
return 0;
|
||||
return spufs_dump_emit(cprm, &ctx->csa.spu_chnldata_RW[3],
|
||||
sizeof(ctx->csa.spu_chnldata_RW[3]));
|
||||
}
|
||||
|
||||
if (len < 4)
|
||||
static ssize_t __spufs_signal1_read(struct spu_context *ctx, char __user *buf,
|
||||
size_t len)
|
||||
{
|
||||
if (len < sizeof(ctx->csa.spu_chnldata_RW[3]))
|
||||
return -EINVAL;
|
||||
|
||||
if (ctx->csa.spu_chnlcnt_RW[3]) {
|
||||
data = ctx->csa.spu_chnldata_RW[3];
|
||||
ret = 4;
|
||||
}
|
||||
|
||||
if (!ret)
|
||||
goto out;
|
||||
|
||||
if (copy_to_user(buf, &data, 4))
|
||||
if (!ctx->csa.spu_chnlcnt_RW[3])
|
||||
return 0;
|
||||
if (copy_to_user(buf, &ctx->csa.spu_chnldata_RW[3],
|
||||
sizeof(ctx->csa.spu_chnldata_RW[3])))
|
||||
return -EFAULT;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
return sizeof(ctx->csa.spu_chnldata_RW[3]);
|
||||
}
|
||||
|
||||
static ssize_t spufs_signal1_read(struct file *file, char __user *buf,
|
||||
@ -1000,7 +989,7 @@ static ssize_t spufs_signal1_read(struct file *file, char __user *buf,
|
||||
ret = spu_acquire_saved(ctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = __spufs_signal1_read(ctx, buf, len, pos);
|
||||
ret = __spufs_signal1_read(ctx, buf, len);
|
||||
spu_release_saved(ctx);
|
||||
|
||||
return ret;
|
||||
@ -1104,28 +1093,26 @@ spufs_signal2_release(struct inode *inode, struct file *file)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t __spufs_signal2_read(struct spu_context *ctx, char __user *buf,
|
||||
size_t len, loff_t *pos)
|
||||
static ssize_t spufs_signal2_dump(struct spu_context *ctx,
|
||||
struct coredump_params *cprm)
|
||||
{
|
||||
int ret = 0;
|
||||
u32 data;
|
||||
if (!ctx->csa.spu_chnlcnt_RW[4])
|
||||
return 0;
|
||||
return spufs_dump_emit(cprm, &ctx->csa.spu_chnldata_RW[4],
|
||||
sizeof(ctx->csa.spu_chnldata_RW[4]));
|
||||
}
|
||||
|
||||
if (len < 4)
|
||||
static ssize_t __spufs_signal2_read(struct spu_context *ctx, char __user *buf,
|
||||
size_t len)
|
||||
{
|
||||
if (len < sizeof(ctx->csa.spu_chnldata_RW[4]))
|
||||
return -EINVAL;
|
||||
|
||||
if (ctx->csa.spu_chnlcnt_RW[4]) {
|
||||
data = ctx->csa.spu_chnldata_RW[4];
|
||||
ret = 4;
|
||||
}
|
||||
|
||||
if (!ret)
|
||||
goto out;
|
||||
|
||||
if (copy_to_user(buf, &data, 4))
|
||||
if (!ctx->csa.spu_chnlcnt_RW[4])
|
||||
return 0;
|
||||
if (copy_to_user(buf, &ctx->csa.spu_chnldata_RW[4],
|
||||
sizeof(ctx->csa.spu_chnldata_RW[4])))
|
||||
return -EFAULT;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
return sizeof(ctx->csa.spu_chnldata_RW[4]);
|
||||
}
|
||||
|
||||
static ssize_t spufs_signal2_read(struct file *file, char __user *buf,
|
||||
@ -1137,7 +1124,7 @@ static ssize_t spufs_signal2_read(struct file *file, char __user *buf,
|
||||
ret = spu_acquire_saved(ctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = __spufs_signal2_read(ctx, buf, len, pos);
|
||||
ret = __spufs_signal2_read(ctx, buf, len);
|
||||
spu_release_saved(ctx);
|
||||
|
||||
return ret;
|
||||
@ -1961,38 +1948,36 @@ static const struct file_operations spufs_caps_fops = {
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
static ssize_t __spufs_mbox_info_read(struct spu_context *ctx,
|
||||
char __user *buf, size_t len, loff_t *pos)
|
||||
static ssize_t spufs_mbox_info_dump(struct spu_context *ctx,
|
||||
struct coredump_params *cprm)
|
||||
{
|
||||
u32 data;
|
||||
|
||||
/* EOF if there's no entry in the mbox */
|
||||
if (!(ctx->csa.prob.mb_stat_R & 0x0000ff))
|
||||
return 0;
|
||||
|
||||
data = ctx->csa.prob.pu_mb_R;
|
||||
|
||||
return simple_read_from_buffer(buf, len, pos, &data, sizeof data);
|
||||
return spufs_dump_emit(cprm, &ctx->csa.prob.pu_mb_R,
|
||||
sizeof(ctx->csa.prob.pu_mb_R));
|
||||
}
|
||||
|
||||
static ssize_t spufs_mbox_info_read(struct file *file, char __user *buf,
|
||||
size_t len, loff_t *pos)
|
||||
{
|
||||
int ret;
|
||||
struct spu_context *ctx = file->private_data;
|
||||
|
||||
if (!access_ok(buf, len))
|
||||
return -EFAULT;
|
||||
u32 stat, data;
|
||||
int ret;
|
||||
|
||||
ret = spu_acquire_saved(ctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
spin_lock(&ctx->csa.register_lock);
|
||||
ret = __spufs_mbox_info_read(ctx, buf, len, pos);
|
||||
stat = ctx->csa.prob.mb_stat_R;
|
||||
data = ctx->csa.prob.pu_mb_R;
|
||||
spin_unlock(&ctx->csa.register_lock);
|
||||
spu_release_saved(ctx);
|
||||
|
||||
return ret;
|
||||
/* EOF if there's no entry in the mbox */
|
||||
if (!(stat & 0x0000ff))
|
||||
return 0;
|
||||
|
||||
return simple_read_from_buffer(buf, len, pos, &data, sizeof(data));
|
||||
}
|
||||
|
||||
static const struct file_operations spufs_mbox_info_fops = {
|
||||
@ -2001,38 +1986,36 @@ static const struct file_operations spufs_mbox_info_fops = {
|
||||
.llseek = generic_file_llseek,
|
||||
};
|
||||
|
||||
static ssize_t __spufs_ibox_info_read(struct spu_context *ctx,
|
||||
char __user *buf, size_t len, loff_t *pos)
|
||||
static ssize_t spufs_ibox_info_dump(struct spu_context *ctx,
|
||||
struct coredump_params *cprm)
|
||||
{
|
||||
u32 data;
|
||||
|
||||
/* EOF if there's no entry in the ibox */
|
||||
if (!(ctx->csa.prob.mb_stat_R & 0xff0000))
|
||||
return 0;
|
||||
|
||||
data = ctx->csa.priv2.puint_mb_R;
|
||||
|
||||
return simple_read_from_buffer(buf, len, pos, &data, sizeof data);
|
||||
return spufs_dump_emit(cprm, &ctx->csa.priv2.puint_mb_R,
|
||||
sizeof(ctx->csa.priv2.puint_mb_R));
|
||||
}
|
||||
|
||||
static ssize_t spufs_ibox_info_read(struct file *file, char __user *buf,
|
||||
size_t len, loff_t *pos)
|
||||
{
|
||||
struct spu_context *ctx = file->private_data;
|
||||
u32 stat, data;
|
||||
int ret;
|
||||
|
||||
if (!access_ok(buf, len))
|
||||
return -EFAULT;
|
||||
|
||||
ret = spu_acquire_saved(ctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
spin_lock(&ctx->csa.register_lock);
|
||||
ret = __spufs_ibox_info_read(ctx, buf, len, pos);
|
||||
stat = ctx->csa.prob.mb_stat_R;
|
||||
data = ctx->csa.priv2.puint_mb_R;
|
||||
spin_unlock(&ctx->csa.register_lock);
|
||||
spu_release_saved(ctx);
|
||||
|
||||
return ret;
|
||||
/* EOF if there's no entry in the ibox */
|
||||
if (!(stat & 0xff0000))
|
||||
return 0;
|
||||
|
||||
return simple_read_from_buffer(buf, len, pos, &data, sizeof(data));
|
||||
}
|
||||
|
||||
static const struct file_operations spufs_ibox_info_fops = {
|
||||
@ -2041,41 +2024,36 @@ static const struct file_operations spufs_ibox_info_fops = {
|
||||
.llseek = generic_file_llseek,
|
||||
};
|
||||
|
||||
static ssize_t __spufs_wbox_info_read(struct spu_context *ctx,
|
||||
char __user *buf, size_t len, loff_t *pos)
|
||||
static size_t spufs_wbox_info_cnt(struct spu_context *ctx)
|
||||
{
|
||||
int i, cnt;
|
||||
u32 data[4];
|
||||
u32 wbox_stat;
|
||||
return (4 - ((ctx->csa.prob.mb_stat_R & 0x00ff00) >> 8)) * sizeof(u32);
|
||||
}
|
||||
|
||||
wbox_stat = ctx->csa.prob.mb_stat_R;
|
||||
cnt = 4 - ((wbox_stat & 0x00ff00) >> 8);
|
||||
for (i = 0; i < cnt; i++) {
|
||||
data[i] = ctx->csa.spu_mailbox_data[i];
|
||||
}
|
||||
|
||||
return simple_read_from_buffer(buf, len, pos, &data,
|
||||
cnt * sizeof(u32));
|
||||
static ssize_t spufs_wbox_info_dump(struct spu_context *ctx,
|
||||
struct coredump_params *cprm)
|
||||
{
|
||||
return spufs_dump_emit(cprm, &ctx->csa.spu_mailbox_data,
|
||||
spufs_wbox_info_cnt(ctx));
|
||||
}
|
||||
|
||||
static ssize_t spufs_wbox_info_read(struct file *file, char __user *buf,
|
||||
size_t len, loff_t *pos)
|
||||
{
|
||||
struct spu_context *ctx = file->private_data;
|
||||
int ret;
|
||||
|
||||
if (!access_ok(buf, len))
|
||||
return -EFAULT;
|
||||
u32 data[ARRAY_SIZE(ctx->csa.spu_mailbox_data)];
|
||||
int ret, count;
|
||||
|
||||
ret = spu_acquire_saved(ctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
spin_lock(&ctx->csa.register_lock);
|
||||
ret = __spufs_wbox_info_read(ctx, buf, len, pos);
|
||||
count = spufs_wbox_info_cnt(ctx);
|
||||
memcpy(&data, &ctx->csa.spu_mailbox_data, sizeof(data));
|
||||
spin_unlock(&ctx->csa.register_lock);
|
||||
spu_release_saved(ctx);
|
||||
|
||||
return ret;
|
||||
return simple_read_from_buffer(buf, len, pos, &data,
|
||||
count * sizeof(u32));
|
||||
}
|
||||
|
||||
static const struct file_operations spufs_wbox_info_fops = {
|
||||
@ -2084,50 +2062,53 @@ static const struct file_operations spufs_wbox_info_fops = {
|
||||
.llseek = generic_file_llseek,
|
||||
};
|
||||
|
||||
static ssize_t __spufs_dma_info_read(struct spu_context *ctx,
|
||||
char __user *buf, size_t len, loff_t *pos)
|
||||
static void spufs_get_dma_info(struct spu_context *ctx,
|
||||
struct spu_dma_info *info)
|
||||
{
|
||||
struct spu_dma_info info;
|
||||
struct mfc_cq_sr *qp, *spuqp;
|
||||
int i;
|
||||
|
||||
info.dma_info_type = ctx->csa.priv2.spu_tag_status_query_RW;
|
||||
info.dma_info_mask = ctx->csa.lscsa->tag_mask.slot[0];
|
||||
info.dma_info_status = ctx->csa.spu_chnldata_RW[24];
|
||||
info.dma_info_stall_and_notify = ctx->csa.spu_chnldata_RW[25];
|
||||
info.dma_info_atomic_command_status = ctx->csa.spu_chnldata_RW[27];
|
||||
info->dma_info_type = ctx->csa.priv2.spu_tag_status_query_RW;
|
||||
info->dma_info_mask = ctx->csa.lscsa->tag_mask.slot[0];
|
||||
info->dma_info_status = ctx->csa.spu_chnldata_RW[24];
|
||||
info->dma_info_stall_and_notify = ctx->csa.spu_chnldata_RW[25];
|
||||
info->dma_info_atomic_command_status = ctx->csa.spu_chnldata_RW[27];
|
||||
for (i = 0; i < 16; i++) {
|
||||
qp = &info.dma_info_command_data[i];
|
||||
spuqp = &ctx->csa.priv2.spuq[i];
|
||||
struct mfc_cq_sr *qp = &info->dma_info_command_data[i];
|
||||
struct mfc_cq_sr *spuqp = &ctx->csa.priv2.spuq[i];
|
||||
|
||||
qp->mfc_cq_data0_RW = spuqp->mfc_cq_data0_RW;
|
||||
qp->mfc_cq_data1_RW = spuqp->mfc_cq_data1_RW;
|
||||
qp->mfc_cq_data2_RW = spuqp->mfc_cq_data2_RW;
|
||||
qp->mfc_cq_data3_RW = spuqp->mfc_cq_data3_RW;
|
||||
}
|
||||
}
|
||||
|
||||
return simple_read_from_buffer(buf, len, pos, &info,
|
||||
sizeof info);
|
||||
static ssize_t spufs_dma_info_dump(struct spu_context *ctx,
|
||||
struct coredump_params *cprm)
|
||||
{
|
||||
struct spu_dma_info info;
|
||||
|
||||
spufs_get_dma_info(ctx, &info);
|
||||
return spufs_dump_emit(cprm, &info, sizeof(info));
|
||||
}
|
||||
|
||||
static ssize_t spufs_dma_info_read(struct file *file, char __user *buf,
|
||||
size_t len, loff_t *pos)
|
||||
{
|
||||
struct spu_context *ctx = file->private_data;
|
||||
struct spu_dma_info info;
|
||||
int ret;
|
||||
|
||||
if (!access_ok(buf, len))
|
||||
return -EFAULT;
|
||||
|
||||
ret = spu_acquire_saved(ctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
spin_lock(&ctx->csa.register_lock);
|
||||
ret = __spufs_dma_info_read(ctx, buf, len, pos);
|
||||
spufs_get_dma_info(ctx, &info);
|
||||
spin_unlock(&ctx->csa.register_lock);
|
||||
spu_release_saved(ctx);
|
||||
|
||||
return ret;
|
||||
return simple_read_from_buffer(buf, len, pos, &info,
|
||||
sizeof(info));
|
||||
}
|
||||
|
||||
static const struct file_operations spufs_dma_info_fops = {
|
||||
@ -2136,52 +2117,55 @@ static const struct file_operations spufs_dma_info_fops = {
|
||||
.llseek = no_llseek,
|
||||
};
|
||||
|
||||
static ssize_t __spufs_proxydma_info_read(struct spu_context *ctx,
|
||||
char __user *buf, size_t len, loff_t *pos)
|
||||
static void spufs_get_proxydma_info(struct spu_context *ctx,
|
||||
struct spu_proxydma_info *info)
|
||||
{
|
||||
struct spu_proxydma_info info;
|
||||
struct mfc_cq_sr *qp, *puqp;
|
||||
int ret = sizeof info;
|
||||
int i;
|
||||
|
||||
if (len < ret)
|
||||
return -EINVAL;
|
||||
info->proxydma_info_type = ctx->csa.prob.dma_querytype_RW;
|
||||
info->proxydma_info_mask = ctx->csa.prob.dma_querymask_RW;
|
||||
info->proxydma_info_status = ctx->csa.prob.dma_tagstatus_R;
|
||||
|
||||
if (!access_ok(buf, len))
|
||||
return -EFAULT;
|
||||
|
||||
info.proxydma_info_type = ctx->csa.prob.dma_querytype_RW;
|
||||
info.proxydma_info_mask = ctx->csa.prob.dma_querymask_RW;
|
||||
info.proxydma_info_status = ctx->csa.prob.dma_tagstatus_R;
|
||||
for (i = 0; i < 8; i++) {
|
||||
qp = &info.proxydma_info_command_data[i];
|
||||
puqp = &ctx->csa.priv2.puq[i];
|
||||
struct mfc_cq_sr *qp = &info->proxydma_info_command_data[i];
|
||||
struct mfc_cq_sr *puqp = &ctx->csa.priv2.puq[i];
|
||||
|
||||
qp->mfc_cq_data0_RW = puqp->mfc_cq_data0_RW;
|
||||
qp->mfc_cq_data1_RW = puqp->mfc_cq_data1_RW;
|
||||
qp->mfc_cq_data2_RW = puqp->mfc_cq_data2_RW;
|
||||
qp->mfc_cq_data3_RW = puqp->mfc_cq_data3_RW;
|
||||
}
|
||||
}
|
||||
|
||||
return simple_read_from_buffer(buf, len, pos, &info,
|
||||
sizeof info);
|
||||
static ssize_t spufs_proxydma_info_dump(struct spu_context *ctx,
|
||||
struct coredump_params *cprm)
|
||||
{
|
||||
struct spu_proxydma_info info;
|
||||
|
||||
spufs_get_proxydma_info(ctx, &info);
|
||||
return spufs_dump_emit(cprm, &info, sizeof(info));
|
||||
}
|
||||
|
||||
static ssize_t spufs_proxydma_info_read(struct file *file, char __user *buf,
|
||||
size_t len, loff_t *pos)
|
||||
{
|
||||
struct spu_context *ctx = file->private_data;
|
||||
struct spu_proxydma_info info;
|
||||
int ret;
|
||||
|
||||
if (len < sizeof(info))
|
||||
return -EINVAL;
|
||||
|
||||
ret = spu_acquire_saved(ctx);
|
||||
if (ret)
|
||||
return ret;
|
||||
spin_lock(&ctx->csa.register_lock);
|
||||
ret = __spufs_proxydma_info_read(ctx, buf, len, pos);
|
||||
spufs_get_proxydma_info(ctx, &info);
|
||||
spin_unlock(&ctx->csa.register_lock);
|
||||
spu_release_saved(ctx);
|
||||
|
||||
return ret;
|
||||
return simple_read_from_buffer(buf, len, pos, &info,
|
||||
sizeof(info));
|
||||
}
|
||||
|
||||
static const struct file_operations spufs_proxydma_info_fops = {
|
||||
@ -2625,23 +2609,23 @@ const struct spufs_tree_descr spufs_dir_debug_contents[] = {
|
||||
};
|
||||
|
||||
const struct spufs_coredump_reader spufs_coredump_read[] = {
|
||||
{ "regs", __spufs_regs_read, NULL, sizeof(struct spu_reg128[128])},
|
||||
{ "fpcr", __spufs_fpcr_read, NULL, sizeof(struct spu_reg128) },
|
||||
{ "regs", spufs_regs_dump, NULL, sizeof(struct spu_reg128[128])},
|
||||
{ "fpcr", spufs_fpcr_dump, NULL, sizeof(struct spu_reg128) },
|
||||
{ "lslr", NULL, spufs_lslr_get, 19 },
|
||||
{ "decr", NULL, spufs_decr_get, 19 },
|
||||
{ "decr_status", NULL, spufs_decr_status_get, 19 },
|
||||
{ "mem", __spufs_mem_read, NULL, LS_SIZE, },
|
||||
{ "signal1", __spufs_signal1_read, NULL, sizeof(u32) },
|
||||
{ "mem", spufs_mem_dump, NULL, LS_SIZE, },
|
||||
{ "signal1", spufs_signal1_dump, NULL, sizeof(u32) },
|
||||
{ "signal1_type", NULL, spufs_signal1_type_get, 19 },
|
||||
{ "signal2", __spufs_signal2_read, NULL, sizeof(u32) },
|
||||
{ "signal2", spufs_signal2_dump, NULL, sizeof(u32) },
|
||||
{ "signal2_type", NULL, spufs_signal2_type_get, 19 },
|
||||
{ "event_mask", NULL, spufs_event_mask_get, 19 },
|
||||
{ "event_status", NULL, spufs_event_status_get, 19 },
|
||||
{ "mbox_info", __spufs_mbox_info_read, NULL, sizeof(u32) },
|
||||
{ "ibox_info", __spufs_ibox_info_read, NULL, sizeof(u32) },
|
||||
{ "wbox_info", __spufs_wbox_info_read, NULL, 4 * sizeof(u32)},
|
||||
{ "dma_info", __spufs_dma_info_read, NULL, sizeof(struct spu_dma_info)},
|
||||
{ "proxydma_info", __spufs_proxydma_info_read,
|
||||
{ "mbox_info", spufs_mbox_info_dump, NULL, sizeof(u32) },
|
||||
{ "ibox_info", spufs_ibox_info_dump, NULL, sizeof(u32) },
|
||||
{ "wbox_info", spufs_wbox_info_dump, NULL, 4 * sizeof(u32)},
|
||||
{ "dma_info", spufs_dma_info_dump, NULL, sizeof(struct spu_dma_info)},
|
||||
{ "proxydma_info", spufs_proxydma_info_dump,
|
||||
NULL, sizeof(struct spu_proxydma_info)},
|
||||
{ "object-id", NULL, spufs_object_id_get, 19 },
|
||||
{ "npc", NULL, spufs_npc_get, 19 },
|
||||
|
@ -337,8 +337,7 @@ void spufs_dma_callback(struct spu *spu, int type);
|
||||
extern struct spu_coredump_calls spufs_coredump_calls;
|
||||
struct spufs_coredump_reader {
|
||||
char *name;
|
||||
ssize_t (*read)(struct spu_context *ctx,
|
||||
char __user *buffer, size_t size, loff_t *pos);
|
||||
ssize_t (*dump)(struct spu_context *ctx, struct coredump_params *cprm);
|
||||
u64 (*get)(struct spu_context *ctx);
|
||||
size_t size;
|
||||
};
|
||||
|
@ -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);
|
||||
user_access_end();
|
||||
|
||||
if (__copy_siginfo_to_user32(&frame->info, &ksig->info, false))
|
||||
if (__copy_siginfo_to_user32(&frame->info, &ksig->info))
|
||||
return -EFAULT;
|
||||
|
||||
/* Set up registers for signal handler */
|
||||
|
@ -214,7 +214,11 @@ static inline bool in_compat_syscall(void)
|
||||
#endif
|
||||
|
||||
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 */
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include <asm/vm86.h>
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
#include <linux/compat.h>
|
||||
#include <asm/proto.h>
|
||||
#include <asm/ia32_unistd.h>
|
||||
#endif /* CONFIG_X86_64 */
|
||||
@ -511,6 +512,31 @@ static int __setup_rt_frame(int sig, struct ksignal *ksig,
|
||||
}
|
||||
#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,
|
||||
compat_sigset_t *set,
|
||||
struct pt_regs *regs)
|
||||
@ -543,7 +569,7 @@ static int x32_setup_rt_frame(struct ksignal *ksig,
|
||||
user_access_end();
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1488,7 +1488,6 @@ static unsigned long vma_dump_size(struct vm_area_struct *vma,
|
||||
vma->vm_pgoff == 0 && (vma->vm_flags & VM_READ)) {
|
||||
u32 __user *header = (u32 __user *) vma->vm_start;
|
||||
u32 word;
|
||||
mm_segment_t fs = get_fs();
|
||||
/*
|
||||
* 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,
|
||||
magic.elfmag[EI_MAG1] = ELFMAG1;
|
||||
magic.elfmag[EI_MAG2] = ELFMAG2;
|
||||
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)))
|
||||
word = 0;
|
||||
set_fs(fs);
|
||||
if (word == magic.cmp)
|
||||
return PAGE_SIZE;
|
||||
}
|
||||
@ -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,
|
||||
const kernel_siginfo_t *siginfo)
|
||||
{
|
||||
mm_segment_t old_fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
copy_siginfo_to_user((user_siginfo_t __user *) csigdata, siginfo);
|
||||
set_fs(old_fs);
|
||||
copy_siginfo_to_external(csigdata, siginfo);
|
||||
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,
|
||||
static int elf_core_dump(struct coredump_params *cprm)
|
||||
{
|
||||
int has_dumped = 0;
|
||||
mm_segment_t fs;
|
||||
int segs, i;
|
||||
size_t vma_data_size = 0;
|
||||
struct vm_area_struct *vma, *gate_vma;
|
||||
@ -2368,13 +2357,10 @@ static int elf_core_dump(struct coredump_params *cprm)
|
||||
* notes. This also sets up the file header.
|
||||
*/
|
||||
if (!fill_note_info(&elf, e_phnum, &info, cprm->siginfo, cprm->regs))
|
||||
goto cleanup;
|
||||
goto end_coredump;
|
||||
|
||||
has_dumped = 1;
|
||||
|
||||
fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
|
||||
offset += sizeof(elf); /* Elf header */
|
||||
offset += segs * sizeof(struct elf_phdr); /* Program headers */
|
||||
|
||||
@ -2502,9 +2488,6 @@ static int elf_core_dump(struct coredump_params *cprm)
|
||||
}
|
||||
|
||||
end_coredump:
|
||||
set_fs(fs);
|
||||
|
||||
cleanup:
|
||||
free_note_info(&info);
|
||||
kfree(shdr4extnum);
|
||||
kvfree(vma_filesz);
|
||||
|
@ -1549,7 +1549,6 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
|
||||
{
|
||||
#define NUM_NOTES 6
|
||||
int has_dumped = 0;
|
||||
mm_segment_t fs;
|
||||
int segs;
|
||||
int i;
|
||||
struct vm_area_struct *vma;
|
||||
@ -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 */
|
||||
elf = kmalloc(sizeof(*elf), GFP_KERNEL);
|
||||
if (!elf)
|
||||
goto cleanup;
|
||||
goto end_coredump;
|
||||
prstatus = kzalloc(sizeof(*prstatus), GFP_KERNEL);
|
||||
if (!prstatus)
|
||||
goto cleanup;
|
||||
goto end_coredump;
|
||||
psinfo = kmalloc(sizeof(*psinfo), GFP_KERNEL);
|
||||
if (!psinfo)
|
||||
goto cleanup;
|
||||
goto end_coredump;
|
||||
notes = kmalloc_array(NUM_NOTES, sizeof(struct memelfnote),
|
||||
GFP_KERNEL);
|
||||
if (!notes)
|
||||
goto cleanup;
|
||||
goto end_coredump;
|
||||
fpu = kmalloc(sizeof(*fpu), GFP_KERNEL);
|
||||
if (!fpu)
|
||||
goto cleanup;
|
||||
goto end_coredump;
|
||||
#ifdef ELF_CORE_COPY_XFPREGS
|
||||
xfpu = kmalloc(sizeof(*xfpu), GFP_KERNEL);
|
||||
if (!xfpu)
|
||||
goto cleanup;
|
||||
goto end_coredump;
|
||||
#endif
|
||||
|
||||
for (ct = current->mm->core_state->dumper.next;
|
||||
ct; ct = ct->next) {
|
||||
tmp = kzalloc(sizeof(*tmp), GFP_KERNEL);
|
||||
if (!tmp)
|
||||
goto cleanup;
|
||||
goto end_coredump;
|
||||
|
||||
tmp->thread = ct->task;
|
||||
list_add(&tmp->list, &thread_list);
|
||||
@ -1678,9 +1677,6 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
|
||||
"LINUX", ELF_CORE_XFPREG_TYPE, sizeof(*xfpu), xfpu);
|
||||
#endif
|
||||
|
||||
fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
|
||||
offset += sizeof(*elf); /* Elf header */
|
||||
offset += segs * sizeof(struct elf_phdr); /* Program headers */
|
||||
|
||||
@ -1788,9 +1784,6 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
|
||||
}
|
||||
|
||||
end_coredump:
|
||||
set_fs(fs);
|
||||
|
||||
cleanup:
|
||||
while (!list_empty(&thread_list)) {
|
||||
struct list_head *tmp = thread_list.next;
|
||||
list_del(tmp);
|
||||
|
@ -43,7 +43,7 @@
|
||||
*/
|
||||
#define user_long_t compat_long_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,
|
||||
|
@ -402,8 +402,15 @@ long compat_get_bitmap(unsigned long *mask, const compat_ulong_t __user *umask,
|
||||
unsigned long bitmap_size);
|
||||
long compat_put_bitmap(compat_ulong_t __user *umask, unsigned long *mask,
|
||||
unsigned long bitmap_size);
|
||||
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);
|
||||
void copy_siginfo_to_external32(struct compat_siginfo *to,
|
||||
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,
|
||||
const struct compat_sigevent __user *u_event);
|
||||
|
||||
|
@ -24,6 +24,14 @@ static inline void clear_siginfo(kernel_siginfo_t *info)
|
||||
|
||||
#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_from_user(kernel_siginfo_t *to, const siginfo_t __user *from);
|
||||
|
||||
|
106
kernel/signal.c
106
kernel/signal.c
@ -3235,94 +3235,94 @@ int copy_siginfo_from_user(kernel_siginfo_t *to, const siginfo_t __user *from)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
int copy_siginfo_to_user32(struct compat_siginfo __user *to,
|
||||
const struct kernel_siginfo *from)
|
||||
#if defined(CONFIG_X86_X32_ABI) || defined(CONFIG_IA32_EMULATION)
|
||||
/**
|
||||
* copy_siginfo_to_external32 - copy a kernel siginfo into a compat user siginfo
|
||||
* @to: compat siginfo destination
|
||||
* @from: kernel siginfo source
|
||||
*
|
||||
* Note: This function does not work properly for the SIGCHLD on x32, but
|
||||
* fortunately it doesn't have to. The only valid callers for this function are
|
||||
* copy_siginfo_to_user32, which is overriden for x32 and the coredump code.
|
||||
* 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)
|
||||
{
|
||||
return __copy_siginfo_to_user32(to, from, in_x32_syscall());
|
||||
}
|
||||
int __copy_siginfo_to_user32(struct compat_siginfo __user *to,
|
||||
const struct kernel_siginfo *from, bool x32_ABI)
|
||||
#endif
|
||||
{
|
||||
struct compat_siginfo new;
|
||||
memset(&new, 0, sizeof(new));
|
||||
memset(to, 0, sizeof(*to));
|
||||
|
||||
new.si_signo = from->si_signo;
|
||||
new.si_errno = from->si_errno;
|
||||
new.si_code = from->si_code;
|
||||
to->si_signo = from->si_signo;
|
||||
to->si_errno = from->si_errno;
|
||||
to->si_code = from->si_code;
|
||||
switch(siginfo_layout(from->si_signo, from->si_code)) {
|
||||
case SIL_KILL:
|
||||
new.si_pid = from->si_pid;
|
||||
new.si_uid = from->si_uid;
|
||||
to->si_pid = from->si_pid;
|
||||
to->si_uid = from->si_uid;
|
||||
break;
|
||||
case SIL_TIMER:
|
||||
new.si_tid = from->si_tid;
|
||||
new.si_overrun = from->si_overrun;
|
||||
new.si_int = from->si_int;
|
||||
to->si_tid = from->si_tid;
|
||||
to->si_overrun = from->si_overrun;
|
||||
to->si_int = from->si_int;
|
||||
break;
|
||||
case SIL_POLL:
|
||||
new.si_band = from->si_band;
|
||||
new.si_fd = from->si_fd;
|
||||
to->si_band = from->si_band;
|
||||
to->si_fd = from->si_fd;
|
||||
break;
|
||||
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
|
||||
new.si_trapno = from->si_trapno;
|
||||
to->si_trapno = from->si_trapno;
|
||||
#endif
|
||||
break;
|
||||
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
|
||||
new.si_trapno = from->si_trapno;
|
||||
to->si_trapno = from->si_trapno;
|
||||
#endif
|
||||
new.si_addr_lsb = from->si_addr_lsb;
|
||||
to->si_addr_lsb = from->si_addr_lsb;
|
||||
break;
|
||||
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
|
||||
new.si_trapno = from->si_trapno;
|
||||
to->si_trapno = from->si_trapno;
|
||||
#endif
|
||||
new.si_lower = ptr_to_compat(from->si_lower);
|
||||
new.si_upper = ptr_to_compat(from->si_upper);
|
||||
to->si_lower = ptr_to_compat(from->si_lower);
|
||||
to->si_upper = ptr_to_compat(from->si_upper);
|
||||
break;
|
||||
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
|
||||
new.si_trapno = from->si_trapno;
|
||||
to->si_trapno = from->si_trapno;
|
||||
#endif
|
||||
new.si_pkey = from->si_pkey;
|
||||
to->si_pkey = from->si_pkey;
|
||||
break;
|
||||
case SIL_CHLD:
|
||||
new.si_pid = from->si_pid;
|
||||
new.si_uid = from->si_uid;
|
||||
new.si_status = from->si_status;
|
||||
#ifdef CONFIG_X86_X32_ABI
|
||||
if (x32_ABI) {
|
||||
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;
|
||||
}
|
||||
to->si_pid = from->si_pid;
|
||||
to->si_uid = from->si_uid;
|
||||
to->si_status = from->si_status;
|
||||
to->si_utime = from->si_utime;
|
||||
to->si_stime = from->si_stime;
|
||||
break;
|
||||
case SIL_RT:
|
||||
new.si_pid = from->si_pid;
|
||||
new.si_uid = from->si_uid;
|
||||
new.si_int = from->si_int;
|
||||
to->si_pid = from->si_pid;
|
||||
to->si_uid = from->si_uid;
|
||||
to->si_int = from->si_int;
|
||||
break;
|
||||
case SIL_SYS:
|
||||
new.si_call_addr = ptr_to_compat(from->si_call_addr);
|
||||
new.si_syscall = from->si_syscall;
|
||||
new.si_arch = from->si_arch;
|
||||
to->si_call_addr = ptr_to_compat(from->si_call_addr);
|
||||
to->si_syscall = from->si_syscall;
|
||||
to->si_arch = from->si_arch;
|
||||
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)))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user