diff options
-rw-r--r-- | fs/kernfs/inode.c | 48 | ||||
-rw-r--r-- | include/linux/kernfs.h | 15 | ||||
-rw-r--r-- | include/linux/lsm_hooks.h | 13 | ||||
-rw-r--r-- | include/linux/security.h | 9 | ||||
-rw-r--r-- | security/security.c | 6 |
5 files changed, 82 insertions, 9 deletions
diff --git a/fs/kernfs/inode.c b/fs/kernfs/inode.c index a365088caa3c..673ef598d97d 100644 --- a/fs/kernfs/inode.c +++ b/fs/kernfs/inode.c | |||
@@ -288,12 +288,11 @@ int kernfs_iop_permission(struct inode *inode, int mask) | |||
288 | return generic_permission(inode, mask); | 288 | return generic_permission(inode, mask); |
289 | } | 289 | } |
290 | 290 | ||
291 | static int kernfs_xattr_get(const struct xattr_handler *handler, | 291 | static int kernfs_node_xattr_get(const struct xattr_handler *handler, |
292 | struct dentry *unused, struct inode *inode, | 292 | struct kernfs_node *kn, const char *suffix, |
293 | const char *suffix, void *value, size_t size) | 293 | void *value, size_t size) |
294 | { | 294 | { |
295 | const char *name = xattr_full_name(handler, suffix); | 295 | const char *name = xattr_full_name(handler, suffix); |
296 | struct kernfs_node *kn = inode->i_private; | ||
297 | struct kernfs_iattrs *attrs; | 296 | struct kernfs_iattrs *attrs; |
298 | 297 | ||
299 | attrs = kernfs_iattrs_noalloc(kn); | 298 | attrs = kernfs_iattrs_noalloc(kn); |
@@ -303,13 +302,11 @@ static int kernfs_xattr_get(const struct xattr_handler *handler, | |||
303 | return simple_xattr_get(&attrs->xattrs, name, value, size); | 302 | return simple_xattr_get(&attrs->xattrs, name, value, size); |
304 | } | 303 | } |
305 | 304 | ||
306 | static int kernfs_xattr_set(const struct xattr_handler *handler, | 305 | static int kernfs_node_xattr_set(const struct xattr_handler *handler, |
307 | struct dentry *unused, struct inode *inode, | 306 | struct kernfs_node *kn, const char *suffix, |
308 | const char *suffix, const void *value, | 307 | const void *value, size_t size, int flags) |
309 | size_t size, int flags) | ||
310 | { | 308 | { |
311 | const char *name = xattr_full_name(handler, suffix); | 309 | const char *name = xattr_full_name(handler, suffix); |
312 | struct kernfs_node *kn = inode->i_private; | ||
313 | struct kernfs_iattrs *attrs; | 310 | struct kernfs_iattrs *attrs; |
314 | 311 | ||
315 | attrs = kernfs_iattrs(kn); | 312 | attrs = kernfs_iattrs(kn); |
@@ -319,6 +316,25 @@ static int kernfs_xattr_set(const struct xattr_handler *handler, | |||
319 | return simple_xattr_set(&attrs->xattrs, name, value, size, flags); | 316 | return simple_xattr_set(&attrs->xattrs, name, value, size, flags); |
320 | } | 317 | } |
321 | 318 | ||
319 | static int kernfs_xattr_get(const struct xattr_handler *handler, | ||
320 | struct dentry *unused, struct inode *inode, | ||
321 | const char *suffix, void *value, size_t size) | ||
322 | { | ||
323 | struct kernfs_node *kn = inode->i_private; | ||
324 | |||
325 | return kernfs_node_xattr_get(handler, kn, suffix, value, size); | ||
326 | } | ||
327 | |||
328 | static int kernfs_xattr_set(const struct xattr_handler *handler, | ||
329 | struct dentry *unused, struct inode *inode, | ||
330 | const char *suffix, const void *value, | ||
331 | size_t size, int flags) | ||
332 | { | ||
333 | struct kernfs_node *kn = inode->i_private; | ||
334 | |||
335 | return kernfs_node_xattr_set(handler, kn, suffix, value, size, flags); | ||
336 | } | ||
337 | |||
322 | static const struct xattr_handler kernfs_trusted_xattr_handler = { | 338 | static const struct xattr_handler kernfs_trusted_xattr_handler = { |
323 | .prefix = XATTR_TRUSTED_PREFIX, | 339 | .prefix = XATTR_TRUSTED_PREFIX, |
324 | .get = kernfs_xattr_get, | 340 | .get = kernfs_xattr_get, |
@@ -336,3 +352,17 @@ const struct xattr_handler *kernfs_xattr_handlers[] = { | |||
336 | &kernfs_security_xattr_handler, | 352 | &kernfs_security_xattr_handler, |
337 | NULL | 353 | NULL |
338 | }; | 354 | }; |
355 | |||
356 | int kernfs_security_xattr_get(struct kernfs_node *kn, const char *suffix, | ||
357 | void *value, size_t size) | ||
358 | { | ||
359 | return kernfs_node_xattr_get(&kernfs_security_xattr_handler, | ||
360 | kn, suffix, value, size); | ||
361 | } | ||
362 | |||
363 | int kernfs_security_xattr_set(struct kernfs_node *kn, const char *suffix, | ||
364 | void *value, size_t size, int flags) | ||
365 | { | ||
366 | return kernfs_node_xattr_set(&kernfs_security_xattr_handler, | ||
367 | kn, suffix, value, size, flags); | ||
368 | } | ||
diff --git a/include/linux/kernfs.h b/include/linux/kernfs.h index c8893f663470..39eea07c2900 100644 --- a/include/linux/kernfs.h +++ b/include/linux/kernfs.h | |||
@@ -371,6 +371,11 @@ __poll_t kernfs_generic_poll(struct kernfs_open_file *of, | |||
371 | struct poll_table_struct *pt); | 371 | struct poll_table_struct *pt); |
372 | void kernfs_notify(struct kernfs_node *kn); | 372 | void kernfs_notify(struct kernfs_node *kn); |
373 | 373 | ||
374 | int kernfs_security_xattr_get(struct kernfs_node *kn, const char *suffix, | ||
375 | void *value, size_t size); | ||
376 | int kernfs_security_xattr_set(struct kernfs_node *kn, const char *suffix, | ||
377 | void *value, size_t size, int flags); | ||
378 | |||
374 | const void *kernfs_super_ns(struct super_block *sb); | 379 | const void *kernfs_super_ns(struct super_block *sb); |
375 | int kernfs_get_tree(struct fs_context *fc); | 380 | int kernfs_get_tree(struct fs_context *fc); |
376 | void kernfs_free_fs_context(struct fs_context *fc); | 381 | void kernfs_free_fs_context(struct fs_context *fc); |
@@ -473,6 +478,16 @@ static inline int kernfs_setattr(struct kernfs_node *kn, | |||
473 | 478 | ||
474 | static inline void kernfs_notify(struct kernfs_node *kn) { } | 479 | static inline void kernfs_notify(struct kernfs_node *kn) { } |
475 | 480 | ||
481 | static inline int kernfs_security_xattr_get(struct kernfs_node *kn, | ||
482 | const char *suffix, void *value, | ||
483 | size_t size) | ||
484 | { return -ENOSYS; } | ||
485 | |||
486 | static inline int kernfs_security_xattr_set(struct kernfs_node *kn, | ||
487 | const char *suffix, void *value, | ||
488 | size_t size, int flags) | ||
489 | { return -ENOSYS; } | ||
490 | |||
476 | static inline const void *kernfs_super_ns(struct super_block *sb) | 491 | static inline const void *kernfs_super_ns(struct super_block *sb) |
477 | { return NULL; } | 492 | { return NULL; } |
478 | 493 | ||
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index a9b8ff578b6b..0dd5bda719e6 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h | |||
@@ -445,6 +445,15 @@ | |||
445 | * to abort the copy up. Note that the caller is responsible for reading | 445 | * to abort the copy up. Note that the caller is responsible for reading |
446 | * and writing the xattrs as this hook is merely a filter. | 446 | * and writing the xattrs as this hook is merely a filter. |
447 | * | 447 | * |
448 | * Security hooks for kernfs node operations | ||
449 | * | ||
450 | * @kernfs_init_security | ||
451 | * Initialize the security context of a newly created kernfs node based | ||
452 | * on its own and its parent's attributes. | ||
453 | * | ||
454 | * @kn_dir the parent kernfs node | ||
455 | * @kn the new child kernfs node | ||
456 | * | ||
448 | * Security hooks for file operations | 457 | * Security hooks for file operations |
449 | * | 458 | * |
450 | * @file_permission: | 459 | * @file_permission: |
@@ -1578,6 +1587,9 @@ union security_list_options { | |||
1578 | int (*inode_copy_up)(struct dentry *src, struct cred **new); | 1587 | int (*inode_copy_up)(struct dentry *src, struct cred **new); |
1579 | int (*inode_copy_up_xattr)(const char *name); | 1588 | int (*inode_copy_up_xattr)(const char *name); |
1580 | 1589 | ||
1590 | int (*kernfs_init_security)(struct kernfs_node *kn_dir, | ||
1591 | struct kernfs_node *kn); | ||
1592 | |||
1581 | int (*file_permission)(struct file *file, int mask); | 1593 | int (*file_permission)(struct file *file, int mask); |
1582 | int (*file_alloc_security)(struct file *file); | 1594 | int (*file_alloc_security)(struct file *file); |
1583 | void (*file_free_security)(struct file *file); | 1595 | void (*file_free_security)(struct file *file); |
@@ -1879,6 +1891,7 @@ struct security_hook_heads { | |||
1879 | struct hlist_head inode_getsecid; | 1891 | struct hlist_head inode_getsecid; |
1880 | struct hlist_head inode_copy_up; | 1892 | struct hlist_head inode_copy_up; |
1881 | struct hlist_head inode_copy_up_xattr; | 1893 | struct hlist_head inode_copy_up_xattr; |
1894 | struct hlist_head kernfs_init_security; | ||
1882 | struct hlist_head file_permission; | 1895 | struct hlist_head file_permission; |
1883 | struct hlist_head file_alloc_security; | 1896 | struct hlist_head file_alloc_security; |
1884 | struct hlist_head file_free_security; | 1897 | struct hlist_head file_free_security; |
diff --git a/include/linux/security.h b/include/linux/security.h index 49f2685324b0..d543293216b9 100644 --- a/include/linux/security.h +++ b/include/linux/security.h | |||
@@ -51,6 +51,7 @@ struct fown_struct; | |||
51 | struct file_operations; | 51 | struct file_operations; |
52 | struct msg_msg; | 52 | struct msg_msg; |
53 | struct xattr; | 53 | struct xattr; |
54 | struct kernfs_node; | ||
54 | struct xfrm_sec_ctx; | 55 | struct xfrm_sec_ctx; |
55 | struct mm_struct; | 56 | struct mm_struct; |
56 | struct fs_context; | 57 | struct fs_context; |
@@ -299,6 +300,8 @@ int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer | |||
299 | void security_inode_getsecid(struct inode *inode, u32 *secid); | 300 | void security_inode_getsecid(struct inode *inode, u32 *secid); |
300 | int security_inode_copy_up(struct dentry *src, struct cred **new); | 301 | int security_inode_copy_up(struct dentry *src, struct cred **new); |
301 | int security_inode_copy_up_xattr(const char *name); | 302 | int security_inode_copy_up_xattr(const char *name); |
303 | int security_kernfs_init_security(struct kernfs_node *kn_dir, | ||
304 | struct kernfs_node *kn); | ||
302 | int security_file_permission(struct file *file, int mask); | 305 | int security_file_permission(struct file *file, int mask); |
303 | int security_file_alloc(struct file *file); | 306 | int security_file_alloc(struct file *file); |
304 | void security_file_free(struct file *file); | 307 | void security_file_free(struct file *file); |
@@ -801,6 +804,12 @@ static inline int security_inode_copy_up(struct dentry *src, struct cred **new) | |||
801 | return 0; | 804 | return 0; |
802 | } | 805 | } |
803 | 806 | ||
807 | static inline int security_kernfs_init_security(struct kernfs_node *kn_dir, | ||
808 | struct kernfs_node *kn) | ||
809 | { | ||
810 | return 0; | ||
811 | } | ||
812 | |||
804 | static inline int security_inode_copy_up_xattr(const char *name) | 813 | static inline int security_inode_copy_up_xattr(const char *name) |
805 | { | 814 | { |
806 | return -EOPNOTSUPP; | 815 | return -EOPNOTSUPP; |
diff --git a/security/security.c b/security/security.c index 23cbb1a295a3..8d6ef9da94eb 100644 --- a/security/security.c +++ b/security/security.c | |||
@@ -1318,6 +1318,12 @@ int security_inode_copy_up_xattr(const char *name) | |||
1318 | } | 1318 | } |
1319 | EXPORT_SYMBOL(security_inode_copy_up_xattr); | 1319 | EXPORT_SYMBOL(security_inode_copy_up_xattr); |
1320 | 1320 | ||
1321 | int security_kernfs_init_security(struct kernfs_node *kn_dir, | ||
1322 | struct kernfs_node *kn) | ||
1323 | { | ||
1324 | return call_int_hook(kernfs_init_security, 0, kn_dir, kn); | ||
1325 | } | ||
1326 | |||
1321 | int security_file_permission(struct file *file, int mask) | 1327 | int security_file_permission(struct file *file, int mask) |
1322 | { | 1328 | { |
1323 | int ret; | 1329 | int ret; |