diff options
Diffstat (limited to 'fs/kernfs/inode.c')
-rw-r--r-- | fs/kernfs/inode.c | 162 |
1 files changed, 62 insertions, 100 deletions
diff --git a/fs/kernfs/inode.c b/fs/kernfs/inode.c index 0c1fd945ce42..f89a0f13840e 100644 --- a/fs/kernfs/inode.c +++ b/fs/kernfs/inode.c | |||
@@ -31,30 +31,27 @@ static const struct inode_operations kernfs_iops = { | |||
31 | .listxattr = kernfs_iop_listxattr, | 31 | .listxattr = kernfs_iop_listxattr, |
32 | }; | 32 | }; |
33 | 33 | ||
34 | static struct kernfs_iattrs *kernfs_iattrs(struct kernfs_node *kn) | 34 | static struct kernfs_iattrs *__kernfs_iattrs(struct kernfs_node *kn, int alloc) |
35 | { | 35 | { |
36 | static DEFINE_MUTEX(iattr_mutex); | 36 | static DEFINE_MUTEX(iattr_mutex); |
37 | struct kernfs_iattrs *ret; | 37 | struct kernfs_iattrs *ret; |
38 | struct iattr *iattrs; | ||
39 | 38 | ||
40 | mutex_lock(&iattr_mutex); | 39 | mutex_lock(&iattr_mutex); |
41 | 40 | ||
42 | if (kn->iattr) | 41 | if (kn->iattr || !alloc) |
43 | goto out_unlock; | 42 | goto out_unlock; |
44 | 43 | ||
45 | kn->iattr = kmem_cache_zalloc(kernfs_iattrs_cache, GFP_KERNEL); | 44 | kn->iattr = kmem_cache_zalloc(kernfs_iattrs_cache, GFP_KERNEL); |
46 | if (!kn->iattr) | 45 | if (!kn->iattr) |
47 | goto out_unlock; | 46 | goto out_unlock; |
48 | iattrs = &kn->iattr->ia_iattr; | ||
49 | 47 | ||
50 | /* assign default attributes */ | 48 | /* assign default attributes */ |
51 | iattrs->ia_mode = kn->mode; | 49 | kn->iattr->ia_uid = GLOBAL_ROOT_UID; |
52 | iattrs->ia_uid = GLOBAL_ROOT_UID; | 50 | kn->iattr->ia_gid = GLOBAL_ROOT_GID; |
53 | iattrs->ia_gid = GLOBAL_ROOT_GID; | ||
54 | 51 | ||
55 | ktime_get_real_ts64(&iattrs->ia_atime); | 52 | ktime_get_real_ts64(&kn->iattr->ia_atime); |
56 | iattrs->ia_mtime = iattrs->ia_atime; | 53 | kn->iattr->ia_mtime = kn->iattr->ia_atime; |
57 | iattrs->ia_ctime = iattrs->ia_atime; | 54 | kn->iattr->ia_ctime = kn->iattr->ia_atime; |
58 | 55 | ||
59 | simple_xattrs_init(&kn->iattr->xattrs); | 56 | simple_xattrs_init(&kn->iattr->xattrs); |
60 | out_unlock: | 57 | out_unlock: |
@@ -63,32 +60,37 @@ out_unlock: | |||
63 | return ret; | 60 | return ret; |
64 | } | 61 | } |
65 | 62 | ||
63 | static struct kernfs_iattrs *kernfs_iattrs(struct kernfs_node *kn) | ||
64 | { | ||
65 | return __kernfs_iattrs(kn, 1); | ||
66 | } | ||
67 | |||
68 | static struct kernfs_iattrs *kernfs_iattrs_noalloc(struct kernfs_node *kn) | ||
69 | { | ||
70 | return __kernfs_iattrs(kn, 0); | ||
71 | } | ||
72 | |||
66 | int __kernfs_setattr(struct kernfs_node *kn, const struct iattr *iattr) | 73 | int __kernfs_setattr(struct kernfs_node *kn, const struct iattr *iattr) |
67 | { | 74 | { |
68 | struct kernfs_iattrs *attrs; | 75 | struct kernfs_iattrs *attrs; |
69 | struct iattr *iattrs; | ||
70 | unsigned int ia_valid = iattr->ia_valid; | 76 | unsigned int ia_valid = iattr->ia_valid; |
71 | 77 | ||
72 | attrs = kernfs_iattrs(kn); | 78 | attrs = kernfs_iattrs(kn); |
73 | if (!attrs) | 79 | if (!attrs) |
74 | return -ENOMEM; | 80 | return -ENOMEM; |
75 | 81 | ||
76 | iattrs = &attrs->ia_iattr; | ||
77 | |||
78 | if (ia_valid & ATTR_UID) | 82 | if (ia_valid & ATTR_UID) |
79 | iattrs->ia_uid = iattr->ia_uid; | 83 | attrs->ia_uid = iattr->ia_uid; |
80 | if (ia_valid & ATTR_GID) | 84 | if (ia_valid & ATTR_GID) |
81 | iattrs->ia_gid = iattr->ia_gid; | 85 | attrs->ia_gid = iattr->ia_gid; |
82 | if (ia_valid & ATTR_ATIME) | 86 | if (ia_valid & ATTR_ATIME) |
83 | iattrs->ia_atime = iattr->ia_atime; | 87 | attrs->ia_atime = iattr->ia_atime; |
84 | if (ia_valid & ATTR_MTIME) | 88 | if (ia_valid & ATTR_MTIME) |
85 | iattrs->ia_mtime = iattr->ia_mtime; | 89 | attrs->ia_mtime = iattr->ia_mtime; |
86 | if (ia_valid & ATTR_CTIME) | 90 | if (ia_valid & ATTR_CTIME) |
87 | iattrs->ia_ctime = iattr->ia_ctime; | 91 | attrs->ia_ctime = iattr->ia_ctime; |
88 | if (ia_valid & ATTR_MODE) { | 92 | if (ia_valid & ATTR_MODE) |
89 | umode_t mode = iattr->ia_mode; | 93 | kn->mode = iattr->ia_mode; |
90 | iattrs->ia_mode = kn->mode = mode; | ||
91 | } | ||
92 | return 0; | 94 | return 0; |
93 | } | 95 | } |
94 | 96 | ||
@@ -135,23 +137,6 @@ out: | |||
135 | return error; | 137 | return error; |
136 | } | 138 | } |
137 | 139 | ||
138 | static int kernfs_node_setsecdata(struct kernfs_iattrs *attrs, void **secdata, | ||
139 | u32 *secdata_len) | ||
140 | { | ||
141 | void *old_secdata; | ||
142 | size_t old_secdata_len; | ||
143 | |||
144 | old_secdata = attrs->ia_secdata; | ||
145 | old_secdata_len = attrs->ia_secdata_len; | ||
146 | |||
147 | attrs->ia_secdata = *secdata; | ||
148 | attrs->ia_secdata_len = *secdata_len; | ||
149 | |||
150 | *secdata = old_secdata; | ||
151 | *secdata_len = old_secdata_len; | ||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t size) | 140 | ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t size) |
156 | { | 141 | { |
157 | struct kernfs_node *kn = kernfs_dentry_node(dentry); | 142 | struct kernfs_node *kn = kernfs_dentry_node(dentry); |
@@ -171,14 +156,15 @@ static inline void set_default_inode_attr(struct inode *inode, umode_t mode) | |||
171 | inode->i_ctime = current_time(inode); | 156 | inode->i_ctime = current_time(inode); |
172 | } | 157 | } |
173 | 158 | ||
174 | static inline void set_inode_attr(struct inode *inode, struct iattr *iattr) | 159 | static inline void set_inode_attr(struct inode *inode, |
160 | struct kernfs_iattrs *attrs) | ||
175 | { | 161 | { |
176 | struct super_block *sb = inode->i_sb; | 162 | struct super_block *sb = inode->i_sb; |
177 | inode->i_uid = iattr->ia_uid; | 163 | inode->i_uid = attrs->ia_uid; |
178 | inode->i_gid = iattr->ia_gid; | 164 | inode->i_gid = attrs->ia_gid; |
179 | inode->i_atime = timespec64_trunc(iattr->ia_atime, sb->s_time_gran); | 165 | inode->i_atime = timespec64_trunc(attrs->ia_atime, sb->s_time_gran); |
180 | inode->i_mtime = timespec64_trunc(iattr->ia_mtime, sb->s_time_gran); | 166 | inode->i_mtime = timespec64_trunc(attrs->ia_mtime, sb->s_time_gran); |
181 | inode->i_ctime = timespec64_trunc(iattr->ia_ctime, sb->s_time_gran); | 167 | inode->i_ctime = timespec64_trunc(attrs->ia_ctime, sb->s_time_gran); |
182 | } | 168 | } |
183 | 169 | ||
184 | static void kernfs_refresh_inode(struct kernfs_node *kn, struct inode *inode) | 170 | static void kernfs_refresh_inode(struct kernfs_node *kn, struct inode *inode) |
@@ -186,15 +172,12 @@ static void kernfs_refresh_inode(struct kernfs_node *kn, struct inode *inode) | |||
186 | struct kernfs_iattrs *attrs = kn->iattr; | 172 | struct kernfs_iattrs *attrs = kn->iattr; |
187 | 173 | ||
188 | inode->i_mode = kn->mode; | 174 | inode->i_mode = kn->mode; |
189 | if (attrs) { | 175 | if (attrs) |
190 | /* | 176 | /* |
191 | * kernfs_node has non-default attributes get them from | 177 | * kernfs_node has non-default attributes get them from |
192 | * persistent copy in kernfs_node. | 178 | * persistent copy in kernfs_node. |
193 | */ | 179 | */ |
194 | set_inode_attr(inode, &attrs->ia_iattr); | 180 | set_inode_attr(inode, attrs); |
195 | security_inode_notifysecctx(inode, attrs->ia_secdata, | ||
196 | attrs->ia_secdata_len); | ||
197 | } | ||
198 | 181 | ||
199 | if (kernfs_type(kn) == KERNFS_DIR) | 182 | if (kernfs_type(kn) == KERNFS_DIR) |
200 | set_nlink(inode, kn->dir.subdirs + 2); | 183 | set_nlink(inode, kn->dir.subdirs + 2); |
@@ -305,78 +288,57 @@ int kernfs_iop_permission(struct inode *inode, int mask) | |||
305 | return generic_permission(inode, mask); | 288 | return generic_permission(inode, mask); |
306 | } | 289 | } |
307 | 290 | ||
308 | static int kernfs_xattr_get(const struct xattr_handler *handler, | 291 | int kernfs_xattr_get(struct kernfs_node *kn, const char *name, |
309 | struct dentry *unused, struct inode *inode, | 292 | void *value, size_t size) |
310 | const char *suffix, void *value, size_t size) | ||
311 | { | 293 | { |
312 | const char *name = xattr_full_name(handler, suffix); | 294 | struct kernfs_iattrs *attrs = kernfs_iattrs_noalloc(kn); |
313 | struct kernfs_node *kn = inode->i_private; | ||
314 | struct kernfs_iattrs *attrs; | ||
315 | |||
316 | attrs = kernfs_iattrs(kn); | ||
317 | if (!attrs) | 295 | if (!attrs) |
318 | return -ENOMEM; | 296 | return -ENODATA; |
319 | 297 | ||
320 | return simple_xattr_get(&attrs->xattrs, name, value, size); | 298 | return simple_xattr_get(&attrs->xattrs, name, value, size); |
321 | } | 299 | } |
322 | 300 | ||
323 | static int kernfs_xattr_set(const struct xattr_handler *handler, | 301 | int kernfs_xattr_set(struct kernfs_node *kn, const char *name, |
324 | struct dentry *unused, struct inode *inode, | 302 | const void *value, size_t size, int flags) |
325 | const char *suffix, const void *value, | ||
326 | size_t size, int flags) | ||
327 | { | 303 | { |
328 | const char *name = xattr_full_name(handler, suffix); | 304 | struct kernfs_iattrs *attrs = kernfs_iattrs(kn); |
329 | struct kernfs_node *kn = inode->i_private; | ||
330 | struct kernfs_iattrs *attrs; | ||
331 | |||
332 | attrs = kernfs_iattrs(kn); | ||
333 | if (!attrs) | 305 | if (!attrs) |
334 | return -ENOMEM; | 306 | return -ENOMEM; |
335 | 307 | ||
336 | return simple_xattr_set(&attrs->xattrs, name, value, size, flags); | 308 | return simple_xattr_set(&attrs->xattrs, name, value, size, flags); |
337 | } | 309 | } |
338 | 310 | ||
339 | static const struct xattr_handler kernfs_trusted_xattr_handler = { | 311 | static int kernfs_vfs_xattr_get(const struct xattr_handler *handler, |
340 | .prefix = XATTR_TRUSTED_PREFIX, | 312 | struct dentry *unused, struct inode *inode, |
341 | .get = kernfs_xattr_get, | 313 | const char *suffix, void *value, size_t size) |
342 | .set = kernfs_xattr_set, | ||
343 | }; | ||
344 | |||
345 | static int kernfs_security_xattr_set(const struct xattr_handler *handler, | ||
346 | struct dentry *unused, struct inode *inode, | ||
347 | const char *suffix, const void *value, | ||
348 | size_t size, int flags) | ||
349 | { | 314 | { |
315 | const char *name = xattr_full_name(handler, suffix); | ||
350 | struct kernfs_node *kn = inode->i_private; | 316 | struct kernfs_node *kn = inode->i_private; |
351 | struct kernfs_iattrs *attrs; | ||
352 | void *secdata; | ||
353 | u32 secdata_len = 0; | ||
354 | int error; | ||
355 | |||
356 | attrs = kernfs_iattrs(kn); | ||
357 | if (!attrs) | ||
358 | return -ENOMEM; | ||
359 | 317 | ||
360 | error = security_inode_setsecurity(inode, suffix, value, size, flags); | 318 | return kernfs_xattr_get(kn, name, value, size); |
361 | if (error) | 319 | } |
362 | return error; | ||
363 | error = security_inode_getsecctx(inode, &secdata, &secdata_len); | ||
364 | if (error) | ||
365 | return error; | ||
366 | 320 | ||
367 | mutex_lock(&kernfs_mutex); | 321 | static int kernfs_vfs_xattr_set(const struct xattr_handler *handler, |
368 | error = kernfs_node_setsecdata(attrs, &secdata, &secdata_len); | 322 | struct dentry *unused, struct inode *inode, |
369 | mutex_unlock(&kernfs_mutex); | 323 | const char *suffix, const void *value, |
324 | size_t size, int flags) | ||
325 | { | ||
326 | const char *name = xattr_full_name(handler, suffix); | ||
327 | struct kernfs_node *kn = inode->i_private; | ||
370 | 328 | ||
371 | if (secdata) | 329 | return kernfs_xattr_set(kn, name, value, size, flags); |
372 | security_release_secctx(secdata, secdata_len); | ||
373 | return error; | ||
374 | } | 330 | } |
375 | 331 | ||
332 | static const struct xattr_handler kernfs_trusted_xattr_handler = { | ||
333 | .prefix = XATTR_TRUSTED_PREFIX, | ||
334 | .get = kernfs_vfs_xattr_get, | ||
335 | .set = kernfs_vfs_xattr_set, | ||
336 | }; | ||
337 | |||
376 | static const struct xattr_handler kernfs_security_xattr_handler = { | 338 | static const struct xattr_handler kernfs_security_xattr_handler = { |
377 | .prefix = XATTR_SECURITY_PREFIX, | 339 | .prefix = XATTR_SECURITY_PREFIX, |
378 | .get = kernfs_xattr_get, | 340 | .get = kernfs_vfs_xattr_get, |
379 | .set = kernfs_security_xattr_set, | 341 | .set = kernfs_vfs_xattr_set, |
380 | }; | 342 | }; |
381 | 343 | ||
382 | const struct xattr_handler *kernfs_xattr_handlers[] = { | 344 | const struct xattr_handler *kernfs_xattr_handlers[] = { |