The bprm->per_clear field only takes the values 0 and
PER_CLEAR_ON_SETID.  Reduce the field to a signle bit to make it clear
that the only question is should the dangerous personality bits be
cleared or not.

Update the documentation of the security lsm hooks.

Signed-off-by: "Eric W. Biederman" <ebied...@xmission.com>
---
 fs/exec.c                  | 7 ++++---
 include/linux/binfmts.h    | 4 +++-
 include/linux/lsm_hooks.h  | 4 ++++
 security/apparmor/domain.c | 2 +-
 security/commoncap.c       | 2 +-
 security/selinux/hooks.c   | 2 +-
 security/smack/smack_lsm.c | 2 +-
 7 files changed, 15 insertions(+), 8 deletions(-)

diff --git a/fs/exec.c b/fs/exec.c
index c3c879a55d65..51fab62b9fca 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1354,7 +1354,8 @@ int begin_new_exec(struct linux_binprm * bprm)
        me->flags &= ~(PF_RANDOMIZE | PF_FORKNOEXEC | PF_KTHREAD |
                                        PF_NOFREEZE | PF_NO_SETAFFINITY);
        flush_thread();
-       me->personality &= ~bprm->per_clear;
+       if (bprm->per_clear)
+               me->personality &= ~PER_CLEAR_ON_SETID;
 
        /*
         * We have to apply CLOEXEC before we change whether the process is
@@ -1628,12 +1629,12 @@ static void bprm_fill_uid(struct linux_binprm *bprm)
                return;
 
        if (mode & S_ISUID) {
-               bprm->per_clear |= PER_CLEAR_ON_SETID;
+               bprm->per_clear = 1;
                bprm->cred->euid = uid;
        }
 
        if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
-               bprm->per_clear |= PER_CLEAR_ON_SETID;
+               bprm->per_clear = 1;
                bprm->cred->egid = gid;
        }
 }
diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h
index 7fc05929c967..e7959a6a895a 100644
--- a/include/linux/binfmts.h
+++ b/include/linux/binfmts.h
@@ -26,6 +26,9 @@ struct linux_binprm {
        unsigned long p; /* current top of mem */
        unsigned long argmin; /* rlimit marker for copy_strings() */
        unsigned int
+               /* Should unsafe personality bits be cleared? */
+               per_clear:1,
+
                /* Should an execfd be passed to userspace? */
                have_execfd:1,
 
@@ -55,7 +58,6 @@ struct linux_binprm {
        struct file * file;
        struct cred *cred;      /* new credentials */
        int unsafe;             /* how unsafe this exec is (mask of 
LSM_UNSAFE_*) */
-       unsigned int per_clear; /* bits to clear in current->personality */
        int argc, envc;
        const char * filename;  /* Name of binary as seen by procps */
        const char * interp;    /* Name of the binary really executed. Most
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index d618ecc4d660..0ca68ad53592 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -42,6 +42,8 @@
  *     (e.g. for transitions between security domains).
  *     The hook must set @bprm->secureexec to 1 if AT_SECURE should be set to
  *     request libc enable secure mode.
+ *     The hook must set @bprm->per_clear to 1 if the dangerous personality
+ *     bits must be cleared from current->personality.
  *     @bprm contains the linux_binprm structure.
  *     Return 0 if the hook is successful and permission is granted.
  * @bprm_repopulate_creds:
@@ -55,6 +57,8 @@
  *     transitions between security domains).
  *     The hook must set @bprm->active_secureexec to 1 if AT_SECURE should be 
set to
  *     request libc enable secure mode.
+ *     The hook must set @bprm->per_clear to 1 if the dangerous personality
+ *     bits must be cleared from current->personality.
  *     @bprm contains the linux_binprm structure.
  *     Return 0 if the hook is successful and permission is granted.
  * @bprm_check_security:
diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
index 0b870a647488..c6d00735a40a 100644
--- a/security/apparmor/domain.c
+++ b/security/apparmor/domain.c
@@ -962,7 +962,7 @@ int apparmor_bprm_creds_for_exec(struct linux_binprm *bprm)
                        aa_label_printk(new, GFP_KERNEL);
                        dbg_printk("\n");
                }
-               bprm->per_clear |= PER_CLEAR_ON_SETID;
+               bprm->per_clear = 1;
        }
        aa_put_label(cred_label(bprm->cred));
        /* transfer reference, released when cred is freed */
diff --git a/security/commoncap.c b/security/commoncap.c
index 77b04cb6feac..48b556046483 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -826,7 +826,7 @@ int cap_bprm_repopulate_creds(struct linux_binprm *bprm)
 
        /* if we have fs caps, clear dangerous personality flags */
        if (__cap_gained(permitted, new, old))
-               bprm->per_clear |= PER_CLEAR_ON_SETID;
+               bprm->per_clear = 1;
 
        /* Don't let someone trace a set[ug]id/setpcap binary with the revised
         * credentials unless they have the appropriate permit.
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 718345dd76bb..6bea1b879fdb 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2385,7 +2385,7 @@ static int selinux_bprm_creds_for_exec(struct 
linux_binprm *bprm)
                }
 
                /* Clear any possibly unsafe personality bits on exec: */
-               bprm->per_clear |= PER_CLEAR_ON_SETID;
+               bprm->per_clear = 1;
 
                /* Enable secure mode for SIDs transitions unless
                   the noatsecure permission is granted between
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 0ac8f4518d07..a0d2fad27b33 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -933,7 +933,7 @@ static int smack_bprm_creds_for_exec(struct linux_binprm 
*bprm)
                return -EPERM;
 
        bsp->smk_task = isp->smk_task;
-       bprm->per_clear |= PER_CLEAR_ON_SETID;
+       bprm->per_clear = 1;
 
        /* Decide if this is a secure exec. */
        if (bsp->smk_task != bsp->smk_forked)
-- 
2.25.0

Reply via email to