1 /**************************************************************************
3 xserver-xorg-video-exynos
5 Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved.
7 Contact: Boram Park <boram1288.park@samsung.com>
9 Permission is hereby granted, free of charge, to any person obtaining a
10 copy of this software and associated documentation files (the
11 "Software"), to deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify, merge, publish,
13 distribute, sub license, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to
15 the following conditions:
17 The above copyright notice and this permission notice (including the
18 next paragraph) shall be included in all copies or substantial portions
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
24 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
25 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
26 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 **************************************************************************/
36 #include "bool_exp_parser.h"
37 #include "bool_exp_rule_checker.h"
42 #define REPLY(fmt, ARG...) \
44 if (reply && len && *len > 0) \
46 int s = snprintf (reply, *len, fmt, ##ARG); \
54 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
86 static int print_func (BINARY_TREE tree, BINARY_TREE_NODE node, BINARY_TREE_NODE parent, void * arg)
88 REPLY_BUFFER *buffer = (REPLY_BUFFER*)arg;
89 char *reply = *buffer->reply;
90 int *len = buffer->len;
91 char * operators[] = { "==", "<", ">", "<=", ">=", "!=" };
93 PARSE_DATA data = bintree_get_node_data (node);
95 if (data->node_type == ALL)
97 else if (data->node_type == AND)
99 else if (data->node_type == OR)
101 else // data->node_type == DATA
103 if (node == bintree_get_left_child (parent))
106 REPLY ("%s %s ", data->variable_name, operators[data->compare]);
108 if (data->value_type == INTEGER)
109 REPLY ("%d", data->value.integer);
111 REPLY ("%s", data->value.string);
113 if (node == bintree_get_right_child (parent))
117 *buffer->reply = reply;
122 static int compare_string (COMPARER compare, char * str2, char * str1)
124 int result = strcasecmp (str2, str1);
144 static int compare_int (COMPARER compare, int int2, int int1)
165 static int validate_func (BINARY_TREE tree, BINARY_TREE_NODE node, BINARY_TREE_NODE parent, void * arg)
167 VAL_ARGUMENTS * args = (VAL_ARGUMENTS*)arg;
168 BINARY_TREE_NODE left, right;
170 PARSE_DATA left_data = NULL, right_data = NULL;
171 PARSE_DATA data = bintree_get_node_data (node);
173 data->result = BEP_UNKNOWN;
175 if (data->node_type == AND || data->node_type == OR)
177 left = bintree_get_left_child (node);
178 right = bintree_get_right_child (node);
179 if (left == NULL || right == NULL)
181 printf ("Node error\n");
185 left_data = bintree_get_node_data (left);
186 right_data = bintree_get_node_data (right);
189 if (data->node_type == ALL)
191 data->result = BEP_TRUE;
193 else if (data->node_type == DATA)
199 minor = index (args->name, ':');
202 int min = MIN (sizeof(major)-1, minor-args->name);
203 strncpy (major, args->name, min);
207 if (!strcasecmp (data->variable_name, "TYPE"))
210 if (args->type == 0) // EVENT
211 type_string = "EVENT";
212 else if (args->type == 1)
213 type_string = "REQUEST";
214 else if (args->type == 2)
215 type_string = "REPLY";
216 else if (args->type == 3)
217 type_string = "FLUSH";
218 else if (args->type == 4)
219 type_string = "ERROR";
222 fprintf (stderr, "Invalid type %d\n", args->type);
226 if (compare_string (data->compare, data->value.string, type_string))
227 data->result = BEP_TRUE;
229 data->result = BEP_FALSE;
231 else if (!strcasecmp (data->variable_name, "MAJOR"))
233 if (minor && compare_string (data->compare, data->value.string, major))
234 data->result = BEP_TRUE;
236 data->result = BEP_FALSE;
238 else if (!strcasecmp (data->variable_name, "MINOR"))
240 if (minor && compare_string (data->compare, data->value.string, minor))
241 data->result = BEP_TRUE;
243 data->result = BEP_FALSE;
245 else if (!strcasecmp (data->variable_name, "PID"))
247 if (compare_int (data->compare, data->value.integer, args->pid))
248 data->result = BEP_TRUE;
250 data->result = BEP_FALSE;
252 else if (!strcasecmp (data->variable_name, "CMD") || !strcasecmp (data->variable_name, "COMMAND"))
254 if (args->cmd && compare_string (data->compare, data->value.string, args->cmd))
255 data->result = BEP_TRUE;
257 data->result = BEP_FALSE;
260 else if (data->node_type == AND)
262 if (left_data->result == BEP_TRUE && right_data->result == BEP_TRUE)
263 data->result = BEP_TRUE;
265 data->result = BEP_FALSE;
267 else if (data->node_type == OR)
269 if (left_data->result == BEP_TRUE || right_data->result == BEP_TRUE)
270 data->result = BEP_TRUE;
272 data->result = BEP_FALSE;
281 RULE_CHECKER rulechecker_init()
283 RULE_CHECKER rc = calloc (sizeof (struct _RULE_CHECKER), 1);
292 void rulechecker_destroy (RULE_CHECKER rc)
295 for (i=rc->count - 1; i>=0; i--)
296 rulechecker_remove_rule (rc, i);
301 RC_RESULT_TYPE rulechecker_add_rule (RULE_CHECKER rc, POLICY_TYPE policy, const char * rule_string)
303 if (rc->count == MAX_RULE)
304 return RC_ERR_TOO_MANY_RULES;
306 rc->rules[rc->count].tree = bool_exp_parse (rule_string);
307 if (rc->rules[rc->count].tree == NULL)
308 return RC_ERR_PARSE_ERROR;
309 rc->rules[rc->count].policy = policy;
316 RC_RESULT_TYPE rulechecker_remove_rule (RULE_CHECKER rc, int index)
318 if (index < 0 || index >= rc->count)
319 return RC_ERR_NO_RULE;
321 bintree_destroy_tree (rc->rules[index].tree);
324 if (index != rc->count)
325 memmove (&rc->rules[index], &rc->rules[index + 1], sizeof (RULE) * (rc->count - index));
330 void rulechecker_print_rule (RULE_CHECKER rc, char *reply, int *len)
332 REPLY_BUFFER buffer = {&reply, len};
335 REPLY (" ---------------- Evlog Rules ----------------\n");
337 for (i=0; i<rc->count; i++)
339 REPLY (" [Rule %d] [%s] \"", i, rc->rules[i].policy == ALLOW ? "ALLOW" : "DENY");
341 bintree_inorder_traverse (rc->rules[i].tree, print_func, (void*)&buffer);
346 const char * rulechecker_print_usage()
349 "######################################################################\n"
350 "### RuleChecker 1.0 for XDBG EvLog filtering. ###\n"
351 "### Designed and developed by ###\n"
352 "### YoungHoon Jung <yhoon.jung@samsung.com> ###\n"
353 "######################################################################\n"
355 "-----------------------------------------------------------------\n"
356 "How to read evlog messages :\n"
357 " Client(pid: [PID]| [CMD]) <====== [TYPE]( [MAJOR]: [MINOR]) ===== XServer\n"
360 " Client(pid:00345| xdbg) <====== Event ( X11:SendEvent) ===== XServer\n"
361 " ==> type = event && pid = 345 && cmd = xdbg && major = X11 && minor = SendEvent\n"
362 " Client(pid:00111| xeyes) ===== Request( SHM:ShmAttach) ======> XServer\n"
363 " ==> type = request && pid = 111 && cmd = xeyes && major = SHM && minor = ShmAttach\n"
365 "-----------------------------------------------------------------\n"
366 "Usage : xdbg evlog_rule add [POLICY] [RULE]\n"
367 " xdbg evlog_rule remove [INDEX]\n"
368 " xdbg evlog_rule file [RULE_FILE]\n"
369 " xdbg evlog_rule help / print\n"
370 " [POLICY] : allow / deny \n"
371 " [RULE] : C Language-style boolean expression syntax. [VARIABLE] [COMPAROTOR] [VALUE]\n"
372 " [VARIABLE] : type / major / minor / command / cmd / pid\n"
373 " [COMPARATOR] : & / && / and / | / || / or / = / == / != / > / >= / < / <=\n"
374 " [VALUE] : string / number \n"
377 " xdbg evlog_rule add allow \"(type=request) && (major == X11 and (minor = SendEvent or minor = ReceiveEvent))\"\n"
378 " xdbg evlog_rule add deny cmd!=ls\n"
379 " xdbg evlog_rule remove 1\n"
383 int rulechecker_validate_rule (RULE_CHECKER rc, int type, int reqID, const char * name, int pid, char * cmd)
385 VAL_ARGUMENTS args = { type, reqID, name, pid, cmd };
386 BINARY_TREE_NODE node;
389 // set default value here
390 POLICY_TYPE default_policy = DENY;
392 for (i=rc->count - 1; i >= 0; i--)
394 bintree_postorder_traverse (rc->rules[i].tree, validate_func, &args);
395 node = bintree_get_head (rc->rules[i].tree);
396 data = bintree_get_node_data (node);
398 if (data->result == BEP_TRUE)
400 return rc->rules[i].policy == ALLOW;
404 return default_policy == ALLOW;