Re: [PATCH v2] selinux: add permission checks for loading other kinds of kernel files

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, Feb 17, 2025 at 3:58 PM Christian Göttsche
<cgzones@xxxxxxxxxxxxxx> wrote:
>
> On Tue, 11 Feb 2025 at 19:22, <kippndavis.work@xxxxxxx> wrote:
> >
> > From: "Kipp N. Davis" <kippndavis.work@xxxxxxx>
> >
> > Although the LSM hooks for loading kernel modules were later generalized
> > to cover loading other kinds of files, SELinux didn't implement
> > corresponding permission checks, leaving only the module case covered.
> > Define and add new permission checks for these other cases.
> >
> > Signed-off-by: Cameron K. Williams <ckwilliams.work@xxxxxxxxx>
> > Signed-off-by: Kipp N. Davis <kippndavis.work@xxxxxxx>
> >
> > ---
> > Changes in v2:
> >   - Removed the `-EACCES` return in default case in
> >     selinux_kernel_read_file() and selinux_kernel_load_from_file(),
> >     reverting previous fallback behavior.
> >   - Added a compile-time check in these functions to catch new
> >     READING/LOADING_XXX entries.
> >
> > Thanks for your review! I've adjusted the default case so as to not
> > return an error and depart from pre-existing logic. I first tried to use
> > the pre-processor #errors but failed with the READING/LOADING_MAX_ID
> > enums, so I opted for BUILD_BUG_ON_MSG as a compile-time check with
> > those same enums instead to catch new entries.
> > ---
> >  security/selinux/hooks.c            | 56 +++++++++++++++++++++++------
> >  security/selinux/include/classmap.h |  4 ++-
> >  2 files changed, 49 insertions(+), 11 deletions(-)
> >
> > diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> > index 7b867dfec88b..67bf37693cd7 100644
> > --- a/security/selinux/hooks.c
> > +++ b/security/selinux/hooks.c
> > @@ -4096,7 +4096,7 @@ static int selinux_kernel_module_request(char *kmod_name)
> >                             SYSTEM__MODULE_REQUEST, &ad);
> >  }
> >
> > -static int selinux_kernel_module_from_file(struct file *file)
> > +static int selinux_kernel_load_from_file(struct file *file, u32 requested)
> >  {
> >         struct common_audit_data ad;
> >         struct inode_security_struct *isec;
> > @@ -4104,12 +4104,9 @@ static int selinux_kernel_module_from_file(struct file *file)
> >         u32 sid = current_sid();
> >         int rc;
> >
> > -       /* init_module */
> >         if (file == NULL)
> >                 return avc_has_perm(sid, sid, SECCLASS_SYSTEM,
> > -                                       SYSTEM__MODULE_LOAD, NULL);
> > -
> > -       /* finit_module */
> > +                                       requested, NULL);
> >
> >         ad.type = LSM_AUDIT_DATA_FILE;
> >         ad.u.file = file;
> > @@ -4123,7 +4120,7 @@ static int selinux_kernel_module_from_file(struct file *file)
> >
> >         isec = inode_security(file_inode(file));
> >         return avc_has_perm(sid, isec->sid, SECCLASS_SYSTEM,
> > -                               SYSTEM__MODULE_LOAD, &ad);
> > +                               requested, &ad);
> >  }
> >
> >  static int selinux_kernel_read_file(struct file *file,
> > @@ -4131,10 +4128,32 @@ static int selinux_kernel_read_file(struct file *file,
> >                                     bool contents)
> >  {
> >         int rc = 0;
> > -
> > +       BUILD_BUG_ON_MSG(READING_MAX_ID > 7,
> > +                 "New kernel_read_file_id introduced; update SELinux!");
> >         switch (id) {
>
> Should READING_UNKNOWN be handled?
> It seems not to be used currently in-tree, but maybe stay on the safe side?

IMHO, no. READING_UNKNOWN/LOADING_UNKNOWN aren't intended to be used
and would be a bug elsewhere in the kernel.

>
> > +       case READING_FIRMWARE:
> > +               rc = selinux_kernel_load_from_file(contents ? file : NULL,
> > +                               SYSTEM__FIRMWARE_LOAD);
> > +               break;
> >         case READING_MODULE:
> > -               rc = selinux_kernel_module_from_file(contents ? file : NULL);
> > +               rc = selinux_kernel_load_from_file(contents ? file : NULL,
> > +                               SYSTEM__MODULE_LOAD);
> > +               break;
> > +       case READING_KEXEC_IMAGE:
> > +               rc = selinux_kernel_load_from_file(contents ? file : NULL,
> > +                               SYSTEM__KEXEC_IMAGE_LOAD);
> > +               break;
> > +       case READING_KEXEC_INITRAMFS:
> > +               rc = selinux_kernel_load_from_file(contents ? file : NULL,
> > +                               SYSTEM__KEXEC_INITRAMFS_LOAD);
> > +               break;
> > +       case READING_POLICY:
> > +               rc = selinux_kernel_load_from_file(contents ? file : NULL,
> > +                               SYSTEM__POLICY_LOAD);
> > +               break;
> > +       case READING_X509_CERTIFICATE:
> > +               rc = selinux_kernel_load_from_file(contents ? file : NULL,
> > +                               SYSTEM__X509_CERTIFICATE_LOAD);
> >                 break;
> >         default:
> >                 break;
> > @@ -4146,10 +4165,27 @@ static int selinux_kernel_read_file(struct file *file,
> >  static int selinux_kernel_load_data(enum kernel_load_data_id id, bool contents)
> >  {
> >         int rc = 0;
> > -
> > +       BUILD_BUG_ON_MSG(LOADING_MAX_ID > 7,
> > +        "New kernel_load_data_id introduced; update SELinux!");
> >         switch (id) {
>
> dito
>
> > +       case LOADING_FIRMWARE:
> > +               rc = selinux_kernel_load_from_file(NULL, SYSTEM__FIRMWARE_LOAD);
> > +               break;
> >         case LOADING_MODULE:
> > -               rc = selinux_kernel_module_from_file(NULL);
> > +               rc = selinux_kernel_load_from_file(NULL, SYSTEM__MODULE_LOAD);
> > +               break;
> > +       case LOADING_KEXEC_IMAGE:
> > +               rc = selinux_kernel_load_from_file(NULL, SYSTEM__KEXEC_IMAGE_LOAD);
> > +               break;
> > +       case LOADING_KEXEC_INITRAMFS:
> > +               rc = selinux_kernel_load_from_file(NULL, SYSTEM__KEXEC_INITRAMFS_LOAD);
> > +               break;
> > +       case LOADING_POLICY:
> > +               rc = selinux_kernel_load_from_file(NULL, SYSTEM__POLICY_LOAD);
> > +               break;
> > +       case LOADING_X509_CERTIFICATE:
> > +               rc = selinux_kernel_load_from_file(NULL,
> > +                               SYSTEM__X509_CERTIFICATE_LOAD);
> >                 break;
> >         default:
> >                 break;
> > diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h
> > index 03e82477dce9..cfac41d12f7d 100644
> > --- a/security/selinux/include/classmap.h
> > +++ b/security/selinux/include/classmap.h
> > @@ -63,7 +63,9 @@ const struct security_class_mapping secclass_map[] = {
> >         { "process2", { "nnp_transition", "nosuid_transition", NULL } },
> >         { "system",
> >           { "ipc_info", "syslog_read", "syslog_mod", "syslog_console",
> > -           "module_request", "module_load", NULL } },
> > +           "module_request", "module_load", "firmware_load",
> > +           "kexec_image_load", "kexec_initramfs_load", "policy_load",
>
> In the SELinux world the word "policy" refers mostly to the SELinux policy.
> Maybe rename the permission verb "policy_load" to
> "security_policy_load" or similar? (it seems to be used by IMA,
> loadpin and zram currently)

I don't really see how that is less ambiguous since SELinux policy is
a security policy too, but don't have any strong feelings either way.
We have the load_policy permission in the security class for loading
SELinux policy, so if we use security_policy_load here, then we'll end
up with SECURITY__LOAD_POLICY and SYSTEM__SECURITY_LOAD_POLICY.
What could go wrong?

>
> > +           "x509_certificate_load", NULL } },
> >         { "capability", { COMMON_CAP_PERMS, NULL } },
> >         { "filesystem",
> >           { "mount", "remount", "unmount", "getattr", "relabelfrom",
> > --
> > 2.48.1
> >
> >





[Index of Archives]     [Selinux Refpolicy]     [Linux SGX]     [Fedora Users]     [Fedora Desktop]     [Yosemite Photos]     [Yosemite Camping]     [Yosemite Campsites]     [KDE Users]     [Gnome Users]

  Powered by Linux