diff options
Diffstat (limited to 'arch/powerpc/kernel/rtas.c')
| -rw-r--r-- | arch/powerpc/kernel/rtas.c | 39 | 
1 files changed, 23 insertions, 16 deletions
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 4cf674d7d5a..8b4c857c142 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -993,32 +993,36 @@ struct pseries_errorlog *get_pseries_errorlog(struct rtas_error_log *log,  		(struct rtas_ext_event_log_v6 *)log->buffer;  	struct pseries_errorlog *sect;  	unsigned char *p, *log_end; +	uint32_t ext_log_length = rtas_error_extended_log_length(log); +	uint8_t log_format = rtas_ext_event_log_format(ext_log); +	uint32_t company_id = rtas_ext_event_company_id(ext_log);  	/* Check that we understand the format */ -	if (log->extended_log_length < sizeof(struct rtas_ext_event_log_v6) || -	    ext_log->log_format != RTAS_V6EXT_LOG_FORMAT_EVENT_LOG || -	    ext_log->company_id != RTAS_V6EXT_COMPANY_ID_IBM) +	if (ext_log_length < sizeof(struct rtas_ext_event_log_v6) || +	    log_format != RTAS_V6EXT_LOG_FORMAT_EVENT_LOG || +	    company_id != RTAS_V6EXT_COMPANY_ID_IBM)  		return NULL; -	log_end = log->buffer + log->extended_log_length; +	log_end = log->buffer + ext_log_length;  	p = ext_log->vendor_log;  	while (p < log_end) {  		sect = (struct pseries_errorlog *)p; -		if (sect->id == section_id) +		if (pseries_errorlog_id(sect) == section_id)  			return sect; -		p += sect->length; +		p += pseries_errorlog_length(sect);  	}  	return NULL;  } +/* We assume to be passed big endian arguments */  asmlinkage int ppc_rtas(struct rtas_args __user *uargs)  {  	struct rtas_args args;  	unsigned long flags;  	char *buff_copy, *errbuf = NULL; -	int nargs; +	int nargs, nret, token;  	int rc;  	if (!capable(CAP_SYS_ADMIN)) @@ -1027,10 +1031,13 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs)  	if (copy_from_user(&args, uargs, 3 * sizeof(u32)) != 0)  		return -EFAULT; -	nargs = args.nargs; +	nargs = be32_to_cpu(args.nargs); +	nret  = be32_to_cpu(args.nret); +	token = be32_to_cpu(args.token); +  	if (nargs > ARRAY_SIZE(args.args) -	    || args.nret > ARRAY_SIZE(args.args) -	    || nargs + args.nret > ARRAY_SIZE(args.args)) +	    || nret > ARRAY_SIZE(args.args) +	    || nargs + nret > ARRAY_SIZE(args.args))  		return -EINVAL;  	/* Copy in args. */ @@ -1038,14 +1045,14 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs)  			   nargs * sizeof(rtas_arg_t)) != 0)  		return -EFAULT; -	if (args.token == RTAS_UNKNOWN_SERVICE) +	if (token == RTAS_UNKNOWN_SERVICE)  		return -EINVAL;  	args.rets = &args.args[nargs]; -	memset(args.rets, 0, args.nret * sizeof(rtas_arg_t)); +	memset(args.rets, 0, nret * sizeof(rtas_arg_t));  	/* Need to handle ibm,suspend_me call specially */ -	if (args.token == ibm_suspend_me_token) { +	if (token == ibm_suspend_me_token) {  		rc = rtas_ibm_suspend_me(&args);  		if (rc)  			return rc; @@ -1062,7 +1069,7 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs)  	/* A -1 return code indicates that the last command couldn't  	   be completed due to a hardware error. */ -	if (args.rets[0] == -1) +	if (be32_to_cpu(args.rets[0]) == -1)  		errbuf = __fetch_rtas_last_error(buff_copy);  	unlock_rtas(flags); @@ -1077,7 +1084,7 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs)  	/* Copy out args. */  	if (copy_to_user(uargs->args + nargs,  			 args.args + nargs, -			 args.nret * sizeof(rtas_arg_t)) != 0) +			 nret * sizeof(rtas_arg_t)) != 0)  		return -EFAULT;  	return 0; @@ -1135,7 +1142,7 @@ void __init rtas_initialize(void)  int __init early_init_dt_scan_rtas(unsigned long node,  		const char *uname, int depth, void *data)  { -	u32 *basep, *entryp, *sizep; +	const u32 *basep, *entryp, *sizep;  	if (depth != 1 || strcmp(uname, "rtas") != 0)  		return 0;  | 
