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; |
