aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorAmy Griffis <amy.griffis@hp.com>2007-02-13 14:15:22 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2007-05-11 05:38:26 -0400
commit5712e88f2b0f626a4857c24128810bbf8ce09537 (patch)
tree1285a3e632e6c3d6dfecc2c3445770a559c712ca /kernel
parent4fc03b9beb2314f3adb9e72b7935a80c577954d1 (diff)
[PATCH] match audit name data
Make more effort to detect previously collected names, so we don't log multiple PATH records for a single filesystem object. Add audit_inc_name_count() to reduce duplicate code. Signed-off-by: Amy Griffis <amy.griffis@hp.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/auditsc.c142
1 files changed, 84 insertions, 58 deletions
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 25d890e997f..5276b7ef05f 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
1341static 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. */
1347static void audit_copy_inode(struct audit_names *name, const struct inode *inode) 1364static 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
1436update_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 1471add_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/**