On 2/19/2021 8:25 AM, Olga Kornievskaia wrote: > On Thu, Feb 18, 2021 at 4:57 PM Casey Schaufler <casey@xxxxxxxxxxxxxxxx> wrote: >> On 2/18/2021 11:50 AM, Olga Kornievskaia wrote: >>> From: Olga Kornievskaia <kolga@xxxxxxxxxx> >>> >>> Add a new hook that takes an existing super block and a new mount >>> with new options and determines if new options confict with an >>> existing mount or not. >>> >>> Signed-off-by: Olga Kornievskaia <kolga@xxxxxxxxxx> >>> ` >>> --- >>> include/linux/lsm_hook_defs.h | 1 + >>> include/linux/lsm_hooks.h | 6 ++++ >>> include/linux/security.h | 8 ++++++ >>> security/security.c | 7 +++++ >>> security/selinux/hooks.c | 54 +++++++++++++++++++++++++++++++++++ >>> 5 files changed, 76 insertions(+) >>> >>> diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h >>> index 7aaa753b8608..1b12a5266a51 100644 >>> --- a/include/linux/lsm_hook_defs.h >>> +++ b/include/linux/lsm_hook_defs.h >>> @@ -62,6 +62,7 @@ LSM_HOOK(int, 0, sb_alloc_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(int, 0, sb_eat_lsm_opts, char *orig, void **mnt_opts) >>> +LSM_HOOK(int, 0, sb_mnt_opts_compat, struct super_block *sb, void *mnt_opts) >>> LSM_HOOK(int, 0, sb_remount, struct super_block *sb, void *mnt_opts) >>> LSM_HOOK(int, 0, sb_kern_mount, struct super_block *sb) >>> LSM_HOOK(int, 0, sb_show_options, struct seq_file *m, struct super_block *sb) >>> diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h >>> index a19adef1f088..77c1e9cdeaca 100644 >>> --- a/include/linux/lsm_hooks.h >>> +++ b/include/linux/lsm_hooks.h >>> @@ -142,6 +142,12 @@ >>> * @orig the original mount data copied from userspace. >>> * @copy copied data which will be passed to the security module. >>> * Returns 0 if the copy was successful. >>> + * @sb_mnt_opts_compat: >>> + * Determine if the existing mount options are compatible with the new >>> + * mount options being used. >>> + * @sb superblock being compared >>> + * @mnt_opts new mount options >>> + * Return 0 if options are the same. >> s/the same/compatible/ >> >>> * @sb_remount: >>> * Extracts security system specific mount options and verifies no changes >>> * are being made to those options. >>> diff --git a/include/linux/security.h b/include/linux/security.h >>> index c35ea0ffccd9..50db3d5d1608 100644 >>> --- a/include/linux/security.h >>> +++ b/include/linux/security.h >>> @@ -291,6 +291,7 @@ int security_sb_alloc(struct super_block *sb); >>> void security_sb_free(struct super_block *sb); >>> void security_free_mnt_opts(void **mnt_opts); >>> int security_sb_eat_lsm_opts(char *options, void **mnt_opts); >>> +int security_sb_mnt_opts_compat(struct super_block *sb, void *mnt_opts); >>> int security_sb_remount(struct super_block *sb, void *mnt_opts); >>> int security_sb_kern_mount(struct super_block *sb); >>> int security_sb_show_options(struct seq_file *m, struct super_block *sb); >>> @@ -635,6 +636,13 @@ static inline int security_sb_remount(struct super_block *sb, >>> return 0; >>> } >>> >>> +static inline int security_sb_mnt_opts_compat(struct super_block *sb, >>> + void *mnt_opts) >>> +{ >>> + return 0; >>> +} >>> + >>> + >>> static inline int security_sb_kern_mount(struct super_block *sb) >>> { >>> return 0; >>> diff --git a/security/security.c b/security/security.c >>> index 7b09cfbae94f..56cf5563efde 100644 >>> --- a/security/security.c >>> +++ b/security/security.c >>> @@ -890,6 +890,13 @@ int security_sb_eat_lsm_opts(char *options, void **mnt_opts) >>> } >>> EXPORT_SYMBOL(security_sb_eat_lsm_opts); >>> >>> +int security_sb_mnt_opts_compat(struct super_block *sb, >>> + void *mnt_opts) >>> +{ >>> + return call_int_hook(sb_mnt_opts_compat, 0, sb, mnt_opts); >>> +} >>> +EXPORT_SYMBOL(security_sb_mnt_opts_compat); >>> + >>> int security_sb_remount(struct super_block *sb, >>> void *mnt_opts) >>> { >>> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c >>> index 644b17ec9e63..f0b8ebc1e2c2 100644 >>> --- a/security/selinux/hooks.c >>> +++ b/security/selinux/hooks.c >>> @@ -2656,6 +2656,59 @@ static int selinux_sb_eat_lsm_opts(char *options, void **mnt_opts) >>> return rc; >>> } >>> >>> +static int selinux_sb_mnt_opts_compat(struct super_block *sb, void *mnt_opts) >>> +{ >>> + struct selinux_mnt_opts *opts = mnt_opts; >>> + struct superblock_security_struct *sbsec = sb->s_security; >>> + u32 sid; >>> + int rc; >>> + >>> + /* superblock not initialized (i.e. no options) - reject if any >> Please maintain the existing comment style used in this file. > I'm again not sure what exactly is the style used in this file and how > is this inconsistent? While not 100% consistent, the style used here has the "/*" alone on the first line with the text starting on the second line. /* * Like this * is done */ not /* Like this * is done */ > > Here's one example from this file: > /* Wake up the parent if it is waiting so that it can recheck > * wait permission to the new task SID. */ > this is another example from this file: > /* Check whether the new SID can inherit signal state from the old SID. > * If not, clear itimers to avoid subsequent signal generation and > * flush and unblock signals. > * > * This must occur _after_ the task SID has been updated so that any > * kill done after the flush will be checked against the new SID. > */ > Here's another: > /* strip quotes */ > > What exactly is not correct about the new comment? > /* superblock not initialized (i.e. no options) - reject if any > * options specified, otherwise accept > */ > It uses "/*" and has a space after. It starts each new line with "*" > and a space. And ends with a new line. This is consistent with the > general kernel style. Actually example 1 is not following kernel style > by not ending on the new line. > > Is the objection that it's perhaps not a sentence that starts with a > capital letter and ends with a period? Not all comments are sentences. > If so please specify. Otherwise, I'm just guessing what you are > expecting. > > >> /* >> * superblock not initialized (i.e. no options) - reject if any >> >>> + * options specified, otherwise accept >>> + */ >>> + if (!(sbsec->flags & SE_SBINITIALIZED)) >>> + return opts ? 1 : 0; >>> + >>> + /* superblock initialized and no options specified - reject if >>> + * superblock has any options set, otherwise accept >>> + */ >>> + if (!opts) >>> + return (sbsec->flags & SE_MNTMASK) ? 1 : 0; >>> + >>> + if (opts->fscontext) { >>> + rc = parse_sid(sb, opts->fscontext, &sid); >>> + if (rc) >>> + return 1; >>> + if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, sid)) >>> + return 1; >>> + } >>> + if (opts->context) { >>> + rc = parse_sid(sb, opts->context, &sid); >>> + if (rc) >>> + return 1; >>> + if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, sid)) >>> + return 1; >>> + } >>> + if (opts->rootcontext) { >>> + struct inode_security_struct *root_isec; >>> + >>> + root_isec = backing_inode_security(sb->s_root); >>> + rc = parse_sid(sb, opts->rootcontext, &sid); >>> + if (rc) >>> + return 1; >>> + if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, sid)) >>> + return 1; >>> + } >>> + if (opts->defcontext) { >>> + rc = parse_sid(sb, opts->defcontext, &sid); >>> + if (rc) >>> + return 1; >>> + if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, sid)) >>> + return 1; >>> + } >>> + return 0; >>> +} >>> + >>> static int selinux_sb_remount(struct super_block *sb, void *mnt_opts) >>> { >>> struct selinux_mnt_opts *opts = mnt_opts; >>> @@ -6984,6 +7037,7 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = { >>> >>> LSM_HOOK_INIT(sb_free_security, selinux_sb_free_security), >>> LSM_HOOK_INIT(sb_free_mnt_opts, selinux_free_mnt_opts), >>> + LSM_HOOK_INIT(sb_mnt_opts_compat, selinux_sb_mnt_opts_compat), >>> LSM_HOOK_INIT(sb_remount, selinux_sb_remount), >>> LSM_HOOK_INIT(sb_kern_mount, selinux_sb_kern_mount), >>> LSM_HOOK_INIT(sb_show_options, selinux_sb_show_options),