diff options
Diffstat (limited to 'arch/powerpc/kernel/rtas.c')
-rw-r--r-- | arch/powerpc/kernel/rtas.c | 22 |
1 files changed, 13 insertions, 9 deletions
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 4cf674d7d5ae..f386296ff378 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c | |||
@@ -1013,12 +1013,13 @@ struct pseries_errorlog *get_pseries_errorlog(struct rtas_error_log *log, | |||
1013 | return NULL; | 1013 | return NULL; |
1014 | } | 1014 | } |
1015 | 1015 | ||
1016 | /* We assume to be passed big endian arguments */ | ||
1016 | asmlinkage int ppc_rtas(struct rtas_args __user *uargs) | 1017 | asmlinkage int ppc_rtas(struct rtas_args __user *uargs) |
1017 | { | 1018 | { |
1018 | struct rtas_args args; | 1019 | struct rtas_args args; |
1019 | unsigned long flags; | 1020 | unsigned long flags; |
1020 | char *buff_copy, *errbuf = NULL; | 1021 | char *buff_copy, *errbuf = NULL; |
1021 | int nargs; | 1022 | int nargs, nret, token; |
1022 | int rc; | 1023 | int rc; |
1023 | 1024 | ||
1024 | if (!capable(CAP_SYS_ADMIN)) | 1025 | if (!capable(CAP_SYS_ADMIN)) |
@@ -1027,10 +1028,13 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs) | |||
1027 | if (copy_from_user(&args, uargs, 3 * sizeof(u32)) != 0) | 1028 | if (copy_from_user(&args, uargs, 3 * sizeof(u32)) != 0) |
1028 | return -EFAULT; | 1029 | return -EFAULT; |
1029 | 1030 | ||
1030 | nargs = args.nargs; | 1031 | nargs = be32_to_cpu(args.nargs); |
1032 | nret = be32_to_cpu(args.nret); | ||
1033 | token = be32_to_cpu(args.token); | ||
1034 | |||
1031 | if (nargs > ARRAY_SIZE(args.args) | 1035 | if (nargs > ARRAY_SIZE(args.args) |
1032 | || args.nret > ARRAY_SIZE(args.args) | 1036 | || nret > ARRAY_SIZE(args.args) |
1033 | || nargs + args.nret > ARRAY_SIZE(args.args)) | 1037 | || nargs + nret > ARRAY_SIZE(args.args)) |
1034 | return -EINVAL; | 1038 | return -EINVAL; |
1035 | 1039 | ||
1036 | /* Copy in args. */ | 1040 | /* Copy in args. */ |
@@ -1038,14 +1042,14 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs) | |||
1038 | nargs * sizeof(rtas_arg_t)) != 0) | 1042 | nargs * sizeof(rtas_arg_t)) != 0) |
1039 | return -EFAULT; | 1043 | return -EFAULT; |
1040 | 1044 | ||
1041 | if (args.token == RTAS_UNKNOWN_SERVICE) | 1045 | if (token == RTAS_UNKNOWN_SERVICE) |
1042 | return -EINVAL; | 1046 | return -EINVAL; |
1043 | 1047 | ||
1044 | args.rets = &args.args[nargs]; | 1048 | args.rets = &args.args[nargs]; |
1045 | memset(args.rets, 0, args.nret * sizeof(rtas_arg_t)); | 1049 | memset(args.rets, 0, nret * sizeof(rtas_arg_t)); |
1046 | 1050 | ||
1047 | /* Need to handle ibm,suspend_me call specially */ | 1051 | /* Need to handle ibm,suspend_me call specially */ |
1048 | if (args.token == ibm_suspend_me_token) { | 1052 | if (token == ibm_suspend_me_token) { |
1049 | rc = rtas_ibm_suspend_me(&args); | 1053 | rc = rtas_ibm_suspend_me(&args); |
1050 | if (rc) | 1054 | if (rc) |
1051 | return rc; | 1055 | return rc; |
@@ -1062,7 +1066,7 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs) | |||
1062 | 1066 | ||
1063 | /* A -1 return code indicates that the last command couldn't | 1067 | /* A -1 return code indicates that the last command couldn't |
1064 | be completed due to a hardware error. */ | 1068 | be completed due to a hardware error. */ |
1065 | if (args.rets[0] == -1) | 1069 | if (be32_to_cpu(args.rets[0]) == -1) |
1066 | errbuf = __fetch_rtas_last_error(buff_copy); | 1070 | errbuf = __fetch_rtas_last_error(buff_copy); |
1067 | 1071 | ||
1068 | unlock_rtas(flags); | 1072 | unlock_rtas(flags); |
@@ -1077,7 +1081,7 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs) | |||
1077 | /* Copy out args. */ | 1081 | /* Copy out args. */ |
1078 | if (copy_to_user(uargs->args + nargs, | 1082 | if (copy_to_user(uargs->args + nargs, |
1079 | args.args + nargs, | 1083 | args.args + nargs, |
1080 | args.nret * sizeof(rtas_arg_t)) != 0) | 1084 | nret * sizeof(rtas_arg_t)) != 0) |
1081 | return -EFAULT; | 1085 | return -EFAULT; |
1082 | 1086 | ||
1083 | return 0; | 1087 | return 0; |