mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-09-18 22:14:16 +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
					
				
					 12 changed files with 296 additions and 323 deletions
				
			
		|  | @ -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 @@ out: | |||
| 	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 @@ Efault: | |||
| } | ||||
| #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…
	
	Add table
		
		Reference in a new issue
	
	 Linus Torvalds
						Linus Torvalds