|
@@ -866,33 +866,10 @@ static inline void audit_free_names(struct audit_context *context)
|
|
{
|
|
{
|
|
struct audit_names *n, *next;
|
|
struct audit_names *n, *next;
|
|
|
|
|
|
-#if AUDIT_DEBUG == 2
|
|
|
|
- if (context->put_count + context->ino_count != context->name_count) {
|
|
|
|
- int i = 0;
|
|
|
|
-
|
|
|
|
- pr_err("%s:%d(:%d): major=%d in_syscall=%d"
|
|
|
|
- " name_count=%d put_count=%d ino_count=%d"
|
|
|
|
- " [NOT freeing]\n", __FILE__, __LINE__,
|
|
|
|
- context->serial, context->major, context->in_syscall,
|
|
|
|
- context->name_count, context->put_count,
|
|
|
|
- context->ino_count);
|
|
|
|
- list_for_each_entry(n, &context->names_list, list) {
|
|
|
|
- pr_err("names[%d] = %p = %s\n", i++, n->name,
|
|
|
|
- n->name->name ?: "(null)");
|
|
|
|
- }
|
|
|
|
- dump_stack();
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
-#endif
|
|
|
|
-#if AUDIT_DEBUG
|
|
|
|
- context->put_count = 0;
|
|
|
|
- context->ino_count = 0;
|
|
|
|
-#endif
|
|
|
|
-
|
|
|
|
list_for_each_entry_safe(n, next, &context->names_list, list) {
|
|
list_for_each_entry_safe(n, next, &context->names_list, list) {
|
|
list_del(&n->list);
|
|
list_del(&n->list);
|
|
- if (n->name && n->name_put)
|
|
|
|
- final_putname(n->name);
|
|
|
|
|
|
+ if (n->name)
|
|
|
|
+ putname(n->name);
|
|
if (n->should_free)
|
|
if (n->should_free)
|
|
kfree(n);
|
|
kfree(n);
|
|
}
|
|
}
|
|
@@ -1711,9 +1688,6 @@ static struct audit_names *audit_alloc_name(struct audit_context *context,
|
|
list_add_tail(&aname->list, &context->names_list);
|
|
list_add_tail(&aname->list, &context->names_list);
|
|
|
|
|
|
context->name_count++;
|
|
context->name_count++;
|
|
-#if AUDIT_DEBUG
|
|
|
|
- context->ino_count++;
|
|
|
|
-#endif
|
|
|
|
return aname;
|
|
return aname;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1734,8 +1708,10 @@ __audit_reusename(const __user char *uptr)
|
|
list_for_each_entry(n, &context->names_list, list) {
|
|
list_for_each_entry(n, &context->names_list, list) {
|
|
if (!n->name)
|
|
if (!n->name)
|
|
continue;
|
|
continue;
|
|
- if (n->name->uptr == uptr)
|
|
|
|
|
|
+ if (n->name->uptr == uptr) {
|
|
|
|
+ n->name->refcnt++;
|
|
return n->name;
|
|
return n->name;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
return NULL;
|
|
return NULL;
|
|
}
|
|
}
|
|
@@ -1752,19 +1728,8 @@ void __audit_getname(struct filename *name)
|
|
struct audit_context *context = current->audit_context;
|
|
struct audit_context *context = current->audit_context;
|
|
struct audit_names *n;
|
|
struct audit_names *n;
|
|
|
|
|
|
- if (!context->in_syscall) {
|
|
|
|
-#if AUDIT_DEBUG == 2
|
|
|
|
- pr_err("%s:%d(:%d): ignoring getname(%p)\n",
|
|
|
|
- __FILE__, __LINE__, context->serial, name);
|
|
|
|
- dump_stack();
|
|
|
|
-#endif
|
|
|
|
|
|
+ if (!context->in_syscall)
|
|
return;
|
|
return;
|
|
- }
|
|
|
|
-
|
|
|
|
-#if AUDIT_DEBUG
|
|
|
|
- /* The filename _must_ have a populated ->name */
|
|
|
|
- BUG_ON(!name->name);
|
|
|
|
-#endif
|
|
|
|
|
|
|
|
n = audit_alloc_name(context, AUDIT_TYPE_UNKNOWN);
|
|
n = audit_alloc_name(context, AUDIT_TYPE_UNKNOWN);
|
|
if (!n)
|
|
if (!n)
|
|
@@ -1772,56 +1737,13 @@ void __audit_getname(struct filename *name)
|
|
|
|
|
|
n->name = name;
|
|
n->name = name;
|
|
n->name_len = AUDIT_NAME_FULL;
|
|
n->name_len = AUDIT_NAME_FULL;
|
|
- n->name_put = true;
|
|
|
|
name->aname = n;
|
|
name->aname = n;
|
|
|
|
+ name->refcnt++;
|
|
|
|
|
|
if (!context->pwd.dentry)
|
|
if (!context->pwd.dentry)
|
|
get_fs_pwd(current->fs, &context->pwd);
|
|
get_fs_pwd(current->fs, &context->pwd);
|
|
}
|
|
}
|
|
|
|
|
|
-/* audit_putname - intercept a putname request
|
|
|
|
- * @name: name to intercept and delay for putname
|
|
|
|
- *
|
|
|
|
- * If we have stored the name from getname in the audit context,
|
|
|
|
- * then we delay the putname until syscall exit.
|
|
|
|
- * Called from include/linux/fs.h:putname().
|
|
|
|
- */
|
|
|
|
-void audit_putname(struct filename *name)
|
|
|
|
-{
|
|
|
|
- struct audit_context *context = current->audit_context;
|
|
|
|
-
|
|
|
|
- BUG_ON(!context);
|
|
|
|
- if (!name->aname || !context->in_syscall) {
|
|
|
|
-#if AUDIT_DEBUG == 2
|
|
|
|
- pr_err("%s:%d(:%d): final_putname(%p)\n",
|
|
|
|
- __FILE__, __LINE__, context->serial, name);
|
|
|
|
- if (context->name_count) {
|
|
|
|
- struct audit_names *n;
|
|
|
|
- int i = 0;
|
|
|
|
-
|
|
|
|
- list_for_each_entry(n, &context->names_list, list)
|
|
|
|
- pr_err("name[%d] = %p = %s\n", i++, n->name,
|
|
|
|
- n->name->name ?: "(null)");
|
|
|
|
- }
|
|
|
|
-#endif
|
|
|
|
- final_putname(name);
|
|
|
|
- }
|
|
|
|
-#if AUDIT_DEBUG
|
|
|
|
- else {
|
|
|
|
- ++context->put_count;
|
|
|
|
- if (context->put_count > context->name_count) {
|
|
|
|
- pr_err("%s:%d(:%d): major=%d in_syscall=%d putname(%p)"
|
|
|
|
- " name_count=%d put_count=%d\n",
|
|
|
|
- __FILE__, __LINE__,
|
|
|
|
- context->serial, context->major,
|
|
|
|
- context->in_syscall, name->name,
|
|
|
|
- context->name_count, context->put_count);
|
|
|
|
- dump_stack();
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-#endif
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
/**
|
|
/**
|
|
* __audit_inode - store the inode and device from a lookup
|
|
* __audit_inode - store the inode and device from a lookup
|
|
* @name: name being audited
|
|
* @name: name being audited
|
|
@@ -1842,11 +1764,6 @@ void __audit_inode(struct filename *name, const struct dentry *dentry,
|
|
if (!name)
|
|
if (!name)
|
|
goto out_alloc;
|
|
goto out_alloc;
|
|
|
|
|
|
-#if AUDIT_DEBUG
|
|
|
|
- /* The struct filename _must_ have a populated ->name */
|
|
|
|
- BUG_ON(!name->name);
|
|
|
|
-#endif
|
|
|
|
-
|
|
|
|
/*
|
|
/*
|
|
* If we have a pointer to an audit_names entry already, then we can
|
|
* If we have a pointer to an audit_names entry already, then we can
|
|
* just use it directly if the type is correct.
|
|
* just use it directly if the type is correct.
|
|
@@ -1893,9 +1810,10 @@ out_alloc:
|
|
n = audit_alloc_name(context, AUDIT_TYPE_UNKNOWN);
|
|
n = audit_alloc_name(context, AUDIT_TYPE_UNKNOWN);
|
|
if (!n)
|
|
if (!n)
|
|
return;
|
|
return;
|
|
- if (name)
|
|
|
|
- /* no need to set ->name_put as the original will cleanup */
|
|
|
|
|
|
+ if (name) {
|
|
n->name = name;
|
|
n->name = name;
|
|
|
|
+ name->refcnt++;
|
|
|
|
+ }
|
|
|
|
|
|
out:
|
|
out:
|
|
if (parent) {
|
|
if (parent) {
|
|
@@ -2000,8 +1918,7 @@ void __audit_inode_child(const struct inode *parent,
|
|
if (found_parent) {
|
|
if (found_parent) {
|
|
found_child->name = found_parent->name;
|
|
found_child->name = found_parent->name;
|
|
found_child->name_len = AUDIT_NAME_FULL;
|
|
found_child->name_len = AUDIT_NAME_FULL;
|
|
- /* don't call __putname() */
|
|
|
|
- found_child->name_put = false;
|
|
|
|
|
|
+ found_child->name->refcnt++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|