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>


  21 
  22 /*
  23  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2013, Joyent, Inc. All rights reserved.
  25  * Copyright 2016 RackTop Systems.
  26  * Copyright (c) 2016 by Delphix. All rights reserved.
  27  * Copyright 2017 OmniOS Community Edition (OmniOSce) Association.
  28  */
  29 
  30 /*
  31  * This is the main implementation file for the low-level repository
  32  * interface.
  33  */
  34 
  35 #include "lowlevel_impl.h"
  36 
  37 #include "repcache_protocol.h"
  38 #include "scf_type.h"
  39 
  40 #include <assert.h>
  41 #include <alloca.h>
  42 #include <door.h>
  43 #include <errno.h>
  44 #include <fcntl.h>
  45 #include <fnmatch.h>
  46 #include <libuutil.h>
  47 #include <poll.h>
  48 #include <pthread.h>
  49 #include <synch.h>
  50 #include <stddef.h>
  51 #include <stdio.h>
  52 #include <stdlib.h>
  53 #include <string.h>
  54 #include <sys/mman.h>
  55 #include <sys/sysmacros.h>
  56 #include <libzonecfg.h>
  57 #include <unistd.h>
  58 #include <dlfcn.h>
  59 
  60 #define ENV_SCF_DEBUG           "LIBSCF_DEBUG"
  61 #define ENV_SCF_DOORPATH        "LIBSCF_DOORPATH"


4065         (void) pthread_mutex_lock(&h->rh_lock);
4066         if (tran->tran_state != TRAN_STATE_SETUP ||
4067             tran->tran_invalid) {
4068                 (void) pthread_mutex_unlock(&h->rh_lock);
4069                 return (scf_set_error(SCF_ERROR_INVALID_ARGUMENT));
4070         }
4071 
4072         total = 0;
4073         for (cur = uu_list_first(tran->tran_props); cur != NULL;
4074             cur = uu_list_next(tran->tran_props, cur)) {
4075                 size = commit_process(cur, NULL);
4076                 if (size == BAD_SIZE) {
4077                         (void) pthread_mutex_unlock(&h->rh_lock);
4078                         return (scf_set_error(SCF_ERROR_INTERNAL));
4079                 }
4080                 assert(TX_SIZE(size) == size);
4081                 total += size;
4082         }
4083 
4084         request_size = REP_PROTOCOL_TRANSACTION_COMMIT_SIZE(total);
4085         request = alloca(request_size);
4086         (void) memset(request, '\0', request_size);




4087         request->rpr_request = REP_PROTOCOL_PROPERTYGRP_TX_COMMIT;
4088         request->rpr_entityid = tran->tran_pg.rd_d.rd_entity;
4089         request->rpr_size = request_size;
4090         cmd = (uintptr_t)request->rpr_cmd;
4091 
4092         datael_finish_reset(&tran->tran_pg.rd_d);
4093 
4094         new_total = 0;
4095         for (cur = uu_list_first(tran->tran_props); cur != NULL;
4096             cur = uu_list_next(tran->tran_props, cur)) {
4097                 size = commit_process(cur, (void *)cmd);
4098                 if (size == BAD_SIZE) {
4099                         (void) pthread_mutex_unlock(&h->rh_lock);
4100                         return (scf_set_error(SCF_ERROR_INTERNAL));

4101                 }
4102                 cmd += size;
4103                 new_total += size;
4104         }
4105         assert(new_total == total);
4106 
4107         r = make_door_call(h, request, request_size,
4108             &response, sizeof (response));
4109 
4110         if (r < 0) {
4111                 (void) pthread_mutex_unlock(&h->rh_lock);
4112                 DOOR_ERRORS_BLOCK(r);
4113         }
4114 
4115         if (response.rpr_response != REP_PROTOCOL_SUCCESS &&
4116             response.rpr_response != REP_PROTOCOL_FAIL_NOT_LATEST) {
4117                 (void) pthread_mutex_unlock(&h->rh_lock);
4118                 return (scf_set_error(proto_error(response.rpr_response)));

4119         }
4120 
4121         tran->tran_state = TRAN_STATE_COMMITTED;
4122         (void) pthread_mutex_unlock(&h->rh_lock);
4123         return (response.rpr_response == REP_PROTOCOL_SUCCESS);




4124 }
4125 
4126 static void
4127 transaction_reset(scf_transaction_t *tran)
4128 {
4129         assert(MUTEX_HELD(&tran->tran_pg.rd_d.rd_handle->rh_lock));
4130 
4131         tran->tran_state = TRAN_STATE_NEW;
4132         datael_reset_locked(&tran->tran_pg.rd_d);
4133 }
4134 
4135 static void
4136 scf_transaction_reset_impl(scf_transaction_t *tran, int and_destroy,
4137     int and_reset_value)
4138 {
4139         scf_transaction_entry_t *cur;
4140         void *cookie;
4141 
4142         (void) pthread_mutex_lock(&tran->tran_pg.rd_d.rd_handle->rh_lock);
4143         cookie = NULL;




  21 
  22 /*
  23  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2013, Joyent, Inc. All rights reserved.
  25  * Copyright 2016 RackTop Systems.
  26  * Copyright (c) 2016 by Delphix. All rights reserved.
  27  * Copyright 2017 OmniOS Community Edition (OmniOSce) Association.
  28  */
  29 
  30 /*
  31  * This is the main implementation file for the low-level repository
  32  * interface.
  33  */
  34 
  35 #include "lowlevel_impl.h"
  36 
  37 #include "repcache_protocol.h"
  38 #include "scf_type.h"
  39 
  40 #include <assert.h>

  41 #include <door.h>
  42 #include <errno.h>
  43 #include <fcntl.h>
  44 #include <fnmatch.h>
  45 #include <libuutil.h>
  46 #include <poll.h>
  47 #include <pthread.h>
  48 #include <synch.h>
  49 #include <stddef.h>
  50 #include <stdio.h>
  51 #include <stdlib.h>
  52 #include <string.h>
  53 #include <sys/mman.h>
  54 #include <sys/sysmacros.h>
  55 #include <libzonecfg.h>
  56 #include <unistd.h>
  57 #include <dlfcn.h>
  58 
  59 #define ENV_SCF_DEBUG           "LIBSCF_DEBUG"
  60 #define ENV_SCF_DOORPATH        "LIBSCF_DOORPATH"


4064         (void) pthread_mutex_lock(&h->rh_lock);
4065         if (tran->tran_state != TRAN_STATE_SETUP ||
4066             tran->tran_invalid) {
4067                 (void) pthread_mutex_unlock(&h->rh_lock);
4068                 return (scf_set_error(SCF_ERROR_INVALID_ARGUMENT));
4069         }
4070 
4071         total = 0;
4072         for (cur = uu_list_first(tran->tran_props); cur != NULL;
4073             cur = uu_list_next(tran->tran_props, cur)) {
4074                 size = commit_process(cur, NULL);
4075                 if (size == BAD_SIZE) {
4076                         (void) pthread_mutex_unlock(&h->rh_lock);
4077                         return (scf_set_error(SCF_ERROR_INTERNAL));
4078                 }
4079                 assert(TX_SIZE(size) == size);
4080                 total += size;
4081         }
4082 
4083         request_size = REP_PROTOCOL_TRANSACTION_COMMIT_SIZE(total);
4084         request = calloc(1, request_size);
4085         if (request == NULL) {
4086                 (void) pthread_mutex_unlock(&h->rh_lock);
4087                 return (scf_set_error(SCF_ERROR_NO_MEMORY));
4088         }
4089 
4090         request->rpr_request = REP_PROTOCOL_PROPERTYGRP_TX_COMMIT;
4091         request->rpr_entityid = tran->tran_pg.rd_d.rd_entity;
4092         request->rpr_size = request_size;
4093         cmd = (uintptr_t)request->rpr_cmd;
4094 
4095         datael_finish_reset(&tran->tran_pg.rd_d);
4096 
4097         new_total = 0;
4098         for (cur = uu_list_first(tran->tran_props); cur != NULL;
4099             cur = uu_list_next(tran->tran_props, cur)) {
4100                 size = commit_process(cur, (void *)cmd);
4101                 if (size == BAD_SIZE) {
4102                         (void) pthread_mutex_unlock(&h->rh_lock);
4103                         r = (scf_set_error(SCF_ERROR_INTERNAL));
4104                         goto out;
4105                 }
4106                 cmd += size;
4107                 new_total += size;
4108         }
4109         assert(new_total == total);
4110 
4111         r = make_door_call(h, request, request_size,
4112             &response, sizeof (response));
4113 
4114         if (r < 0) {
4115                 (void) pthread_mutex_unlock(&h->rh_lock);
4116                 DOOR_ERRORS_BLOCK(r);
4117         }
4118 
4119         if (response.rpr_response != REP_PROTOCOL_SUCCESS &&
4120             response.rpr_response != REP_PROTOCOL_FAIL_NOT_LATEST) {
4121                 (void) pthread_mutex_unlock(&h->rh_lock);
4122                 r = (scf_set_error(proto_error(response.rpr_response)));
4123                 goto out;
4124         }
4125 
4126         tran->tran_state = TRAN_STATE_COMMITTED;
4127         (void) pthread_mutex_unlock(&h->rh_lock);
4128         r = (response.rpr_response == REP_PROTOCOL_SUCCESS);
4129 
4130 out:
4131         free(request);
4132         return (r);
4133 }
4134 
4135 static void
4136 transaction_reset(scf_transaction_t *tran)
4137 {
4138         assert(MUTEX_HELD(&tran->tran_pg.rd_d.rd_handle->rh_lock));
4139 
4140         tran->tran_state = TRAN_STATE_NEW;
4141         datael_reset_locked(&tran->tran_pg.rd_d);
4142 }
4143 
4144 static void
4145 scf_transaction_reset_impl(scf_transaction_t *tran, int and_destroy,
4146     int and_reset_value)
4147 {
4148         scf_transaction_entry_t *cur;
4149         void *cookie;
4150 
4151         (void) pthread_mutex_lock(&tran->tran_pg.rd_d.rd_handle->rh_lock);
4152         cookie = NULL;