diff mbox

[v4a,8/8] module: replace the existing LSM hook in init_module

Message ID 1527780226.3427.20.camel@linux.vnet.ibm.com (mailing list archive)
State New, archived
Headers show

Commit Message

Mimi Zohar May 31, 2018, 3:23 p.m. UTC
Both the init_module and finit_module syscalls call either directly
or indirectly the security_kernel_read_file LSM hook.  This patch
replaces the direct call in init_module with a call to the new
security_kernel_load_data hook and makes the corresponding changes
in SELinux, LoadPin, and IMA.

Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
Cc: Jeff Vander Stoep <jeffv@google.com>
Cc: Paul Moore <paul@paul-moore.com>
Cc: Casey Schaufler <casey@schaufler-ca.com>
Cc: Kees Cook <keescook@chromium.org>

---
Changelog:
- For SELinux, have both the security_kernel_read_file and
security_kernel_load_data LSM hooks call selinux_kernel_read_file().
- LoadPin: replace existing init_module LSM hook support with
new security_kernel_load_data hook.

 kernel/module.c                   |  2 +-
 security/integrity/ima/ima_main.c | 24 ++++++++++--------------
 security/loadpin/loadpin.c        | 15 +++++++++++++++
 security/selinux/hooks.c          | 15 +++++++++++++++
 4 files changed, 41 insertions(+), 15 deletions(-)

Comments

Paul Moore June 1, 2018, 10:28 p.m. UTC | #1
On Thu, May 31, 2018 at 11:23 AM, Mimi Zohar <zohar@linux.vnet.ibm.com> wrote:
> Both the init_module and finit_module syscalls call either directly
> or indirectly the security_kernel_read_file LSM hook.  This patch
> replaces the direct call in init_module with a call to the new
> security_kernel_load_data hook and makes the corresponding changes
> in SELinux, LoadPin, and IMA.
>
> Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
> Cc: Jeff Vander Stoep <jeffv@google.com>
> Cc: Paul Moore <paul@paul-moore.com>
> Cc: Casey Schaufler <casey@schaufler-ca.com>
> Cc: Kees Cook <keescook@chromium.org>
>
> ---
> Changelog:
> - For SELinux, have both the security_kernel_read_file and
> security_kernel_load_data LSM hooks call selinux_kernel_read_file().
> - LoadPin: replace existing init_module LSM hook support with
> new security_kernel_load_data hook.
>
>  kernel/module.c                   |  2 +-
>  security/integrity/ima/ima_main.c | 24 ++++++++++--------------
>  security/loadpin/loadpin.c        | 15 +++++++++++++++
>  security/selinux/hooks.c          | 15 +++++++++++++++
>  4 files changed, 41 insertions(+), 15 deletions(-)

As mentioned in the previous iteration, I have no strong opinion on
the question of the LSM hooks, but the SELinux bits look okay to me.

Acked-by: Paul Moore <paul@paul-moore.com>

> diff --git a/kernel/module.c b/kernel/module.c
> index ce8066b88178..b97c642b5b4d 100644
> --- a/kernel/module.c
> +++ b/kernel/module.c
> @@ -2879,7 +2879,7 @@ static int copy_module_from_user(const void __user *umod, unsigned long len,
>         if (info->len < sizeof(*(info->hdr)))
>                 return -ENOEXEC;
>
> -       err = security_kernel_read_file(NULL, READING_MODULE);
> +       err = security_kernel_load_data(LOADING_MODULE);
>         if (err)
>                 return err;
>
> diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
> index 5a7696152982..cd33a2eff496 100644
> --- a/security/integrity/ima/ima_main.c
> +++ b/security/integrity/ima/ima_main.c
> @@ -438,17 +438,6 @@ static int read_idmap[READING_MAX_ID] = {
>   */
>  int ima_read_file(struct file *file, enum kernel_read_file_id read_id)
>  {
> -       bool sig_enforce = is_module_sig_enforced();
> -
> -       if (!file && read_id == READING_MODULE) {
> -               if (!sig_enforce && (ima_appraise & IMA_APPRAISE_MODULES) &&
> -                   (ima_appraise & IMA_APPRAISE_ENFORCE)) {
> -                       pr_err("impossible to appraise a module without a file descriptor. sig_enforce kernel parameter might help\n");
> -                       return -EACCES; /* INTEGRITY_UNKNOWN */
> -               }
> -               return 0;       /* We rely on module signature checking */
> -       }
> -
>         if (read_id == READING_FIRMWARE_PREALLOC_BUFFER) {
>                 if ((ima_appraise & IMA_APPRAISE_FIRMWARE) &&
>                     (ima_appraise & IMA_APPRAISE_ENFORCE)) {
> @@ -487,9 +476,6 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size,
>                 return 0;
>         }
>
> -       if (!file && read_id == READING_MODULE) /* MODULE_SIG_FORCE enabled */
> -               return 0;
> -
>         /* permit signed certs */
>         if (!file && read_id == READING_X509_CERTIFICATE)
>                 return 0;
> @@ -518,6 +504,8 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size,
>   */
>  int ima_load_data(enum kernel_load_data_id id)
>  {
> +       bool sig_enforce;
> +
>         if ((ima_appraise & IMA_APPRAISE_ENFORCE) != IMA_APPRAISE_ENFORCE)
>                 return 0;
>
> @@ -533,6 +521,14 @@ int ima_load_data(enum kernel_load_data_id id)
>                         pr_err("Prevent firmware sysfs fallback loading.\n");
>                         return -EACCES; /* INTEGRITY_UNKNOWN */
>                 }
> +               break;
> +       case LOADING_MODULE:
> +               sig_enforce = is_module_sig_enforced();
> +
> +               if (!sig_enforce && (ima_appraise & IMA_APPRAISE_MODULES)) {
> +                       pr_err("impossible to appraise a module without a file descriptor. sig_enforce kernel parameter might help\n");
> +                       return -EACCES; /* INTEGRITY_UNKNOWN */
> +               }
>         default:
>                 break;
>         }
> diff --git a/security/loadpin/loadpin.c b/security/loadpin/loadpin.c
> index 5fa191252c8f..a9c07bfbc338 100644
> --- a/security/loadpin/loadpin.c
> +++ b/security/loadpin/loadpin.c
> @@ -173,9 +173,24 @@ static int loadpin_read_file(struct file *file, enum kernel_read_file_id id)
>         return 0;
>  }
>
> +static int loadpin_load_data(enum kernel_load_data_id id)
> +{
> +       int rc = 0;
> +
> +       switch (id) {
> +       case LOADING_MODULE:
> +               rc = loadpin_read_file(NULL, READING_MODULE);
> +       default:
> +               break;
> +       }
> +
> +       return rc;
> +}
> +
>  static struct security_hook_list loadpin_hooks[] __lsm_ro_after_init = {
>         LSM_HOOK_INIT(sb_free_security, loadpin_sb_free_security),
>         LSM_HOOK_INIT(kernel_read_file, loadpin_read_file),
> +       LSM_HOOK_INIT(kernel_load_data, loadpin_load_data),
>  };
>
>  void __init loadpin_add_hooks(void)
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index 02ebd1585eaf..475aed9ee2c7 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -4059,6 +4059,20 @@ static int selinux_kernel_read_file(struct file *file,
>         return rc;
>  }
>
> +static int selinux_kernel_load_data(enum kernel_load_data_id id)
> +{
> +       int rc = 0;
> +
> +       switch (id) {
> +       case LOADING_MODULE:
> +               rc = selinux_kernel_module_from_file(NULL);
> +       default:
> +               break;
> +       }
> +
> +       return rc;
> +}
> +
>  static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
>  {
>         return avc_has_perm(&selinux_state,
> @@ -6950,6 +6964,7 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
>         LSM_HOOK_INIT(kernel_act_as, selinux_kernel_act_as),
>         LSM_HOOK_INIT(kernel_create_files_as, selinux_kernel_create_files_as),
>         LSM_HOOK_INIT(kernel_module_request, selinux_kernel_module_request),
> +       LSM_HOOK_INIT(kernel_load_data, selinux_kernel_load_data),
>         LSM_HOOK_INIT(kernel_read_file, selinux_kernel_read_file),
>         LSM_HOOK_INIT(task_setpgid, selinux_task_setpgid),
>         LSM_HOOK_INIT(task_getpgid, selinux_task_getpgid),
> --
> 2.7.5
>
Jessica Yu June 4, 2018, 9:19 a.m. UTC | #2
+++ Mimi Zohar [31/05/18 11:23 -0400]:
>Both the init_module and finit_module syscalls call either directly
>or indirectly the security_kernel_read_file LSM hook.  This patch
>replaces the direct call in init_module with a call to the new
>security_kernel_load_data hook and makes the corresponding changes
>in SELinux, LoadPin, and IMA.
>
>Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
>Cc: Jeff Vander Stoep <jeffv@google.com>
>Cc: Paul Moore <paul@paul-moore.com>
>Cc: Casey Schaufler <casey@schaufler-ca.com>
>Cc: Kees Cook <keescook@chromium.org>

For the module.c parts:

Acked-by: Jessica Yu <jeyu@kernel.org>

>Changelog:
>- For SELinux, have both the security_kernel_read_file and
>security_kernel_load_data LSM hooks call selinux_kernel_read_file().
>- LoadPin: replace existing init_module LSM hook support with
>new security_kernel_load_data hook.
>
> kernel/module.c                   |  2 +-
> security/integrity/ima/ima_main.c | 24 ++++++++++--------------
> security/loadpin/loadpin.c        | 15 +++++++++++++++
> security/selinux/hooks.c          | 15 +++++++++++++++
> 4 files changed, 41 insertions(+), 15 deletions(-)
>
>diff --git a/kernel/module.c b/kernel/module.c
>index ce8066b88178..b97c642b5b4d 100644
>--- a/kernel/module.c
>+++ b/kernel/module.c
>@@ -2879,7 +2879,7 @@ static int copy_module_from_user(const void __user *umod, unsigned long len,
> 	if (info->len < sizeof(*(info->hdr)))
> 		return -ENOEXEC;
>
>-	err = security_kernel_read_file(NULL, READING_MODULE);
>+	err = security_kernel_load_data(LOADING_MODULE);
> 	if (err)
> 		return err;
>
>diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
>index 5a7696152982..cd33a2eff496 100644
>--- a/security/integrity/ima/ima_main.c
>+++ b/security/integrity/ima/ima_main.c
>@@ -438,17 +438,6 @@ static int read_idmap[READING_MAX_ID] = {
>  */
> int ima_read_file(struct file *file, enum kernel_read_file_id read_id)
> {
>-	bool sig_enforce = is_module_sig_enforced();
>-
>-	if (!file && read_id == READING_MODULE) {
>-		if (!sig_enforce && (ima_appraise & IMA_APPRAISE_MODULES) &&
>-		    (ima_appraise & IMA_APPRAISE_ENFORCE)) {
>-			pr_err("impossible to appraise a module without a file descriptor. sig_enforce kernel parameter might help\n");
>-			return -EACCES;	/* INTEGRITY_UNKNOWN */
>-		}
>-		return 0;	/* We rely on module signature checking */
>-	}
>-
> 	if (read_id == READING_FIRMWARE_PREALLOC_BUFFER) {
> 		if ((ima_appraise & IMA_APPRAISE_FIRMWARE) &&
> 		    (ima_appraise & IMA_APPRAISE_ENFORCE)) {
>@@ -487,9 +476,6 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size,
> 		return 0;
> 	}
>
>-	if (!file && read_id == READING_MODULE) /* MODULE_SIG_FORCE enabled */
>-		return 0;
>-
> 	/* permit signed certs */
> 	if (!file && read_id == READING_X509_CERTIFICATE)
> 		return 0;
>@@ -518,6 +504,8 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size,
>  */
> int ima_load_data(enum kernel_load_data_id id)
> {
>+	bool sig_enforce;
>+
> 	if ((ima_appraise & IMA_APPRAISE_ENFORCE) != IMA_APPRAISE_ENFORCE)
> 		return 0;
>
>@@ -533,6 +521,14 @@ int ima_load_data(enum kernel_load_data_id id)
> 			pr_err("Prevent firmware sysfs fallback loading.\n");
> 			return -EACCES;	/* INTEGRITY_UNKNOWN */
> 		}
>+		break;
>+	case LOADING_MODULE:
>+		sig_enforce = is_module_sig_enforced();
>+
>+		if (!sig_enforce && (ima_appraise & IMA_APPRAISE_MODULES)) {
>+			pr_err("impossible to appraise a module without a file descriptor. sig_enforce kernel parameter might help\n");
>+			return -EACCES;	/* INTEGRITY_UNKNOWN */
>+		}
> 	default:
> 		break;
> 	}
>diff --git a/security/loadpin/loadpin.c b/security/loadpin/loadpin.c
>index 5fa191252c8f..a9c07bfbc338 100644
>--- a/security/loadpin/loadpin.c
>+++ b/security/loadpin/loadpin.c
>@@ -173,9 +173,24 @@ static int loadpin_read_file(struct file *file, enum kernel_read_file_id id)
> 	return 0;
> }
>
>+static int loadpin_load_data(enum kernel_load_data_id id)
>+{
>+	int rc = 0;
>+
>+	switch (id) {
>+	case LOADING_MODULE:
>+		rc = loadpin_read_file(NULL, READING_MODULE);
>+	default:
>+		break;
>+	}
>+
>+	return rc;
>+}
>+
> static struct security_hook_list loadpin_hooks[] __lsm_ro_after_init = {
> 	LSM_HOOK_INIT(sb_free_security, loadpin_sb_free_security),
> 	LSM_HOOK_INIT(kernel_read_file, loadpin_read_file),
>+	LSM_HOOK_INIT(kernel_load_data, loadpin_load_data),
> };
>
> void __init loadpin_add_hooks(void)
>diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
>index 02ebd1585eaf..475aed9ee2c7 100644
>--- a/security/selinux/hooks.c
>+++ b/security/selinux/hooks.c
>@@ -4059,6 +4059,20 @@ static int selinux_kernel_read_file(struct file *file,
> 	return rc;
> }
>
>+static int selinux_kernel_load_data(enum kernel_load_data_id id)
>+{
>+	int rc = 0;
>+
>+	switch (id) {
>+	case LOADING_MODULE:
>+		rc = selinux_kernel_module_from_file(NULL);
>+	default:
>+		break;
>+	}
>+
>+	return rc;
>+}
>+
> static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
> {
> 	return avc_has_perm(&selinux_state,
>@@ -6950,6 +6964,7 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
> 	LSM_HOOK_INIT(kernel_act_as, selinux_kernel_act_as),
> 	LSM_HOOK_INIT(kernel_create_files_as, selinux_kernel_create_files_as),
> 	LSM_HOOK_INIT(kernel_module_request, selinux_kernel_module_request),
>+	LSM_HOOK_INIT(kernel_load_data, selinux_kernel_load_data),
> 	LSM_HOOK_INIT(kernel_read_file, selinux_kernel_read_file),
> 	LSM_HOOK_INIT(task_setpgid, selinux_task_setpgid),
> 	LSM_HOOK_INIT(task_getpgid, selinux_task_getpgid),
>-- 
>2.7.5
>
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Kees Cook June 5, 2018, 7:45 p.m. UTC | #3
On Thu, May 31, 2018 at 8:23 AM, Mimi Zohar <zohar@linux.vnet.ibm.com> wrote:
> diff --git a/security/loadpin/loadpin.c b/security/loadpin/loadpin.c
> index 5fa191252c8f..a9c07bfbc338 100644
> --- a/security/loadpin/loadpin.c
> +++ b/security/loadpin/loadpin.c
> @@ -173,9 +173,24 @@ static int loadpin_read_file(struct file *file, enum kernel_read_file_id id)
>         return 0;
>  }
>
> +static int loadpin_load_data(enum kernel_load_data_id id)
> +{
> +       int rc = 0;
> +
> +       switch (id) {
> +       case LOADING_MODULE:
> +               rc = loadpin_read_file(NULL, READING_MODULE);
> +       default:
> +               break;
> +       }
> +
> +       return rc;
> +}

Is it worth keeping the same enum between the two hooks? That would
simplify this a bit since it could just pass the id without remapping.

And if you must have a separate enum, please change this to fail
closed instead of open (and mark the fall-through):

int rc = -EPERM;

switch (id) {
case LOADING_MODULE:
    rc = loadpin_read_file(NULL, READING_MODULE);
    /* Fall-through */
default:
    break;
}

Thanks!

-Kees

> +
>  static struct security_hook_list loadpin_hooks[] __lsm_ro_after_init = {
>         LSM_HOOK_INIT(sb_free_security, loadpin_sb_free_security),
>         LSM_HOOK_INIT(kernel_read_file, loadpin_read_file),
> +       LSM_HOOK_INIT(kernel_load_data, loadpin_load_data),
>  };
>
>  void __init loadpin_add_hooks(void)
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index 02ebd1585eaf..475aed9ee2c7 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -4059,6 +4059,20 @@ static int selinux_kernel_read_file(struct file *file,
>         return rc;
>  }
>
> +static int selinux_kernel_load_data(enum kernel_load_data_id id)
> +{
> +       int rc = 0;
> +
> +       switch (id) {
> +       case LOADING_MODULE:
> +               rc = selinux_kernel_module_from_file(NULL);
> +       default:
> +               break;
> +       }
> +
> +       return rc;
> +}
> +
>  static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
>  {
>         return avc_has_perm(&selinux_state,
> @@ -6950,6 +6964,7 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
>         LSM_HOOK_INIT(kernel_act_as, selinux_kernel_act_as),
>         LSM_HOOK_INIT(kernel_create_files_as, selinux_kernel_create_files_as),
>         LSM_HOOK_INIT(kernel_module_request, selinux_kernel_module_request),
> +       LSM_HOOK_INIT(kernel_load_data, selinux_kernel_load_data),
>         LSM_HOOK_INIT(kernel_read_file, selinux_kernel_read_file),
>         LSM_HOOK_INIT(task_setpgid, selinux_task_setpgid),
>         LSM_HOOK_INIT(task_getpgid, selinux_task_getpgid),
> --
> 2.7.5
>
Mimi Zohar June 5, 2018, 9:35 p.m. UTC | #4
On Tue, 2018-06-05 at 12:45 -0700, Kees Cook wrote:

> And if you must have a separate enum, please change this to fail
> closed instead of open (and mark the fall-through):
> 
> int rc = -EPERM;
> 
> switch (id) {
> case LOADING_MODULE:
>     rc = loadpin_read_file(NULL, READING_MODULE);
>     /* Fall-through */
> default:
>     break;
> }

This will fail the sysfs firmware fallback loading and the kexec_load
syscall without any message, as you have for init_module.  Is that
what you want?

Mimi

 

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Kees Cook June 5, 2018, 10:26 p.m. UTC | #5
On Tue, Jun 5, 2018 at 2:35 PM, Mimi Zohar <zohar@linux.vnet.ibm.com> wrote:
> On Tue, 2018-06-05 at 12:45 -0700, Kees Cook wrote:
>
>> And if you must have a separate enum, please change this to fail
>> closed instead of open (and mark the fall-through):
>>
>> int rc = -EPERM;
>>
>> switch (id) {
>> case LOADING_MODULE:
>>     rc = loadpin_read_file(NULL, READING_MODULE);
>>     /* Fall-through */
>> default:
>>     break;
>> }
>
> This will fail the sysfs firmware fallback loading and the kexec_load
> syscall without any message, as you have for init_module.  Is that
> what you want?

I'd prefer there be a full mapping of the enums so that everything
gets passed into loadpin_read_file() :)

Can the enum be shared or is that nonsensical?

-Kees
Mimi Zohar June 5, 2018, 10:40 p.m. UTC | #6
On Tue, 2018-06-05 at 15:26 -0700, Kees Cook wrote:
> On Tue, Jun 5, 2018 at 2:35 PM, Mimi Zohar <zohar@linux.vnet.ibm.com> wrote:
> > On Tue, 2018-06-05 at 12:45 -0700, Kees Cook wrote:
> >
> >> And if you must have a separate enum, please change this to fail
> >> closed instead of open (and mark the fall-through):
> >>
> >> int rc = -EPERM;
> >>
> >> switch (id) {
> >> case LOADING_MODULE:
> >>     rc = loadpin_read_file(NULL, READING_MODULE);
> >>     /* Fall-through */
> >> default:
> >>     break;
> >> }
> >
> > This will fail the sysfs firmware fallback loading and the kexec_load
> > syscall without any message, as you have for init_module.  Is that
> > what you want?
> 
> I'd prefer there be a full mapping of the enums so that everything
> gets passed into loadpin_read_file() :)
> 
> Can the enum be shared or is that nonsensical?

Considering this is v4 of the patch set, it's pretty obvious I did
everything possible not to define a new LSM hook.  Even if we can't
re-use the existing enum, we could define the new enum in terms
of __kernel_read_file_id.

enum kernel_load_data_id {
        __kernel_read_file_id(__data_id_enumify)
};

static const char * const kernel_load_data_str[] = {
        __kernel_read_file_id(__data_id_stringify)
};

Eric, Serge, would using either the existing __kernel_read_file_id
enum or the above definitions be acceptable?

Mimi

--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/kernel/module.c b/kernel/module.c
index ce8066b88178..b97c642b5b4d 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -2879,7 +2879,7 @@  static int copy_module_from_user(const void __user *umod, unsigned long len,
 	if (info->len < sizeof(*(info->hdr)))
 		return -ENOEXEC;
 
-	err = security_kernel_read_file(NULL, READING_MODULE);
+	err = security_kernel_load_data(LOADING_MODULE);
 	if (err)
 		return err;
 
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 5a7696152982..cd33a2eff496 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -438,17 +438,6 @@  static int read_idmap[READING_MAX_ID] = {
  */
 int ima_read_file(struct file *file, enum kernel_read_file_id read_id)
 {
-	bool sig_enforce = is_module_sig_enforced();
-
-	if (!file && read_id == READING_MODULE) {
-		if (!sig_enforce && (ima_appraise & IMA_APPRAISE_MODULES) &&
-		    (ima_appraise & IMA_APPRAISE_ENFORCE)) {
-			pr_err("impossible to appraise a module without a file descriptor. sig_enforce kernel parameter might help\n");
-			return -EACCES;	/* INTEGRITY_UNKNOWN */
-		}
-		return 0;	/* We rely on module signature checking */
-	}
-
 	if (read_id == READING_FIRMWARE_PREALLOC_BUFFER) {
 		if ((ima_appraise & IMA_APPRAISE_FIRMWARE) &&
 		    (ima_appraise & IMA_APPRAISE_ENFORCE)) {
@@ -487,9 +476,6 @@  int ima_post_read_file(struct file *file, void *buf, loff_t size,
 		return 0;
 	}
 
-	if (!file && read_id == READING_MODULE) /* MODULE_SIG_FORCE enabled */
-		return 0;
-
 	/* permit signed certs */
 	if (!file && read_id == READING_X509_CERTIFICATE)
 		return 0;
@@ -518,6 +504,8 @@  int ima_post_read_file(struct file *file, void *buf, loff_t size,
  */
 int ima_load_data(enum kernel_load_data_id id)
 {
+	bool sig_enforce;
+
 	if ((ima_appraise & IMA_APPRAISE_ENFORCE) != IMA_APPRAISE_ENFORCE)
 		return 0;
 
@@ -533,6 +521,14 @@  int ima_load_data(enum kernel_load_data_id id)
 			pr_err("Prevent firmware sysfs fallback loading.\n");
 			return -EACCES;	/* INTEGRITY_UNKNOWN */
 		}
+		break;
+	case LOADING_MODULE:
+		sig_enforce = is_module_sig_enforced();
+
+		if (!sig_enforce && (ima_appraise & IMA_APPRAISE_MODULES)) {
+			pr_err("impossible to appraise a module without a file descriptor. sig_enforce kernel parameter might help\n");
+			return -EACCES;	/* INTEGRITY_UNKNOWN */
+		}
 	default:
 		break;
 	}
diff --git a/security/loadpin/loadpin.c b/security/loadpin/loadpin.c
index 5fa191252c8f..a9c07bfbc338 100644
--- a/security/loadpin/loadpin.c
+++ b/security/loadpin/loadpin.c
@@ -173,9 +173,24 @@  static int loadpin_read_file(struct file *file, enum kernel_read_file_id id)
 	return 0;
 }
 
+static int loadpin_load_data(enum kernel_load_data_id id)
+{
+	int rc = 0;
+
+	switch (id) {
+	case LOADING_MODULE:
+		rc = loadpin_read_file(NULL, READING_MODULE);
+	default:
+		break;
+	}
+
+	return rc;
+}
+
 static struct security_hook_list loadpin_hooks[] __lsm_ro_after_init = {
 	LSM_HOOK_INIT(sb_free_security, loadpin_sb_free_security),
 	LSM_HOOK_INIT(kernel_read_file, loadpin_read_file),
+	LSM_HOOK_INIT(kernel_load_data, loadpin_load_data),
 };
 
 void __init loadpin_add_hooks(void)
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 02ebd1585eaf..475aed9ee2c7 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4059,6 +4059,20 @@  static int selinux_kernel_read_file(struct file *file,
 	return rc;
 }
 
+static int selinux_kernel_load_data(enum kernel_load_data_id id)
+{
+	int rc = 0;
+
+	switch (id) {
+	case LOADING_MODULE:
+		rc = selinux_kernel_module_from_file(NULL);
+	default:
+		break;
+	}
+
+	return rc;
+}
+
 static int selinux_task_setpgid(struct task_struct *p, pid_t pgid)
 {
 	return avc_has_perm(&selinux_state,
@@ -6950,6 +6964,7 @@  static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
 	LSM_HOOK_INIT(kernel_act_as, selinux_kernel_act_as),
 	LSM_HOOK_INIT(kernel_create_files_as, selinux_kernel_create_files_as),
 	LSM_HOOK_INIT(kernel_module_request, selinux_kernel_module_request),
+	LSM_HOOK_INIT(kernel_load_data, selinux_kernel_load_data),
 	LSM_HOOK_INIT(kernel_read_file, selinux_kernel_read_file),
 	LSM_HOOK_INIT(task_setpgid, selinux_task_setpgid),
 	LSM_HOOK_INIT(task_getpgid, selinux_task_getpgid),