[OpenBIOS] [commit] r1250 - trunk/openbios-devel/libopenbios
repository service
svn at openbios.org
Mon Jan 13 10:46:44 CET 2014
Author: mcayland
Date: Mon Jan 13 10:46:43 2014
New Revision: 1250
URL: http://tracker.coreboot.org/trac/openbios/changeset/1250
Log:
client.c: stop clients from being able to invoke stack underflow
Clients that incorrectly requested too many return arguments for a client
interface call could cause a Forth stack underflow (this was discovered due
to a bug in NetBSD SPARC64).
Ensure that we can never POP() beyond the original position of the stack from
before the client interface call.
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland at ilande.co.uk>
Modified:
trunk/openbios-devel/libopenbios/client.c
Modified: trunk/openbios-devel/libopenbios/client.c
==============================================================================
--- trunk/openbios-devel/libopenbios/client.c Mon Jan 13 10:46:41 2014 (r1249)
+++ trunk/openbios-devel/libopenbios/client.c Mon Jan 13 10:46:43 2014 (r1250)
@@ -244,41 +244,43 @@
/* call-method, interpret */
static int
-handle_calls( prom_args_t *pb )
+handle_calls(prom_args_t *pb)
{
- int i, dstacksave = dstackcnt;
- prom_uarg_t val;
+ int i, j, dstacksave;
+ ucell val;
#ifdef DEBUG_CIF
printk("%s %s ([" FMT_prom_arg "] -- [" FMT_prom_arg "])\n",
get_service(pb), arg2pointer(pb->args[0]), pb->nargs, pb->nret);
#endif
+ dstacksave = dstackcnt;
for (i = pb->nargs - 1; i >= 0; i--)
PUSH(pb->args[i]);
push_str(get_service(pb));
fword("client-call-iface");
- /* Drop the return code from client-call-iface (status is handled by the
- catch result which is the first parameter below) */
- POP();
-
- for (i = 0; i < pb->nret; i++) {
- val = POP();
- pb->args[pb->nargs + i] = val;
+ /* If the catch result is non-zero, restore stack and exit */
+ val = POP();
+ if (val) {
+ dstackcnt = dstacksave;
+ return 0;
+ }
- /* don't pop args if an exception occured */
- if (!i && val)
- break;
+ j = dstackcnt;
+ for (i = 0; i < pb->nret; i++, j--) {
+ if (dstackcnt > dstacksave) {
+ pb->args[pb->nargs + i] = POP();
+ }
}
#ifdef DEBUG_CIF
/* useful for debug but not necessarily an error */
- if (i != pb->nret || dstackcnt != dstacksave) {
+ if (j != dstacksave) {
printk("%s '%s': possible argument error (" FMT_prom_arg "--" FMT_prom_arg ") got %d\n",
get_service(pb), arg2pointer(pb->args[0]),
- pb->nargs - 2, pb->nret, i);
+ pb->nargs - 2, pb->nret, j - dstacksave);
}
printk("handle_calls return:");
@@ -293,10 +295,11 @@
}
int
-of_client_interface( int *params )
+of_client_interface(int *params)
{
prom_args_t *pb = (prom_args_t*)params;
- int val, i, dstacksave;
+ ucell val;
+ int i, j, dstacksave;
if (pb->nargs < 0 || pb->nret < 0 ||
pb->nargs + pb->nret > PROM_MAX_ARGS)
@@ -317,34 +320,41 @@
push_str(get_service(pb));
fword("client-iface");
- if (val=POP()) {
- dstackcnt = dstacksave;
- if (val == -1)
+ val = POP();
+ if (val) {
+ if (val == -1) {
printk("Unimplemented service %s ([" FMT_prom_arg "] -- [" FMT_prom_arg "])\n",
- get_service(pb), pb->nargs, pb->nret);
+ get_service(pb), pb->nargs, pb->nret);
+ } else {
#ifdef DEBUG_CIF
- else
- printk("ERROR!\n");
+ printk("Error calling client interface: " FMT_ucellx "\n", val);
#endif
+ }
+
+ dstackcnt = dstacksave;
return -1;
}
- for (i = 0; i < pb->nret ; i++)
- pb->args[pb->nargs + i] = POP();
+ j = dstackcnt;
+ for (i = 0; i < pb->nret; i++, j--) {
+ if (dstackcnt > dstacksave) {
+ pb->args[pb->nargs + i] = POP();
+ }
+ }
- if (dstackcnt != dstacksave) {
#ifdef DEBUG_CIF
+ if (j != dstacksave) {
printk("service %s: possible argument error (%d %d)\n",
- get_service(pb), i, dstackcnt - dstacksave);
-#endif
+ get_service(pb), i, j - dstacksave);
+
/* Some clients request less parameters than the CIF method
returns, e.g. getprop with OpenSolaris. Hence we drop any
- stack parameters after issuing a warning above */
- dstackcnt = dstacksave;
+ stack parameters on exit after issuing a warning above */
}
-#ifdef DEBUG_CIF
dump_return(pb);
#endif
+
+ dstackcnt = dstacksave;
return 0;
}
More information about the OpenBIOS
mailing list