aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorJeff Layton <jlayton@redhat.com>2012-10-10 15:25:28 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2012-10-12 20:14:55 -0400
commit91a27b2a756784714e924e5e854b919273082d26 (patch)
tree3913246b7d6e62703ec915f481e3a7159393f0f0 /kernel
parent8e377d15078a501c4da98471f56396343c407d92 (diff)
vfs: define struct filename and have getname() return it
getname() is intended to copy pathname strings from userspace into a kernel buffer. The result is just a string in kernel space. It would however be quite helpful to be able to attach some ancillary info to the string. For instance, we could attach some audit-related info to reduce the amount of audit-related processing needed. When auditing is enabled, we could also call getname() on the string more than once and not need to recopy it from userspace. This patchset converts the getname()/putname() interfaces to return a struct instead of a string. For now, the struct just tracks the string in kernel space and the original userland pointer for it. Later, we'll add other information to the struct as it becomes convenient. Signed-off-by: Jeff Layton <jlayton@redhat.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/acct.c4
-rw-r--r--kernel/auditsc.c64
2 files changed, 37 insertions, 31 deletions
diff --git a/kernel/acct.c b/kernel/acct.c
index 5be01017d30f..08354195eecc 100644
--- a/kernel/acct.c
+++ b/kernel/acct.c
@@ -260,10 +260,10 @@ SYSCALL_DEFINE1(acct, const char __user *, name)
260 return -EPERM; 260 return -EPERM;
261 261
262 if (name) { 262 if (name) {
263 char *tmp = getname(name); 263 struct filename *tmp = getname(name);
264 if (IS_ERR(tmp)) 264 if (IS_ERR(tmp))
265 return (PTR_ERR(tmp)); 265 return (PTR_ERR(tmp));
266 error = acct_on(tmp); 266 error = acct_on(tmp->name);
267 putname(tmp); 267 putname(tmp);
268 } else { 268 } else {
269 struct bsd_acct_struct *acct; 269 struct bsd_acct_struct *acct;
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index d147585e9ef3..d4d82319eed5 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -103,28 +103,29 @@ struct audit_cap_data {
103 * we don't let putname() free it (instead we free all of the saved 103 * we don't let putname() free it (instead we free all of the saved
104 * pointers at syscall exit time). 104 * pointers at syscall exit time).
105 * 105 *
106 * Further, in fs/namei.c:path_lookup() we store the inode and device. */ 106 * Further, in fs/namei.c:path_lookup() we store the inode and device.
107 */
107struct audit_names { 108struct audit_names {
108 struct list_head list; /* audit_context->names_list */ 109 struct list_head list; /* audit_context->names_list */
109 const char *name; 110 struct filename *name;
110 unsigned long ino; 111 unsigned long ino;
111 dev_t dev; 112 dev_t dev;
112 umode_t mode; 113 umode_t mode;
113 kuid_t uid; 114 kuid_t uid;
114 kgid_t gid; 115 kgid_t gid;
115 dev_t rdev; 116 dev_t rdev;
116 u32 osid; 117 u32 osid;
117 struct audit_cap_data fcap; 118 struct audit_cap_data fcap;
118 unsigned int fcap_ver; 119 unsigned int fcap_ver;
119 int name_len; /* number of name's characters to log */ 120 int name_len; /* number of name's characters to log */
120 unsigned char type; /* record type */ 121 unsigned char type; /* record type */
121 bool name_put; /* call __putname() for this name */ 122 bool name_put; /* call __putname() for this name */
122 /* 123 /*
123 * This was an allocated audit_names and not from the array of 124 * This was an allocated audit_names and not from the array of
124 * names allocated in the task audit context. Thus this name 125 * names allocated in the task audit context. Thus this name
125 * should be freed on syscall exit 126 * should be freed on syscall exit
126 */ 127 */
127 bool should_free; 128 bool should_free;
128}; 129};
129 130
130struct audit_aux_data { 131struct audit_aux_data {
@@ -996,7 +997,7 @@ static inline void audit_free_names(struct audit_context *context)
996 context->ino_count); 997 context->ino_count);
997 list_for_each_entry(n, &context->names_list, list) { 998 list_for_each_entry(n, &context->names_list, list) {
998 printk(KERN_ERR "names[%d] = %p = %s\n", i, 999 printk(KERN_ERR "names[%d] = %p = %s\n", i,
999 n->name, n->name ?: "(null)"); 1000 n->name, n->name->name ?: "(null)");
1000 } 1001 }
1001 dump_stack(); 1002 dump_stack();
1002 return; 1003 return;
@@ -1553,7 +1554,7 @@ static void audit_log_name(struct audit_context *context, struct audit_names *n,
1553 case AUDIT_NAME_FULL: 1554 case AUDIT_NAME_FULL:
1554 /* log the full path */ 1555 /* log the full path */
1555 audit_log_format(ab, " name="); 1556 audit_log_format(ab, " name=");
1556 audit_log_untrustedstring(ab, n->name); 1557 audit_log_untrustedstring(ab, n->name->name);
1557 break; 1558 break;
1558 case 0: 1559 case 0:
1559 /* name was specified as a relative path and the 1560 /* name was specified as a relative path and the
@@ -1563,7 +1564,7 @@ static void audit_log_name(struct audit_context *context, struct audit_names *n,
1563 default: 1564 default:
1564 /* log the name's directory component */ 1565 /* log the name's directory component */
1565 audit_log_format(ab, " name="); 1566 audit_log_format(ab, " name=");
1566 audit_log_n_untrustedstring(ab, n->name, 1567 audit_log_n_untrustedstring(ab, n->name->name,
1567 n->name_len); 1568 n->name_len);
1568 } 1569 }
1569 } else 1570 } else
@@ -2026,7 +2027,7 @@ static struct audit_names *audit_alloc_name(struct audit_context *context,
2026 * Add a name to the list of audit names for this context. 2027 * Add a name to the list of audit names for this context.
2027 * Called from fs/namei.c:getname(). 2028 * Called from fs/namei.c:getname().
2028 */ 2029 */
2029void __audit_getname(const char *name) 2030void __audit_getname(struct filename *name)
2030{ 2031{
2031 struct audit_context *context = current->audit_context; 2032 struct audit_context *context = current->audit_context;
2032 struct audit_names *n; 2033 struct audit_names *n;
@@ -2040,6 +2041,11 @@ void __audit_getname(const char *name)
2040 return; 2041 return;
2041 } 2042 }
2042 2043
2044#if AUDIT_DEBUG
2045 /* The filename _must_ have a populated ->name */
2046 BUG_ON(!name->name);
2047#endif
2048
2043 n = audit_alloc_name(context, AUDIT_TYPE_UNKNOWN); 2049 n = audit_alloc_name(context, AUDIT_TYPE_UNKNOWN);
2044 if (!n) 2050 if (!n)
2045 return; 2051 return;
@@ -2059,7 +2065,7 @@ void __audit_getname(const char *name)
2059 * then we delay the putname until syscall exit. 2065 * then we delay the putname until syscall exit.
2060 * Called from include/linux/fs.h:putname(). 2066 * Called from include/linux/fs.h:putname().
2061 */ 2067 */
2062void audit_putname(const char *name) 2068void audit_putname(struct filename *name)
2063{ 2069{
2064 struct audit_context *context = current->audit_context; 2070 struct audit_context *context = current->audit_context;
2065 2071
@@ -2074,7 +2080,7 @@ void audit_putname(const char *name)
2074 2080
2075 list_for_each_entry(n, &context->names_list, list) 2081 list_for_each_entry(n, &context->names_list, list)
2076 printk(KERN_ERR "name[%d] = %p = %s\n", i, 2082 printk(KERN_ERR "name[%d] = %p = %s\n", i,
2077 n->name, n->name ?: "(null)"); 2083 n->name, n->name->name ?: "(null)");
2078 } 2084 }
2079#endif 2085#endif
2080 __putname(name); 2086 __putname(name);
@@ -2088,8 +2094,8 @@ void audit_putname(const char *name)
2088 " put_count=%d\n", 2094 " put_count=%d\n",
2089 __FILE__, __LINE__, 2095 __FILE__, __LINE__,
2090 context->serial, context->major, 2096 context->serial, context->major,
2091 context->in_syscall, name, context->name_count, 2097 context->in_syscall, name->name,
2092 context->put_count); 2098 context->name_count, context->put_count);
2093 dump_stack(); 2099 dump_stack();
2094 } 2100 }
2095 } 2101 }
@@ -2152,7 +2158,7 @@ void __audit_inode(const char *name, const struct dentry *dentry,
2152 2158
2153 list_for_each_entry_reverse(n, &context->names_list, list) { 2159 list_for_each_entry_reverse(n, &context->names_list, list) {
2154 /* does the name pointer match? */ 2160 /* does the name pointer match? */
2155 if (n->name != name) 2161 if (!n->name || n->name->name != name)
2156 continue; 2162 continue;
2157 2163
2158 /* match the correct record type */ 2164 /* match the correct record type */
@@ -2175,7 +2181,7 @@ out_alloc:
2175 return; 2181 return;
2176out: 2182out:
2177 if (parent) { 2183 if (parent) {
2178 n->name_len = n->name ? parent_len(n->name) : AUDIT_NAME_FULL; 2184 n->name_len = n->name ? parent_len(n->name->name) : AUDIT_NAME_FULL;
2179 n->type = AUDIT_TYPE_PARENT; 2185 n->type = AUDIT_TYPE_PARENT;
2180 } else { 2186 } else {
2181 n->name_len = AUDIT_NAME_FULL; 2187 n->name_len = AUDIT_NAME_FULL;
@@ -2220,7 +2226,7 @@ void __audit_inode_child(const struct inode *parent,
2220 continue; 2226 continue;
2221 2227
2222 if (n->ino == parent->i_ino && 2228 if (n->ino == parent->i_ino &&
2223 !audit_compare_dname_path(dname, n->name, n->name_len)) { 2229 !audit_compare_dname_path(dname, n->name->name, n->name_len)) {
2224 found_parent = n; 2230 found_parent = n;
2225 break; 2231 break;
2226 } 2232 }
@@ -2236,8 +2242,8 @@ void __audit_inode_child(const struct inode *parent,
2236 if (found_parent && (n->name != found_parent->name)) 2242 if (found_parent && (n->name != found_parent->name))
2237 continue; 2243 continue;
2238 2244
2239 if (!strcmp(dname, n->name) || 2245 if (!strcmp(dname, n->name->name) ||
2240 !audit_compare_dname_path(dname, n->name, 2246 !audit_compare_dname_path(dname, n->name->name,
2241 found_parent ? 2247 found_parent ?
2242 found_parent->name_len : 2248 found_parent->name_len :
2243 AUDIT_NAME_FULL)) { 2249 AUDIT_NAME_FULL)) {