diff options
| -rw-r--r-- | kernel/auditsc.c | 142 |
1 files changed, 84 insertions, 58 deletions
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 25d890e997f2..5276b7ef05f1 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
| @@ -78,11 +78,6 @@ extern int audit_enabled; | |||
| 78 | * for saving names from getname(). */ | 78 | * for saving names from getname(). */ |
| 79 | #define AUDIT_NAMES 20 | 79 | #define AUDIT_NAMES 20 |
| 80 | 80 | ||
| 81 | /* AUDIT_NAMES_RESERVED is the number of slots we reserve in the | ||
| 82 | * audit_context from being used for nameless inodes from | ||
| 83 | * path_lookup. */ | ||
| 84 | #define AUDIT_NAMES_RESERVED 7 | ||
| 85 | |||
| 86 | /* Indicates that audit should log the full pathname. */ | 81 | /* Indicates that audit should log the full pathname. */ |
| 87 | #define AUDIT_NAME_FULL -1 | 82 | #define AUDIT_NAME_FULL -1 |
| 88 | 83 | ||
| @@ -1343,6 +1338,28 @@ void audit_putname(const char *name) | |||
| 1343 | #endif | 1338 | #endif |
| 1344 | } | 1339 | } |
| 1345 | 1340 | ||
| 1341 | static int audit_inc_name_count(struct audit_context *context, | ||
| 1342 | const struct inode *inode) | ||
| 1343 | { | ||
| 1344 | if (context->name_count >= AUDIT_NAMES) { | ||
| 1345 | if (inode) | ||
| 1346 | printk(KERN_DEBUG "name_count maxed, losing inode data: " | ||
| 1347 | "dev=%02x:%02x, inode=%lu", | ||
| 1348 | MAJOR(inode->i_sb->s_dev), | ||
| 1349 | MINOR(inode->i_sb->s_dev), | ||
| 1350 | inode->i_ino); | ||
| 1351 | |||
| 1352 | else | ||
| 1353 | printk(KERN_DEBUG "name_count maxed, losing inode data"); | ||
| 1354 | return 1; | ||
| 1355 | } | ||
| 1356 | context->name_count++; | ||
| 1357 | #if AUDIT_DEBUG | ||
| 1358 | context->ino_count++; | ||
| 1359 | #endif | ||
| 1360 | return 0; | ||
| 1361 | } | ||
| 1362 | |||
| 1346 | /* Copy inode data into an audit_names. */ | 1363 | /* Copy inode data into an audit_names. */ |
| 1347 | static void audit_copy_inode(struct audit_names *name, const struct inode *inode) | 1364 | static void audit_copy_inode(struct audit_names *name, const struct inode *inode) |
| 1348 | { | 1365 | { |
| @@ -1380,13 +1397,10 @@ void __audit_inode(const char *name, const struct inode *inode) | |||
| 1380 | else { | 1397 | else { |
| 1381 | /* FIXME: how much do we care about inodes that have no | 1398 | /* FIXME: how much do we care about inodes that have no |
| 1382 | * associated name? */ | 1399 | * associated name? */ |
| 1383 | if (context->name_count >= AUDIT_NAMES - AUDIT_NAMES_RESERVED) | 1400 | if (audit_inc_name_count(context, inode)) |
| 1384 | return; | 1401 | return; |
| 1385 | idx = context->name_count++; | 1402 | idx = context->name_count - 1; |
| 1386 | context->names[idx].name = NULL; | 1403 | context->names[idx].name = NULL; |
| 1387 | #if AUDIT_DEBUG | ||
| 1388 | ++context->ino_count; | ||
| 1389 | #endif | ||
| 1390 | } | 1404 | } |
| 1391 | audit_copy_inode(&context->names[idx], inode); | 1405 | audit_copy_inode(&context->names[idx], inode); |
| 1392 | } | 1406 | } |
| @@ -1410,7 +1424,7 @@ void __audit_inode_child(const char *dname, const struct inode *inode, | |||
| 1410 | { | 1424 | { |
| 1411 | int idx; | 1425 | int idx; |
| 1412 | struct audit_context *context = current->audit_context; | 1426 | struct audit_context *context = current->audit_context; |
| 1413 | const char *found_name = NULL; | 1427 | const char *found_parent = NULL, *found_child = NULL; |
| 1414 | int dirlen = 0; | 1428 | int dirlen = 0; |
| 1415 | 1429 | ||
| 1416 | if (!context->in_syscall) | 1430 | if (!context->in_syscall) |
| @@ -1418,61 +1432,73 @@ void __audit_inode_child(const char *dname, const struct inode *inode, | |||
| 1418 | 1432 | ||
| 1419 | /* determine matching parent */ | 1433 | /* determine matching parent */ |
| 1420 | if (!dname) | 1434 | if (!dname) |
| 1421 | goto update_context; | 1435 | goto add_names; |
| 1422 | for (idx = 0; idx < context->name_count; idx++) | ||
| 1423 | if (context->names[idx].ino == parent->i_ino) { | ||
| 1424 | const char *name = context->names[idx].name; | ||
| 1425 | 1436 | ||
| 1426 | if (!name) | 1437 | /* parent is more likely, look for it first */ |
| 1427 | continue; | 1438 | for (idx = 0; idx < context->name_count; idx++) { |
| 1439 | struct audit_names *n = &context->names[idx]; | ||
| 1428 | 1440 | ||
| 1429 | if (audit_compare_dname_path(dname, name, &dirlen) == 0) { | 1441 | if (!n->name) |
| 1430 | context->names[idx].name_len = dirlen; | 1442 | continue; |
| 1431 | found_name = name; | 1443 | |
| 1432 | break; | 1444 | if (n->ino == parent->i_ino && |
| 1433 | } | 1445 | !audit_compare_dname_path(dname, n->name, &dirlen)) { |
| 1446 | n->name_len = dirlen; /* update parent data in place */ | ||
| 1447 | found_parent = n->name; | ||
| 1448 | goto add_names; | ||
| 1434 | } | 1449 | } |
| 1450 | } | ||
| 1435 | 1451 | ||
| 1436 | update_context: | 1452 | /* no matching parent, look for matching child */ |
| 1437 | idx = context->name_count; | 1453 | for (idx = 0; idx < context->name_count; idx++) { |
| 1438 | if (context->name_count == AUDIT_NAMES) { | 1454 | struct audit_names *n = &context->names[idx]; |
| 1439 | printk(KERN_DEBUG "name_count maxed and losing %s\n", | 1455 | |
| 1440 | found_name ?: "(null)"); | 1456 | if (!n->name) |
| 1441 | return; | 1457 | continue; |
| 1458 | |||
| 1459 | /* strcmp() is the more likely scenario */ | ||
| 1460 | if (!strcmp(dname, n->name) || | ||
| 1461 | !audit_compare_dname_path(dname, n->name, &dirlen)) { | ||
| 1462 | if (inode) | ||
| 1463 | audit_copy_inode(n, inode); | ||
| 1464 | else | ||
| 1465 | n->ino = (unsigned long)-1; | ||
| 1466 | found_child = n->name; | ||
| 1467 | goto add_names; | ||
| 1468 | } | ||
| 1442 | } | 1469 | } |
| 1443 | context->name_count++; | 1470 | |
| 1444 | #if AUDIT_DEBUG | 1471 | add_names: |
| 1445 | context->ino_count++; | 1472 | if (!found_parent) { |
| 1446 | #endif | 1473 | if (audit_inc_name_count(context, parent)) |
| 1447 | /* Re-use the name belonging to the slot for a matching parent directory. | ||
| 1448 | * All names for this context are relinquished in audit_free_names() */ | ||
| 1449 | context->names[idx].name = found_name; | ||
| 1450 | context->names[idx].name_len = AUDIT_NAME_FULL; | ||
| 1451 | context->names[idx].name_put = 0; /* don't call __putname() */ | ||
| 1452 | |||
| 1453 | if (!inode) | ||
| 1454 | context->names[idx].ino = (unsigned long)-1; | ||
| 1455 | else | ||
| 1456 | audit_copy_inode(&context->names[idx], inode); | ||
| 1457 | |||
| 1458 | /* A parent was not found in audit_names, so copy the inode data for the | ||
| 1459 | * provided parent. */ | ||
| 1460 | if (!found_name) { | ||
| 1461 | idx = context->name_count; | ||
| 1462 | if (context->name_count == AUDIT_NAMES) { | ||
| 1463 | printk(KERN_DEBUG | ||
| 1464 | "name_count maxed and losing parent inode data: dev=%02x:%02x, inode=%lu", | ||
| 1465 | MAJOR(parent->i_sb->s_dev), | ||
| 1466 | MINOR(parent->i_sb->s_dev), | ||
| 1467 | parent->i_ino); | ||
| 1468 | return; | 1474 | return; |
| 1469 | } | 1475 | idx = context->name_count - 1; |
| 1470 | context->name_count++; | 1476 | context->names[idx].name = NULL; |
| 1471 | #if AUDIT_DEBUG | ||
| 1472 | context->ino_count++; | ||
| 1473 | #endif | ||
| 1474 | audit_copy_inode(&context->names[idx], parent); | 1477 | audit_copy_inode(&context->names[idx], parent); |
| 1475 | } | 1478 | } |
| 1479 | |||
| 1480 | if (!found_child) { | ||
| 1481 | if (audit_inc_name_count(context, inode)) | ||
| 1482 | return; | ||
| 1483 | idx = context->name_count - 1; | ||
| 1484 | |||
| 1485 | /* Re-use the name belonging to the slot for a matching parent | ||
| 1486 | * directory. All names for this context are relinquished in | ||
| 1487 | * audit_free_names() */ | ||
| 1488 | if (found_parent) { | ||
| 1489 | context->names[idx].name = found_parent; | ||
| 1490 | context->names[idx].name_len = AUDIT_NAME_FULL; | ||
| 1491 | /* don't call __putname() */ | ||
| 1492 | context->names[idx].name_put = 0; | ||
| 1493 | } else { | ||
| 1494 | context->names[idx].name = NULL; | ||
| 1495 | } | ||
| 1496 | |||
| 1497 | if (inode) | ||
| 1498 | audit_copy_inode(&context->names[idx], inode); | ||
| 1499 | else | ||
| 1500 | context->names[idx].ino = (unsigned long)-1; | ||
| 1501 | } | ||
| 1476 | } | 1502 | } |
| 1477 | 1503 | ||
| 1478 | /** | 1504 | /** |
