Commit 83e804f0 authored by Mickaël Salaün's avatar Mickaël Salaün Committed by James Morris

fs,security: Add sb_delete hook

The sb_delete security hook is called when shutting down a superblock,
which may be useful to release kernel objects tied to the superblock's
lifetime (e.g. inodes).

This new hook is needed by Landlock to release (ephemerally) tagged
struct inodes.  This comes from the unprivileged nature of Landlock
described in the next commit.

Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: James Morris <jmorris@namei.org>
Signed-off-by: default avatarMickaël Salaün <mic@linux.microsoft.com>
Reviewed-by: default avatarJann Horn <jannh@google.com>
Acked-by: default avatarSerge Hallyn <serge@hallyn.com>
Reviewed-by: default avatarKees Cook <keescook@chromium.org>
Link: https://lore.kernel.org/r/20210422154123.13086-7-mic@digikod.netSigned-off-by: default avatarJames Morris <jamorris@linux.microsoft.com>
parent cb2c7d1a
...@@ -454,6 +454,7 @@ void generic_shutdown_super(struct super_block *sb) ...@@ -454,6 +454,7 @@ void generic_shutdown_super(struct super_block *sb)
evict_inodes(sb); evict_inodes(sb);
/* only nonzero refcount inodes can have marks */ /* only nonzero refcount inodes can have marks */
fsnotify_sb_delete(sb); fsnotify_sb_delete(sb);
security_sb_delete(sb);
if (sb->s_dio_done_wq) { if (sb->s_dio_done_wq) {
destroy_workqueue(sb->s_dio_done_wq); destroy_workqueue(sb->s_dio_done_wq);
......
...@@ -59,6 +59,7 @@ LSM_HOOK(int, 0, fs_context_dup, struct fs_context *fc, ...@@ -59,6 +59,7 @@ LSM_HOOK(int, 0, fs_context_dup, struct fs_context *fc,
LSM_HOOK(int, -ENOPARAM, fs_context_parse_param, struct fs_context *fc, LSM_HOOK(int, -ENOPARAM, fs_context_parse_param, struct fs_context *fc,
struct fs_parameter *param) struct fs_parameter *param)
LSM_HOOK(int, 0, sb_alloc_security, struct super_block *sb) LSM_HOOK(int, 0, sb_alloc_security, struct super_block *sb)
LSM_HOOK(void, LSM_RET_VOID, sb_delete, struct super_block *sb)
LSM_HOOK(void, LSM_RET_VOID, sb_free_security, struct super_block *sb) LSM_HOOK(void, LSM_RET_VOID, sb_free_security, struct super_block *sb)
LSM_HOOK(void, LSM_RET_VOID, sb_free_mnt_opts, void *mnt_opts) LSM_HOOK(void, LSM_RET_VOID, sb_free_mnt_opts, void *mnt_opts)
LSM_HOOK(int, 0, sb_eat_lsm_opts, char *orig, void **mnt_opts) LSM_HOOK(int, 0, sb_eat_lsm_opts, char *orig, void **mnt_opts)
......
...@@ -108,6 +108,9 @@ ...@@ -108,6 +108,9 @@
* allocated. * allocated.
* @sb contains the super_block structure to be modified. * @sb contains the super_block structure to be modified.
* Return 0 if operation was successful. * Return 0 if operation was successful.
* @sb_delete:
* Release objects tied to a superblock (e.g. inodes).
* @sb contains the super_block structure being released.
* @sb_free_security: * @sb_free_security:
* Deallocate and clear the sb->s_security field. * Deallocate and clear the sb->s_security field.
* @sb contains the super_block structure to be modified. * @sb contains the super_block structure to be modified.
......
...@@ -291,6 +291,7 @@ void security_bprm_committed_creds(struct linux_binprm *bprm); ...@@ -291,6 +291,7 @@ void security_bprm_committed_creds(struct linux_binprm *bprm);
int security_fs_context_dup(struct fs_context *fc, struct fs_context *src_fc); int security_fs_context_dup(struct fs_context *fc, struct fs_context *src_fc);
int security_fs_context_parse_param(struct fs_context *fc, struct fs_parameter *param); int security_fs_context_parse_param(struct fs_context *fc, struct fs_parameter *param);
int security_sb_alloc(struct super_block *sb); int security_sb_alloc(struct super_block *sb);
void security_sb_delete(struct super_block *sb);
void security_sb_free(struct super_block *sb); void security_sb_free(struct super_block *sb);
void security_free_mnt_opts(void **mnt_opts); void security_free_mnt_opts(void **mnt_opts);
int security_sb_eat_lsm_opts(char *options, void **mnt_opts); int security_sb_eat_lsm_opts(char *options, void **mnt_opts);
...@@ -631,6 +632,9 @@ static inline int security_sb_alloc(struct super_block *sb) ...@@ -631,6 +632,9 @@ static inline int security_sb_alloc(struct super_block *sb)
return 0; return 0;
} }
static inline void security_sb_delete(struct super_block *sb)
{ }
static inline void security_sb_free(struct super_block *sb) static inline void security_sb_free(struct super_block *sb)
{ } { }
......
...@@ -900,6 +900,11 @@ int security_sb_alloc(struct super_block *sb) ...@@ -900,6 +900,11 @@ int security_sb_alloc(struct super_block *sb)
return rc; return rc;
} }
void security_sb_delete(struct super_block *sb)
{
call_void_hook(sb_delete, sb);
}
void security_sb_free(struct super_block *sb) void security_sb_free(struct super_block *sb)
{ {
call_void_hook(sb_free_security, sb); call_void_hook(sb_free_security, sb);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment