Browse code

stats: detect of mod param items is set after track

- it can lead to crash if items is set to greater value than the default
one (GH #2101)
- round up for better memory alignment in the allocated structures

Daniel-Constantin Mierla authored on 14/01/2022 07:55:06
Showing 1 changed files
... ...
@@ -79,6 +79,22 @@ struct module_exports exports = {
79 79
 };
80 80
 
81 81
 
82
+typedef struct statsc_nmap {
83
+	str sname;
84
+	str rname;
85
+	int64_t *vals;
86
+	struct statsc_nmap *next;
87
+} statsc_nmap_t;
88
+
89
+typedef struct _statsc_info {
90
+	uint64_t steps;
91
+	uint32_t slots;
92
+	uint32_t items;
93
+	statsc_nmap_t *slist;
94
+} statsc_info_t;
95
+
96
+static statsc_info_t *_statsc_info = NULL;
97
+
82 98
 /**
83 99
  * @brief Initialize statsc module function
84 100
  */
... ...
@@ -92,9 +108,17 @@ static int mod_init(void)
92 108
 		LM_ERR("failed to register timer routine\n");
93 109
 		return -1;
94 110
 	}
95
-	if(statsc_init()<0) {
96
-		LM_ERR("failed to initialize the stats collector structure\n");
97
-		return -1;
111
+	if(_statsc_info==NULL) {
112
+		if(statsc_init()<0) {
113
+			LM_ERR("failed to initialize the stats collector structure\n");
114
+			return -1;
115
+		}
116
+	} else {
117
+		if(_statsc_info->items != (uint32_t)statsc_items) {
118
+			LM_ERR("number of items set after tracking statiscs were added\n");
119
+			LM_ERR("set mod param 'items' before 'track'\n");
120
+			return -1;
121
+		}
98 122
 	}
99 123
 	return 0;
100 124
 }
... ...
@@ -132,16 +156,6 @@ static int w_statsc_reset(sip_msg_t* msg, char* p1, char* p2)
132 156
 	return ki_statsc_reset(msg);
133 157
 }
134 158
 
135
-typedef int (*statsc_func_t)(void *p, int64_t *res);
136
-
137
-typedef struct statsc_nmap {
138
-	str sname;
139
-	str rname;
140
-	int64_t *vals;
141
-	struct statsc_nmap *next;
142
-} statsc_nmap_t;
143
-
144
-
145 159
 int statsc_svalue(str *name, int64_t *res)
146 160
 {
147 161
 	stat_var       *stat;
... ...
@@ -149,6 +163,7 @@ int statsc_svalue(str *name, int64_t *res)
149 163
 	stat = get_stat(name);
150 164
 	if(stat==NULL) {
151 165
 		LM_ERR("statistic %.*s not found\n", name->len, name->s);
166
+		*res = 0;
152 167
 		return -1;
153 168
 	}
154 169
 
... ...
@@ -158,20 +173,13 @@ int statsc_svalue(str *name, int64_t *res)
158 173
 }
159 174
 
160 175
 static statsc_nmap_t _statsc_nmap_default[] = {
161
-	{ str_init("shm.free"),        str_init("free_size"), 0, 0}, /* shmem:free_size */
162
-	{ str_init("shm.used"),        str_init("used_size"), 0, 0},
163
-	{ str_init("shm.real_used"),   str_init("real_used_size"), 0, 0},
164
-	{ {0, 0},                      {0, 0}, 0, 0}
176
+	{ str_init("shm.free"),      str_init("free_size"), NULL, NULL}, /* shmem:free_size */
177
+	{ str_init("shm.used"),      str_init("used_size"), NULL, NULL},
178
+	{ str_init("shm.real_used"), str_init("real_used_size"), NULL, NULL},
179
+	{ {NULL, 0},                 {NULL, 0}, NULL, NULL}
165 180
 };
166 181
 
167
-typedef struct _statsc_info {
168
-	uint64_t steps;
169
-	uint32_t slots;
170
-	statsc_nmap_t *slist;
171
-} statsc_info_t;
172
-
173
-
174
-static statsc_info_t *_statsc_info = NULL;
182
+#define STRLEN_ROUNDUP(len)  ( ( ((size_t)len) / sizeof(void*) + 1 ) * sizeof(void*) )
175 183
 
176 184
 int statsc_nmap_add(str *sname, str *rname)
177 185
 {
... ...
@@ -180,11 +188,17 @@ int statsc_nmap_add(str *sname, str *rname)
180 188
 	statsc_nmap_t *sl = NULL;
181 189
 
182 190
 	if(_statsc_info==NULL) {
191
+		LM_ERR("root structure not initialize yet\n");
192
+		return -1;
193
+	}
194
+	if(_statsc_info->items != (uint32_t)statsc_items) {
195
+		LM_ERR("number of items set after tracking statiscs were added\n");
196
+		LM_ERR("set mod param 'items' before 'track'\n");
183 197
 		return -1;
184 198
 	}
185 199
 
186 200
 	sz = sizeof(statsc_nmap_t) + statsc_items * sizeof(int64_t)
187
-		+ sname->len + rname->len + 4;
201
+		+ STRLEN_ROUNDUP(sname->len) + STRLEN_ROUNDUP(rname->len);
188 202
 	sm = shm_malloc(sz);
189 203
 	if(sm==NULL) {
190 204
 		LM_ERR("no more shared memory\n");
... ...
@@ -193,15 +207,18 @@ int statsc_nmap_add(str *sname, str *rname)
193 207
 	memset(sm, 0, sz);
194 208
 	sm->sname.s = (char*)((char*)sm + sizeof(statsc_nmap_t));
195 209
 	sm->sname.len = sname->len;
196
-	sm->rname.s = (char*)((char*)sm->sname.s + sm->sname.len + 1);
210
+	sm->rname.s = (char*)((char*)sm->sname.s + STRLEN_ROUNDUP(sm->sname.len));
197 211
 	sm->rname.len = rname->len;
198
-	sm->vals = (int64_t*)((char*)sm->rname.s + sm->rname.len + 1);
212
+	sm->vals = (int64_t*)((char*)sm->rname.s + STRLEN_ROUNDUP(sm->rname.len));
199 213
 	memcpy(sm->sname.s, sname->s, sname->len);
200 214
 	memcpy(sm->rname.s, rname->s, rname->len);
201 215
 
216
+	LM_INFO("added stat mapping [%.*s] [%.*s]\n", sname->len, sname->s,
217
+			 rname->len,  rname->s);
202 218
 	if(_statsc_info->slist==NULL) {
203 219
 		_statsc_info->slist = sm;
204 220
 		_statsc_info->slots = 1;
221
+		_statsc_info->items = (uint32_t)statsc_items;
205 222
 		return 0;
206 223
 	}
207 224
 	sl = _statsc_info->slist;
... ...
@@ -239,6 +256,7 @@ int statsc_init(void)
239 256
 	sm->vals = (int64_t*)((char*)sm + sizeof(statsc_nmap_t));
240 257
 	_statsc_info->slist = sm;
241 258
 	_statsc_info->slots = 1;
259
+	_statsc_info->items = (uint32_t)statsc_items;
242 260
 
243 261
 	for(i=0; _statsc_nmap_default[i].sname.s!=0; i++) {
244 262
 		if(statsc_nmap_add(&_statsc_nmap_default[i].sname,
... ...
@@ -273,7 +291,7 @@ void statsc_timer(unsigned int ticks, void *param)
273 291
 
274 292
 	i = 0;
275 293
 	for(sm=_statsc_info->slist->next; sm!=NULL; sm=sm->next) {
276
-		LM_DBG("fetching value for: [%.*s] - step [%d]\n", sm->rname.len,
294
+		LM_DBG("fetching value for: [%.*s] - index [%d]\n", sm->rname.len,
277 295
 				sm->rname.s, i);
278 296
 		statsc_svalue(&sm->rname, sm->vals + n);
279 297
 		i++;