suricata
util-luajit.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2016 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Victor Julien <victor@inliniac.net>
22  *
23  */
24 
25 #include "suricata-common.h"
26 
27 #ifdef HAVE_LUAJIT
28 #include "conf.h"
29 #include "util-pool.h"
30 #include "util-lua.h"
31 #include "util-luajit.h"
32 
33 /** \brief lua_State pool
34  *
35  * Lua requires states to be alloc'd in memory <2GB. For this reason we
36  * prealloc the states early during engine startup so we have a better chance
37  * of getting the states. We protect the pool with a lock as the detect
38  * threads access it during their init and cleanup.
39  *
40  * Pool size is automagically determined based on number of keyword occurences,
41  * cpus/cores and rule reloads being enabled or not.
42  *
43  * Alternatively, the "detect-engine.luajit-states" var can be set.
44  */
45 static Pool *luajit_states = NULL;
46 static pthread_mutex_t luajit_states_lock = SCMUTEX_INITIALIZER;
47 static int luajit_states_cnt = 0;
48 static int luajit_states_cnt_max = 0;
49 static int luajit_states_size = 0;
50 #define LUAJIT_DEFAULT_STATES 128
51 
52 static void *LuaStatePoolAlloc(void)
53 {
54  return luaL_newstate();
55 }
56 
57 static void LuaStatePoolFree(void *d)
58 {
59  lua_State *s = (lua_State *)d;
60  if (s != NULL)
61  lua_close(s);
62 }
63 
64 /** \brief Populate lua states pool
65  *
66  * \param num keyword instances
67  * \param reloads bool indicating we have rule reloads enabled
68  */
69 int LuajitSetupStatesPool(void)
70 {
71  int retval = 0;
72  pthread_mutex_lock(&luajit_states_lock);
73 
74  if (luajit_states == NULL) {
75  intmax_t cnt = 0;
76  if (ConfGetInt("luajit.states", &cnt) != 1) {
77  ConfNode *denode = NULL;
78  ConfNode *decnf = ConfGetNode("detect-engine");
79  if (decnf != NULL) {
80  TAILQ_FOREACH(denode, &decnf->head, next) {
81  if (denode->val && strcmp(denode->val, "luajit-states") == 0) {
82  ConfGetChildValueInt(denode, "luajit-states", &cnt);
83  }
84  }
85  }
86  }
87  if (cnt == 0) {
88  cnt = LUAJIT_DEFAULT_STATES;
89  }
90  luajit_states_size = cnt;
91 
92  luajit_states = PoolInit(0, cnt, 0, LuaStatePoolAlloc, NULL, NULL, NULL, LuaStatePoolFree);
93  if (luajit_states == NULL) {
94  SCLogError(SC_ERR_LUA_ERROR, "luastate pool init failed, lua/luajit keywords won't work");
95  retval = -1;
96  }
97 
98  if (retval == 0) {
99  SCLogConfig("luajit states preallocated: %d", luajit_states_size);
100  }
101  }
102 
103  pthread_mutex_unlock(&luajit_states_lock);
104  return retval;
105 }
106 
107 void LuajitFreeStatesPool(void)
108 {
109  pthread_mutex_lock(&luajit_states_lock);
110  if (luajit_states_cnt_max > luajit_states_size) {
111  SCLogNotice("luajit states used %d is bigger than pool size %d. Set "
112  "luajit.states to %d to avoid memory issues. "
113  "See #1577 and #1955.", luajit_states_cnt_max, luajit_states_size,
114  luajit_states_cnt_max);
115  }
116  PoolFree(luajit_states);
117  luajit_states = NULL;
118  luajit_states_size = 0;
119  luajit_states_cnt = 0;
120  pthread_mutex_unlock(&luajit_states_lock);
121 }
122 
123 lua_State *LuajitGetState(void)
124 {
125  lua_State *s = NULL;
126  pthread_mutex_lock(&luajit_states_lock);
127  if (luajit_states != NULL) {
128  s = (lua_State *)PoolGet(luajit_states);
129  if (s != NULL) {
130  if (luajit_states_cnt == luajit_states_size) {
131  SCLogWarning(SC_WARN_LUA_SCRIPT, "luajit states pool size %d "
132  "reached. Increase luajit.states config option. "
133  "See #1577 and #1955", luajit_states_size);
134  }
135 
136  luajit_states_cnt++;
137  if (luajit_states_cnt > luajit_states_cnt_max)
138  luajit_states_cnt_max = luajit_states_cnt;
139  }
140  }
141  pthread_mutex_unlock(&luajit_states_lock);
142  return s;
143 }
144 
145 void LuajitReturnState(lua_State *s)
146 {
147  if (s != NULL) {
148  pthread_mutex_lock(&luajit_states_lock);
149  PoolReturn(luajit_states, (void *)s);
150  BUG_ON(luajit_states_cnt <= 0);
151  luajit_states_cnt--;
152  pthread_mutex_unlock(&luajit_states_lock);
153  }
154 }
155 
156 #endif /* HAVE_LUAJIT */
lua_State
void lua_State
Definition: util-lua.h:31
ConfGetChildValueInt
int ConfGetChildValueInt(const ConfNode *base, const char *name, intmax_t *val)
Definition: conf.c:424
ConfGetInt
int ConfGetInt(const char *name, intmax_t *val)
Retrieve a configuration value as an integer.
Definition: conf.c:392
ConfNode_::val
char * val
Definition: conf.h:34
next
struct HtpBodyChunk_ * next
Definition: app-layer-htp.h:0
util-lua.h
ConfGetNode
ConfNode * ConfGetNode(const char *name)
Get a ConfNode by name.
Definition: conf.c:175
TAILQ_FOREACH
#define TAILQ_FOREACH(var, head, field)
Definition: queue.h:252
Pool_
Definition: util-pool.h:43
SCMUTEX_INITIALIZER
#define SCMUTEX_INITIALIZER
Definition: threads-debug.h:121
SC_WARN_LUA_SCRIPT
@ SC_WARN_LUA_SCRIPT
Definition: util-error.h:291
SC_ERR_LUA_ERROR
@ SC_ERR_LUA_ERROR
Definition: util-error.h:244
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:281
PoolFree
void PoolFree(Pool *p)
Definition: util-pool.c:220
conf.h
PoolReturn
void PoolReturn(Pool *p, void *data)
Definition: util-pool.c:333
suricata-common.h
SCLogError
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:255
SCLogConfig
struct SCLogConfig_ SCLogConfig
Holds the config state used by the logging api.
PoolGet
void * PoolGet(Pool *p)
Definition: util-pool.c:275
SCLogWarning
#define SCLogWarning(err_code,...)
Macro used to log WARNING messages.
Definition: util-debug.h:242
ConfNode_
Definition: conf.h:32
SCLogNotice
#define SCLogNotice(...)
Macro used to log NOTICE messages.
Definition: util-debug.h:230
util-luajit.h
util-pool.h
PoolInit
Pool * PoolInit(uint32_t size, uint32_t prealloc_size, uint32_t elt_size, void *(*Alloc)(void), int(*Init)(void *, void *), void *InitData, void(*Cleanup)(void *), void(*Free)(void *))
Init a Pool.
Definition: util-pool.c:84