Skip to content

Commit 6833841

Browse files
committed
Add check for basic naming style violations
Refpolicy findings: networkmanager.te: 8: (C): Naming convention voliated: contains invalid character (C-006) networkmanager.te: 9: (C): Naming convention voliated: contains invalid character (C-006) networkmanager.te: 12: (C): Naming convention voliated: contains invalid character (C-006) networkmanager.te: 15: (C): Naming convention voliated: contains invalid character (C-006) networkmanager.te: 18: (C): Naming convention voliated: contains invalid character (C-006) networkmanager.te: 21: (C): Naming convention voliated: contains invalid character (C-006) networkmanager.te: 24: (C): Naming convention voliated: contains invalid character (C-006) networkmanager.te: 27: (C): Naming convention voliated: contains invalid character (C-006) networkmanager.te: 30: (C): Naming convention voliated: contains invalid character (C-006) networkmanager.te: 33: (C): Naming convention voliated: contains invalid character (C-006) slocate.if: 13: (C): Naming convention voliated: interface has no module name prefix (C-006) openoffice.if: 18: (C): Naming convention voliated: interface has no module name prefix (C-006) openoffice.if: 48: (C): Naming convention voliated: interface has no module name prefix (C-006) openoffice.if: 67: (C): Naming convention voliated: interface has no module name prefix (C-006) openoffice.if: 86: (C): Naming convention voliated: interface has no module name prefix (C-006) openoffice.if: 106: (C): Naming convention voliated: interface has no module name prefix (C-006) openoffice.if: 127: (C): Naming convention voliated: interface has no module name prefix (C-006) qemu.if: 113: (C): Naming convention voliated: template has an invalid postfix (C-006) webalizer.if: 60: (C): Naming convention voliated: interface has no module name prefix (C-006) udev.if: 461: (C): Naming convention voliated: interface has no module name prefix (C-006) udev.if: 486: (C): Naming convention voliated: interface has no module name prefix (C-006) udev.if: 505: (C): Naming convention voliated: interface has no module name prefix (C-006) daemontools.if: 91: (C): Naming convention voliated: interface has no module name prefix (C-006) systemd.if: 147: (C): Naming convention voliated: contains invalid character (C-006) iscsi.if: 13: (C): Naming convention voliated: interface has no module name prefix (C-006) kismet.if: 18: (C): Naming convention voliated: template has an invalid postfix (C-006) lsm.if: 20: (C): Naming convention voliated: interface has no module name prefix (C-006) mailscanner.if: 14: (C): Naming convention voliated: interface has no module name prefix (C-006) mailscanner.if: 41: (C): Naming convention voliated: interface has no module name prefix (C-006) dhcp.if: 13: (C): Naming convention voliated: interface has no module name prefix (C-006) dhcp.if: 33: (C): Naming convention voliated: interface has no module name prefix (C-006) dhcp.if: 53: (C): Naming convention voliated: interface has no module name prefix (C-006) dhcp.if: 78: (C): Naming convention voliated: interface has no module name prefix (C-006) rlogin.if: 32: (C): Naming convention voliated: template has an invalid postfix (C-006) qpid.if: 13: (C): Naming convention voliated: interface has no module name prefix (C-006) qpid.if: 32: (C): Naming convention voliated: interface has no module name prefix (C-006) qpid.if: 50: (C): Naming convention voliated: interface has no module name prefix (C-006) qpid.if: 69: (C): Naming convention voliated: interface has no module name prefix (C-006) qpid.if: 87: (C): Naming convention voliated: interface has no module name prefix (C-006) qpid.if: 106: (C): Naming convention voliated: interface has no module name prefix (C-006) qpid.if: 125: (C): Naming convention voliated: interface has no module name prefix (C-006) qpid.if: 145: (C): Naming convention voliated: interface has no module name prefix (C-006) qpid.if: 171: (C): Naming convention voliated: interface has no module name prefix (C-006) ctdb.if: 14: (C): Naming convention voliated: interface has no module name prefix (C-006) ctdb.if: 34: (C): Naming convention voliated: interface has no module name prefix (C-006) aisexec.if: 79: (C): Naming convention voliated: interface has no module name prefix (C-006) isns.if: 20: (C): Naming convention voliated: interface has no module name prefix (C-006) l2tp.if: 14: (C): Naming convention voliated: interface has no module name prefix (C-006) l2tp.if: 34: (C): Naming convention voliated: interface has no module name prefix (C-006) l2tp.if: 53: (C): Naming convention voliated: interface has no module name prefix (C-006) polipo.if: 18: (C): Naming convention voliated: template has an invalid postfix (C-006) systemtap.if: 20: (C): Naming convention voliated: interface has no module name prefix (C-006) git.if: 18: (C): Naming convention voliated: template has an invalid postfix (C-006) cobbler.if: 13: (C): Naming convention voliated: interface has no module name prefix (C-006) cobbler.if: 33: (C): Naming convention voliated: interface has no module name prefix (C-006) example.if: 29: (C): Naming convention voliated: interface has no module name prefix (C-006) example.if: 47: (C): Naming convention voliated: interface has no module name prefix (C-006) Found the following issue counts: C-006: 57
1 parent 146c1f1 commit 6833841

File tree

12 files changed

+374
-2
lines changed

12 files changed

+374
-2
lines changed

README

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ CHECK IDS
137137
C-001: Violation of refpolicy te file ordering conventions
138138
C-004: Interface does not have documentation comment
139139
C-005: Permissions in av rule or class declaration not ordered
140+
C-006: Violation of refpolicy style naming conventions
140141

141142
S-001: Require block used instead of interface call
142143
S-002: File context file labels with type not declared in module

src/Makefile.am

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
# limitations under the License.
1414

1515
bin_PROGRAMS = selint
16-
selint_SOURCES = main.c lex.l parse.y tree.c tree.h selint_error.h parse_functions.c parse_functions.h maps.c maps.h runner.c runner.h parse_fc.c parse_fc.h template.c template.h file_list.c file_list.h check_hooks.c check_hooks.h fc_checks.c fc_checks.h util.c util.h if_checks.c if_checks.h selint_config.c selint_config.h string_list.c string_list.h startup.c startup.h te_checks.c te_checks.h ordering.c ordering.h color.c color.h
16+
selint_SOURCES = main.c lex.l parse.y tree.c tree.h selint_error.h parse_functions.c parse_functions.h maps.c maps.h runner.c runner.h parse_fc.c parse_fc.h template.c template.h file_list.c file_list.h check_hooks.c check_hooks.h fc_checks.c fc_checks.h util.c util.h if_checks.c if_checks.h selint_config.c selint_config.h string_list.c string_list.h startup.c startup.h te_checks.c te_checks.h ordering.c ordering.h color.c color.h naming.c naming.h
1717
BUILT_SOURCES = parse.h
1818
AM_YFLAGS = -d -Wno-yacc -Werror=conflicts-rr -Werror=conflicts-sr
1919

src/check_hooks.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ enum convention_ids {
2525
C_ID_TE_ORDER = 1,
2626
C_ID_IF_COMMENT = 4,
2727
C_ID_UNORDERED_PERM = 5,
28+
C_ID_NAMING = 6,
2829
C_END
2930
};
3031

src/naming.c

Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
/*
2+
* Copyright 2020 The SELint Contributors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "naming.h"
18+
19+
#include <ctype.h>
20+
#include <stddef.h>
21+
#include <string.h>
22+
23+
static const char *const reason_invalid_char = "contains invalid character";
24+
static const char *const reason_start_underscore = "starts with an underscore";
25+
static const char *const reason_consecutive_underscores = "contains consecutive underscores";
26+
static const char *const reason_end_underscore = "ends with an underscore";
27+
static const char *const reason_type_postfix = "type does not end with type-specific postfix";
28+
static const char *const reason_role_postfix = "role does not end with role-specific postfix";
29+
static const char *const reason_user_postfix = "user does not end with user-specific postfix";
30+
static const char *const reason_if_no_mod_prefix = "interface has no module name prefix";
31+
static const char *const reason_if_no_postfix = "interface has no postfix";
32+
static const char *const reason_if_invalid_postfix = "interface has an invalid postfix";
33+
static const char *const reason_temp_no_mod_prefix = "template has no module name prefix";
34+
static const char *const reason_temp_no_postfix = "template has no postfix";
35+
static const char *const reason_temp_invalid_postfix = "template has an invalid postfix";
36+
37+
38+
static const char *generic_check(const char *name)
39+
{
40+
const unsigned char *c = (const unsigned char *)name;
41+
42+
if (*c == '_') {
43+
return reason_start_underscore;
44+
}
45+
46+
unsigned short prev_is_underscore = 0;
47+
while (*c != '\0') {
48+
if (!islower(*c) && !isdigit(*c) && *c != '_') {
49+
return reason_invalid_char;
50+
}
51+
52+
if (*c == '_') {
53+
if (prev_is_underscore) {
54+
return reason_consecutive_underscores;
55+
}
56+
57+
prev_is_underscore = 1;
58+
} else {
59+
prev_is_underscore = 0;
60+
}
61+
62+
c++;
63+
}
64+
65+
if (*(c-1) == '_') {
66+
return reason_end_underscore;
67+
}
68+
69+
return NULL;
70+
}
71+
72+
static const char *type_check(const char *name)
73+
{
74+
const size_t name_len = strlen(name);
75+
if (name_len < 2 || name[name_len-2] != '_' || name[name_len-1] != 't') {
76+
return reason_type_postfix;
77+
}
78+
79+
return NULL;
80+
}
81+
82+
static const char *role_check(const char *name)
83+
{
84+
const size_t name_len = strlen(name);
85+
if (name_len < 2 || name[name_len-2] != '_' || name[name_len-1] != 'r') {
86+
return reason_role_postfix;
87+
}
88+
89+
return NULL;
90+
}
91+
92+
static const char *user_check(const char *name)
93+
{
94+
const size_t name_len = strlen(name);
95+
if (name_len < 2 || name[name_len-2] != '_' || name[name_len-1] != 'u') {
96+
return reason_user_postfix;
97+
}
98+
99+
return NULL;
100+
}
101+
102+
const char *naming_decl_check(const char *name, enum decl_flavor flavor)
103+
{
104+
// class and permission names are not in the scope of a policy writer
105+
if (flavor == DECL_CLASS || flavor == DECL_PERM) {
106+
return NULL;
107+
}
108+
109+
const char *res = generic_check(name);
110+
if (res) {
111+
return res;
112+
}
113+
114+
switch (flavor) {
115+
case DECL_TYPE:
116+
res = type_check(name);
117+
break;
118+
case DECL_ATTRIBUTE:
119+
//TODO
120+
break;
121+
case DECL_ROLE:
122+
res = role_check(name);
123+
break;
124+
case DECL_ATTRIBUTE_ROLE:
125+
//TODO
126+
break;
127+
case DECL_USER:
128+
res = user_check(name);
129+
break;
130+
case DECL_BOOL:
131+
//TODO
132+
break;
133+
case DECL_CLASS:
134+
case DECL_PERM:
135+
break;
136+
}
137+
138+
if (res) {
139+
return res;
140+
}
141+
142+
return NULL;
143+
}
144+
145+
static int mod_prefix_check(const char *name, const char *mod_name)
146+
{
147+
const size_t mod_name_len = strlen(mod_name);
148+
149+
if (0 == strncmp(name, mod_name, mod_name_len) && name[mod_name_len] == '_') {
150+
return 0;
151+
}
152+
153+
static const char *const exceptions[][2] = {
154+
{ "fs" , "filesystem" },
155+
{ "corecmd" , "corecommands" },
156+
{ "seutil" , "selinuxutil" },
157+
{ "libs" , "libraries" },
158+
{ "dev" , "devices" },
159+
{ "term" , "terminal" },
160+
{ "corenet" , "corenetwork" },
161+
{ "auth" , "authlogin" },
162+
{ "userdom" , "userdomain" },
163+
{ "sysnet" , "sysnetwork" },
164+
};
165+
166+
const char *prefix = strchr(name, '_');
167+
if (!prefix) {
168+
return 1;
169+
}
170+
171+
const size_t prefix_len = prefix - name;
172+
173+
size_t i;
174+
for (i = 0; i < (sizeof exceptions / sizeof *exceptions); ++i) {
175+
if (0 == strncmp(name, exceptions[i][0], prefix_len) &&
176+
0 == strcmp(mod_name, exceptions[i][1])) {
177+
return 0;
178+
}
179+
}
180+
181+
return 1;
182+
}
183+
184+
const char *naming_if_check(const char *name, const char *module_name)
185+
{
186+
const char *res = generic_check(name);
187+
if (res) {
188+
return res;
189+
}
190+
191+
if (mod_prefix_check(name, module_name)) {
192+
return reason_if_no_mod_prefix;
193+
}
194+
195+
const char *postfix = strrchr(name, '_');
196+
if (!postfix) {
197+
return reason_if_no_postfix;
198+
}
199+
200+
static const char *const invalid_postfixes[] = {
201+
"_pattern",
202+
};
203+
size_t i;
204+
for (i = 0; i < (sizeof invalid_postfixes / sizeof *invalid_postfixes); ++i) {
205+
if (0 == strcmp(postfix, invalid_postfixes[i])) {
206+
return reason_if_invalid_postfix;
207+
}
208+
}
209+
210+
return NULL;
211+
}
212+
213+
const char *naming_temp_check(const char *name, const char *module_name)
214+
{
215+
const char *res = generic_check(name);
216+
if (res) {
217+
return res;
218+
}
219+
220+
if (mod_prefix_check(name, module_name)) {
221+
return reason_temp_no_mod_prefix;
222+
}
223+
224+
const char *postfix = strrchr(name, '_');
225+
if (!postfix) {
226+
return reason_temp_no_postfix;
227+
}
228+
229+
if (0 != strcmp(postfix, "_template") &&
230+
0 != strcmp(postfix, "_admin")) {
231+
return reason_temp_invalid_postfix;
232+
}
233+
234+
return NULL;
235+
}

src/naming.h

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Copyright 2020 The SELint Contributors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#ifndef NAMING_H
18+
#define NAMING_H
19+
20+
#include "tree.h"
21+
22+
/**********************************
23+
* Check the given name with the given kind of declaration for naming
24+
* convention violations.
25+
* name (in) - the name of the declaration
26+
* flavor (in) - the kind of declaration
27+
* Returns NULL if check passes, else a violation reason.
28+
**********************************/
29+
const char *naming_decl_check(const char *name, enum decl_flavor flavor);
30+
31+
/**********************************
32+
* Check the given interface name for naming
33+
* convention violations.
34+
* name (in) - the name of the interface
35+
* module_name (in) - the name of the containing module
36+
* Returns NULL if check passes, else a violation reason.
37+
**********************************/
38+
const char *naming_if_check(const char *name, const char *module_name);
39+
40+
/**********************************
41+
* Check the given template name for naming
42+
* convention violations.
43+
* name (in) - the name of the template
44+
* module_name (in) - the name of the containing module
45+
* Returns NULL if check passes, else a violation reason.
46+
**********************************/
47+
const char *naming_temp_check(const char *name, const char *module_name);
48+
49+
#endif

src/runner.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,14 @@ struct checks *register_checks(char level,
141141
add_check(NODE_DECL, ck, "C-005",
142142
check_unordered_perms);
143143
}
144+
if (CHECK_ENABLED("C-006")) {
145+
add_check(NODE_DECL, ck, "C-006",
146+
check_naming);
147+
add_check(NODE_TEMP_DEF, ck, "C-006",
148+
check_naming);
149+
add_check(NODE_INTERFACE_DEF, ck, "C-006",
150+
check_naming);
151+
}
144152
// FALLTHRU
145153
case 'S':
146154
if (CHECK_ENABLED("S-001")) {

src/te_checks.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "maps.h"
1919
#include "tree.h"
2020
#include "ordering.h"
21+
#include "naming.h"
2122

2223
struct check_result *check_te_order(const struct check_data *data,
2324
const struct policy_node *node)
@@ -114,6 +115,42 @@ struct check_result *check_unordered_perms(__attribute__((unused)) const struct
114115

115116
}
116117

118+
struct check_result *check_naming(const struct check_data *data,
119+
const struct policy_node *node)
120+
{
121+
const char *reason;
122+
123+
switch (node->flavor) {
124+
case NODE_DECL:
125+
// check only declarations in te files
126+
if (data->flavor != FILE_TE_FILE) {
127+
return NULL;
128+
}
129+
130+
reason = naming_decl_check(node->data.d_data->name, node->data.d_data->flavor);
131+
break;
132+
133+
case NODE_INTERFACE_DEF:
134+
reason = naming_if_check(node->data.str, data->mod_name);
135+
break;
136+
137+
case NODE_TEMP_DEF:
138+
reason = naming_temp_check(node->data.str, data->mod_name);
139+
break;
140+
141+
default:
142+
return alloc_internal_error("Invalid node type for `check_naming`");
143+
}
144+
145+
if (!reason) {
146+
return NULL;
147+
}
148+
149+
return make_check_result('C', C_ID_NAMING,
150+
"Naming convention voliated: %s",
151+
reason);
152+
}
153+
117154
struct check_result *check_require_block(const struct check_data *data,
118155
const struct policy_node *node)
119156
{

src/te_checks.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,16 @@ struct check_result *check_te_order(const struct check_data *data,
4545
struct check_result *check_unordered_perms(const struct check_data *data,
4646
const struct policy_node *node);
4747

48+
/*********************************************
49+
* Check for violations of refpolicy style naming conventions.
50+
* Called on NODE_DECL nodes.
51+
* data - metadata about the file currently being scanned
52+
* node - the node to check
53+
* returns NULL if passed or check_result for issue C-005
54+
*********************************************/
55+
struct check_result *check_naming(const struct check_data *data,
56+
const struct policy_node *node);
57+
4858
/*********************************************
4959
* Check for the presence of require blocks in TE files.
5060
* Interface calls are to be prefered.

0 commit comments

Comments
 (0)