diff options
Diffstat (limited to 'security/tomoyo/common.c')
-rw-r--r-- | security/tomoyo/common.c | 259 |
1 files changed, 200 insertions, 59 deletions
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index cb1aaf148ad4..044115d49033 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c | |||
@@ -1192,75 +1192,216 @@ static int tomoyo_write_exception_policy(struct tomoyo_io_buffer *head) | |||
1192 | return -EINVAL; | 1192 | return -EINVAL; |
1193 | } | 1193 | } |
1194 | 1194 | ||
1195 | static void tomoyo_print_number(char *buffer, int buffer_len, | ||
1196 | const struct tomoyo_number_union *ptr) | ||
1197 | { | ||
1198 | int i; | ||
1199 | unsigned long min = ptr->values[0]; | ||
1200 | const unsigned long max = ptr->values[1]; | ||
1201 | u8 min_type = ptr->min_type; | ||
1202 | const u8 max_type = ptr->max_type; | ||
1203 | memset(buffer, 0, buffer_len); | ||
1204 | buffer_len -= 2; | ||
1205 | for (i = 0; i < 2; i++) { | ||
1206 | int len; | ||
1207 | switch (min_type) { | ||
1208 | case TOMOYO_VALUE_TYPE_HEXADECIMAL: | ||
1209 | snprintf(buffer, buffer_len, "0x%lX", min); | ||
1210 | break; | ||
1211 | case TOMOYO_VALUE_TYPE_OCTAL: | ||
1212 | snprintf(buffer, buffer_len, "0%lo", min); | ||
1213 | break; | ||
1214 | default: | ||
1215 | snprintf(buffer, buffer_len, "%lu", min); | ||
1216 | break; | ||
1217 | } | ||
1218 | if (min == max && min_type == max_type) | ||
1219 | break; | ||
1220 | len = strlen(buffer); | ||
1221 | buffer[len++] = '-'; | ||
1222 | buffer += len; | ||
1223 | buffer_len -= len; | ||
1224 | min_type = max_type; | ||
1225 | min = max; | ||
1226 | } | ||
1227 | } | ||
1228 | |||
1229 | static const char *tomoyo_group_name[TOMOYO_MAX_GROUP] = { | ||
1230 | [TOMOYO_PATH_GROUP] = TOMOYO_KEYWORD_PATH_GROUP, | ||
1231 | [TOMOYO_NUMBER_GROUP] = TOMOYO_KEYWORD_NUMBER_GROUP | ||
1232 | }; | ||
1233 | |||
1195 | /** | 1234 | /** |
1196 | * tomoyo_read_exception_policy - Read exception policy. | 1235 | * tomoyo_read_group - Read "struct tomoyo_path_group"/"struct tomoyo_number_group" list. |
1197 | * | 1236 | * |
1198 | * @head: Pointer to "struct tomoyo_io_buffer". | 1237 | * @head: Pointer to "struct tomoyo_io_buffer". |
1238 | * @idx: Index number. | ||
1239 | * | ||
1240 | * Returns true on success, false otherwise. | ||
1199 | * | 1241 | * |
1200 | * Caller holds tomoyo_read_lock(). | 1242 | * Caller holds tomoyo_read_lock(). |
1201 | */ | 1243 | */ |
1202 | static void tomoyo_read_exception_policy(struct tomoyo_io_buffer *head) | 1244 | static bool tomoyo_read_group(struct tomoyo_io_buffer *head, const int idx) |
1203 | { | 1245 | { |
1204 | if (!head->read_eof) { | 1246 | struct list_head *gpos; |
1205 | switch (head->read_step) { | 1247 | struct list_head *mpos; |
1206 | case 0: | 1248 | const char *w[3] = { "", "", "" }; |
1207 | head->read_var2 = NULL; | 1249 | w[0] = tomoyo_group_name[idx]; |
1208 | head->read_step = 1; | 1250 | list_for_each_cookie(gpos, head->read_var1, &tomoyo_group_list[idx]) { |
1209 | case 1: | 1251 | struct tomoyo_group *group = |
1210 | if (!tomoyo_read_domain_keeper_policy(head)) | 1252 | list_entry(gpos, struct tomoyo_group, list); |
1211 | break; | 1253 | w[1] = group->group_name->name; |
1212 | head->read_var2 = NULL; | 1254 | list_for_each_cookie(mpos, head->read_var2, |
1213 | head->read_step = 2; | 1255 | &group->member_list) { |
1214 | case 2: | 1256 | char buffer[128]; |
1215 | if (!tomoyo_read_globally_readable_policy(head)) | 1257 | struct tomoyo_acl_head *ptr = |
1216 | break; | 1258 | list_entry(mpos, struct tomoyo_acl_head, list); |
1217 | head->read_var2 = NULL; | 1259 | if (ptr->is_deleted) |
1218 | head->read_step = 3; | 1260 | continue; |
1219 | case 3: | 1261 | if (idx == TOMOYO_PATH_GROUP) { |
1220 | head->read_var2 = NULL; | 1262 | w[2] = container_of(ptr, |
1221 | head->read_step = 4; | 1263 | struct tomoyo_path_group, |
1222 | case 4: | 1264 | head)->member_name->name; |
1223 | if (!tomoyo_read_domain_initializer_policy(head)) | 1265 | } else if (idx == TOMOYO_NUMBER_GROUP) { |
1224 | break; | 1266 | tomoyo_print_number(buffer, sizeof(buffer), |
1225 | head->read_var2 = NULL; | 1267 | &container_of |
1226 | head->read_step = 5; | 1268 | (ptr, struct |
1227 | case 5: | 1269 | tomoyo_number_group, |
1228 | if (!tomoyo_read_alias_policy(head)) | 1270 | head)->number); |
1229 | break; | 1271 | w[2] = buffer; |
1230 | head->read_var2 = NULL; | 1272 | } |
1231 | head->read_step = 6; | 1273 | if (!tomoyo_io_printf(head, "%s%s %s\n", w[0], w[1], |
1232 | case 6: | 1274 | w[2])) |
1233 | if (!tomoyo_read_aggregator_policy(head)) | 1275 | return false; |
1234 | break; | 1276 | } |
1235 | head->read_var2 = NULL; | 1277 | } |
1236 | head->read_step = 7; | 1278 | return true; |
1237 | case 7: | 1279 | } |
1238 | if (!tomoyo_read_file_pattern(head)) | 1280 | |
1239 | break; | 1281 | /** |
1240 | head->read_var2 = NULL; | 1282 | * tomoyo_read_policy - Read "struct tomoyo_..._entry" list. |
1241 | head->read_step = 8; | 1283 | * |
1242 | case 8: | 1284 | * @head: Pointer to "struct tomoyo_io_buffer". |
1243 | if (!tomoyo_read_no_rewrite_policy(head)) | 1285 | * @idx: Index number. |
1244 | break; | 1286 | * |
1245 | head->read_var2 = NULL; | 1287 | * Returns true on success, false otherwise. |
1246 | head->read_step = 9; | 1288 | * |
1247 | case 9: | 1289 | * Caller holds tomoyo_read_lock(). |
1248 | if (!tomoyo_read_path_group_policy(head)) | 1290 | */ |
1249 | break; | 1291 | static bool tomoyo_read_policy(struct tomoyo_io_buffer *head, const int idx) |
1250 | head->read_var1 = NULL; | 1292 | { |
1251 | head->read_var2 = NULL; | 1293 | struct list_head *pos; |
1252 | head->read_step = 10; | 1294 | list_for_each_cookie(pos, head->read_var2, &tomoyo_policy_list[idx]) { |
1253 | case 10: | 1295 | const char *w[4] = { "", "", "", "" }; |
1254 | if (!tomoyo_read_number_group_policy(head)) | 1296 | struct tomoyo_acl_head *acl = container_of(pos, typeof(*acl), |
1255 | break; | 1297 | list); |
1256 | head->read_var1 = NULL; | 1298 | if (acl->is_deleted) |
1257 | head->read_var2 = NULL; | 1299 | continue; |
1258 | head->read_step = 11; | 1300 | switch (idx) { |
1259 | case 11: | 1301 | case TOMOYO_ID_DOMAIN_KEEPER: |
1260 | head->read_eof = true; | 1302 | { |
1303 | struct tomoyo_domain_keeper_entry *ptr = | ||
1304 | container_of(acl, typeof(*ptr), head); | ||
1305 | w[0] = ptr->is_not ? | ||
1306 | TOMOYO_KEYWORD_NO_KEEP_DOMAIN : | ||
1307 | TOMOYO_KEYWORD_KEEP_DOMAIN; | ||
1308 | if (ptr->program) { | ||
1309 | w[1] = ptr->program->name; | ||
1310 | w[2] = " from "; | ||
1311 | } | ||
1312 | w[3] = ptr->domainname->name; | ||
1313 | } | ||
1314 | break; | ||
1315 | case TOMOYO_ID_DOMAIN_INITIALIZER: | ||
1316 | { | ||
1317 | struct tomoyo_domain_initializer_entry *ptr = | ||
1318 | container_of(acl, typeof(*ptr), head); | ||
1319 | w[0] = ptr->is_not ? | ||
1320 | TOMOYO_KEYWORD_NO_INITIALIZE_DOMAIN : | ||
1321 | TOMOYO_KEYWORD_INITIALIZE_DOMAIN; | ||
1322 | w[1] = ptr->program->name; | ||
1323 | if (ptr->domainname) { | ||
1324 | w[2] = " from "; | ||
1325 | w[3] = ptr->domainname->name; | ||
1326 | } | ||
1327 | } | ||
1261 | break; | 1328 | break; |
1329 | case TOMOYO_ID_GLOBALLY_READABLE: | ||
1330 | { | ||
1331 | struct tomoyo_globally_readable_file_entry *ptr | ||
1332 | = container_of(acl, typeof(*ptr), head); | ||
1333 | w[0] = TOMOYO_KEYWORD_ALLOW_READ; | ||
1334 | w[1] = ptr->filename->name; | ||
1335 | } | ||
1336 | break; | ||
1337 | case TOMOYO_ID_ALIAS: | ||
1338 | { | ||
1339 | struct tomoyo_alias_entry *ptr = | ||
1340 | container_of(acl, typeof(*ptr), head); | ||
1341 | w[0] = TOMOYO_KEYWORD_ALIAS; | ||
1342 | w[1] = ptr->original_name->name; | ||
1343 | w[2] = " "; | ||
1344 | w[3] = ptr->aliased_name->name; | ||
1345 | } | ||
1346 | break; | ||
1347 | case TOMOYO_ID_AGGREGATOR: | ||
1348 | { | ||
1349 | struct tomoyo_aggregator_entry *ptr = | ||
1350 | container_of(acl, typeof(*ptr), head); | ||
1351 | w[0] = TOMOYO_KEYWORD_AGGREGATOR; | ||
1352 | w[1] = ptr->original_name->name; | ||
1353 | w[2] = " "; | ||
1354 | w[3] = ptr->aggregated_name->name; | ||
1355 | } | ||
1356 | break; | ||
1357 | case TOMOYO_ID_PATTERN: | ||
1358 | { | ||
1359 | struct tomoyo_pattern_entry *ptr = | ||
1360 | container_of(acl, typeof(*ptr), head); | ||
1361 | w[0] = TOMOYO_KEYWORD_FILE_PATTERN; | ||
1362 | w[1] = ptr->pattern->name; | ||
1363 | } | ||
1364 | break; | ||
1365 | case TOMOYO_ID_NO_REWRITE: | ||
1366 | { | ||
1367 | struct tomoyo_no_rewrite_entry *ptr = | ||
1368 | container_of(acl, typeof(*ptr), head); | ||
1369 | w[0] = TOMOYO_KEYWORD_DENY_REWRITE; | ||
1370 | w[1] = ptr->pattern->name; | ||
1371 | } | ||
1372 | break; | ||
1373 | default: | ||
1374 | continue; | ||
1262 | } | 1375 | } |
1376 | if (!tomoyo_io_printf(head, "%s%s%s%s\n", w[0], w[1], w[2], | ||
1377 | w[3])) | ||
1378 | return false; | ||
1263 | } | 1379 | } |
1380 | return true; | ||
1381 | } | ||
1382 | |||
1383 | /** | ||
1384 | * tomoyo_read_exception_policy - Read exception policy. | ||
1385 | * | ||
1386 | * @head: Pointer to "struct tomoyo_io_buffer". | ||
1387 | * | ||
1388 | * Caller holds tomoyo_read_lock(). | ||
1389 | */ | ||
1390 | static void tomoyo_read_exception_policy(struct tomoyo_io_buffer *head) | ||
1391 | { | ||
1392 | if (head->read_eof) | ||
1393 | return; | ||
1394 | while (head->read_step < TOMOYO_MAX_POLICY && | ||
1395 | tomoyo_read_policy(head, head->read_step)) | ||
1396 | head->read_step++; | ||
1397 | if (head->read_step < TOMOYO_MAX_POLICY) | ||
1398 | return; | ||
1399 | while (head->read_step < TOMOYO_MAX_POLICY + TOMOYO_MAX_GROUP && | ||
1400 | tomoyo_read_group(head, head->read_step - TOMOYO_MAX_POLICY)) | ||
1401 | head->read_step++; | ||
1402 | if (head->read_step < TOMOYO_MAX_POLICY + TOMOYO_MAX_GROUP) | ||
1403 | return; | ||
1404 | head->read_eof = true; | ||
1264 | } | 1405 | } |
1265 | 1406 | ||
1266 | /** | 1407 | /** |