Print this page
NEX-16554 alloca() in libscf causes an iSCSI application to crash
Reviewed by: Yuri Pankon <yuri.pankov@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>

@@ -36,11 +36,10 @@
 
 #include "repcache_protocol.h"
 #include "scf_type.h"
 
 #include <assert.h>
-#include <alloca.h>
 #include <door.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <fnmatch.h>
 #include <libuutil.h>

@@ -4080,12 +4079,16 @@
                 assert(TX_SIZE(size) == size);
                 total += size;
         }
 
         request_size = REP_PROTOCOL_TRANSACTION_COMMIT_SIZE(total);
-        request = alloca(request_size);
-        (void) memset(request, '\0', request_size);
+        request = calloc(1, request_size);
+        if (request == NULL) {
+                (void) pthread_mutex_unlock(&h->rh_lock);
+                return (scf_set_error(SCF_ERROR_NO_MEMORY));
+        }
+
         request->rpr_request = REP_PROTOCOL_PROPERTYGRP_TX_COMMIT;
         request->rpr_entityid = tran->tran_pg.rd_d.rd_entity;
         request->rpr_size = request_size;
         cmd = (uintptr_t)request->rpr_cmd;
 

@@ -4095,11 +4098,12 @@
         for (cur = uu_list_first(tran->tran_props); cur != NULL;
             cur = uu_list_next(tran->tran_props, cur)) {
                 size = commit_process(cur, (void *)cmd);
                 if (size == BAD_SIZE) {
                         (void) pthread_mutex_unlock(&h->rh_lock);
-                        return (scf_set_error(SCF_ERROR_INTERNAL));
+                        r = (scf_set_error(SCF_ERROR_INTERNAL));
+                        goto out;
                 }
                 cmd += size;
                 new_total += size;
         }
         assert(new_total == total);

@@ -4113,16 +4117,21 @@
         }
 
         if (response.rpr_response != REP_PROTOCOL_SUCCESS &&
             response.rpr_response != REP_PROTOCOL_FAIL_NOT_LATEST) {
                 (void) pthread_mutex_unlock(&h->rh_lock);
-                return (scf_set_error(proto_error(response.rpr_response)));
+                r = (scf_set_error(proto_error(response.rpr_response)));
+                goto out;
         }
 
         tran->tran_state = TRAN_STATE_COMMITTED;
         (void) pthread_mutex_unlock(&h->rh_lock);
-        return (response.rpr_response == REP_PROTOCOL_SUCCESS);
+        r = (response.rpr_response == REP_PROTOCOL_SUCCESS);
+
+out:
+        free(request);
+        return (r);
 }
 
 static void
 transaction_reset(scf_transaction_t *tran)
 {