Message ID | 20230831104136.903180-15-roberto.sassu@huaweicloud.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | security: Move IMA and EVM to the LSM infrastructure | expand |
On 8/31/2023 3:41 AM, Roberto Sassu wrote: > From: Roberto Sassu <roberto.sassu@huawei.com> > > In preparation to move IMA and EVM to the LSM infrastructure, introduce the > file_post_open hook. Also, export security_file_post_open() for NFS. Repeat of new LSM hook general comment: Would you please include some explanation of how an LSM would use this hook? You might start with a description of how it is used in IMA/EVM, and why that could be generally useful. > > Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com> > Reviewed-by: Stefan Berger <stefanb@linux.ibm.com> > --- > fs/namei.c | 2 ++ > fs/nfsd/vfs.c | 6 ++++++ > include/linux/lsm_hook_defs.h | 1 + > include/linux/security.h | 6 ++++++ > security/security.c | 17 +++++++++++++++++ > 5 files changed, 32 insertions(+) > > diff --git a/fs/namei.c b/fs/namei.c > index 1f5ec71360de..7dc4626859f0 100644 > --- a/fs/namei.c > +++ b/fs/namei.c > @@ -3634,6 +3634,8 @@ static int do_open(struct nameidata *nd, > error = may_open(idmap, &nd->path, acc_mode, open_flag); > if (!error && !(file->f_mode & FMODE_OPENED)) > error = vfs_open(&nd->path, file); > + if (!error) > + error = security_file_post_open(file, op->acc_mode); > if (!error) > error = ima_file_check(file, op->acc_mode); > if (!error && do_truncate) > diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c > index 8a2321d19194..3450bb1c8a18 100644 > --- a/fs/nfsd/vfs.c > +++ b/fs/nfsd/vfs.c > @@ -862,6 +862,12 @@ __nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, > goto out_nfserr; > } > > + host_err = security_file_post_open(file, may_flags); > + if (host_err) { > + fput(file); > + goto out_nfserr; > + } > + > host_err = ima_file_check(file, may_flags); > if (host_err) { > fput(file); > diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h > index 1153e7163b8b..60ed33f0c80d 100644 > --- a/include/linux/lsm_hook_defs.h > +++ b/include/linux/lsm_hook_defs.h > @@ -188,6 +188,7 @@ LSM_HOOK(int, 0, file_send_sigiotask, struct task_struct *tsk, > struct fown_struct *fown, int sig) > LSM_HOOK(int, 0, file_receive, struct file *file) > LSM_HOOK(int, 0, file_open, struct file *file) > +LSM_HOOK(int, 0, file_post_open, struct file *file, int mask) > LSM_HOOK(int, 0, file_truncate, struct file *file) > LSM_HOOK(int, 0, task_alloc, struct task_struct *task, > unsigned long clone_flags) > diff --git a/include/linux/security.h b/include/linux/security.h > index 665bba3e0081..a0f16511c059 100644 > --- a/include/linux/security.h > +++ b/include/linux/security.h > @@ -403,6 +403,7 @@ int security_file_send_sigiotask(struct task_struct *tsk, > struct fown_struct *fown, int sig); > int security_file_receive(struct file *file); > int security_file_open(struct file *file); > +int security_file_post_open(struct file *file, int mask); > int security_file_truncate(struct file *file); > int security_task_alloc(struct task_struct *task, unsigned long clone_flags); > void security_task_free(struct task_struct *task); > @@ -1044,6 +1045,11 @@ static inline int security_file_open(struct file *file) > return 0; > } > > +static inline int security_file_post_open(struct file *file, int mask) > +{ > + return 0; > +} > + > static inline int security_file_truncate(struct file *file) > { > return 0; > diff --git a/security/security.c b/security/security.c > index 3947159ba5e9..3e0078b51e46 100644 > --- a/security/security.c > +++ b/security/security.c > @@ -2856,6 +2856,23 @@ int security_file_open(struct file *file) > return fsnotify_perm(file, MAY_OPEN); > } > > +/** > + * security_file_post_open() - Recheck access to a file after it has been opened > + * @file: the file > + * @mask: access mask > + * > + * Recheck access with mask after the file has been opened. The hook is useful > + * for LSMs that require the file content to be available in order to make > + * decisions. > + * > + * Return: Returns 0 if permission is granted. > + */ > +int security_file_post_open(struct file *file, int mask) > +{ > + return call_int_hook(file_post_open, 0, file, mask); > +} > +EXPORT_SYMBOL_GPL(security_file_post_open); > + > /** > * security_file_truncate() - Check if truncating a file is allowed > * @file: file
diff --git a/fs/namei.c b/fs/namei.c index 1f5ec71360de..7dc4626859f0 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -3634,6 +3634,8 @@ static int do_open(struct nameidata *nd, error = may_open(idmap, &nd->path, acc_mode, open_flag); if (!error && !(file->f_mode & FMODE_OPENED)) error = vfs_open(&nd->path, file); + if (!error) + error = security_file_post_open(file, op->acc_mode); if (!error) error = ima_file_check(file, op->acc_mode); if (!error && do_truncate) diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 8a2321d19194..3450bb1c8a18 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -862,6 +862,12 @@ __nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, goto out_nfserr; } + host_err = security_file_post_open(file, may_flags); + if (host_err) { + fput(file); + goto out_nfserr; + } + host_err = ima_file_check(file, may_flags); if (host_err) { fput(file); diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h index 1153e7163b8b..60ed33f0c80d 100644 --- a/include/linux/lsm_hook_defs.h +++ b/include/linux/lsm_hook_defs.h @@ -188,6 +188,7 @@ LSM_HOOK(int, 0, file_send_sigiotask, struct task_struct *tsk, struct fown_struct *fown, int sig) LSM_HOOK(int, 0, file_receive, struct file *file) LSM_HOOK(int, 0, file_open, struct file *file) +LSM_HOOK(int, 0, file_post_open, struct file *file, int mask) LSM_HOOK(int, 0, file_truncate, struct file *file) LSM_HOOK(int, 0, task_alloc, struct task_struct *task, unsigned long clone_flags) diff --git a/include/linux/security.h b/include/linux/security.h index 665bba3e0081..a0f16511c059 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -403,6 +403,7 @@ int security_file_send_sigiotask(struct task_struct *tsk, struct fown_struct *fown, int sig); int security_file_receive(struct file *file); int security_file_open(struct file *file); +int security_file_post_open(struct file *file, int mask); int security_file_truncate(struct file *file); int security_task_alloc(struct task_struct *task, unsigned long clone_flags); void security_task_free(struct task_struct *task); @@ -1044,6 +1045,11 @@ static inline int security_file_open(struct file *file) return 0; } +static inline int security_file_post_open(struct file *file, int mask) +{ + return 0; +} + static inline int security_file_truncate(struct file *file) { return 0; diff --git a/security/security.c b/security/security.c index 3947159ba5e9..3e0078b51e46 100644 --- a/security/security.c +++ b/security/security.c @@ -2856,6 +2856,23 @@ int security_file_open(struct file *file) return fsnotify_perm(file, MAY_OPEN); } +/** + * security_file_post_open() - Recheck access to a file after it has been opened + * @file: the file + * @mask: access mask + * + * Recheck access with mask after the file has been opened. The hook is useful + * for LSMs that require the file content to be available in order to make + * decisions. + * + * Return: Returns 0 if permission is granted. + */ +int security_file_post_open(struct file *file, int mask) +{ + return call_int_hook(file_post_open, 0, file, mask); +} +EXPORT_SYMBOL_GPL(security_file_post_open); + /** * security_file_truncate() - Check if truncating a file is allowed * @file: file