Merge tag 'selinux-pr-20170831' of git://git.kernel.org/pub/scm/linux/kernel/git...
[sfrench/cifs-2.6.git] / security / selinux / hooks.c
index 33fd061305c40376c7f632ebcdf6fe5fd7b1e3fc..f5d304736852f98508144c23e7325068c6ae2ee8 100644 (file)
@@ -3,7 +3,7 @@
  *
  *  This file contains the SELinux hook function implementations.
  *
- *  Authors:  Stephen Smalley, <sds@epoch.ncsc.mil>
+ *  Authors:  Stephen Smalley, <sds@tycho.nsa.gov>
  *           Chris Vance, <cvance@nai.com>
  *           Wayne Salamon, <wsalamon@nai.com>
  *           James Morris <jmorris@redhat.com>
@@ -815,7 +815,9 @@ static int selinux_set_mnt_opts(struct super_block *sb,
        if (!strcmp(sb->s_type->name, "debugfs") ||
            !strcmp(sb->s_type->name, "tracefs") ||
            !strcmp(sb->s_type->name, "sysfs") ||
-           !strcmp(sb->s_type->name, "pstore"))
+           !strcmp(sb->s_type->name, "pstore") ||
+           !strcmp(sb->s_type->name, "cgroup") ||
+           !strcmp(sb->s_type->name, "cgroup2"))
                sbsec->flags |= SE_SBGENFS;
 
        if (!sbsec->behavior) {
@@ -1303,6 +1305,7 @@ static inline u16 socket_type_to_security_class(int family, int type, int protoc
                case SOCK_SEQPACKET:
                        return SECCLASS_UNIX_STREAM_SOCKET;
                case SOCK_DGRAM:
+               case SOCK_RAW:
                        return SECCLASS_UNIX_DGRAM_SOCKET;
                }
                break;
@@ -2317,6 +2320,7 @@ static int check_nnp_nosuid(const struct linux_binprm *bprm,
        int nnp = (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS);
        int nosuid = !mnt_may_suid(bprm->file->f_path.mnt);
        int rc;
+       u32 av;
 
        if (!nnp && !nosuid)
                return 0; /* neither NNP nor nosuid */
@@ -2325,24 +2329,40 @@ static int check_nnp_nosuid(const struct linux_binprm *bprm,
                return 0; /* No change in credentials */
 
        /*
-        * The only transitions we permit under NNP or nosuid
-        * are transitions to bounded SIDs, i.e. SIDs that are
-        * guaranteed to only be allowed a subset of the permissions
-        * of the current SID.
+        * If the policy enables the nnp_nosuid_transition policy capability,
+        * then we permit transitions under NNP or nosuid if the
+        * policy allows the corresponding permission between
+        * the old and new contexts.
         */
-       rc = security_bounded_transition(old_tsec->sid, new_tsec->sid);
-       if (rc) {
-               /*
-                * On failure, preserve the errno values for NNP vs nosuid.
-                * NNP:  Operation not permitted for caller.
-                * nosuid:  Permission denied to file.
-                */
+       if (selinux_policycap_nnp_nosuid_transition) {
+               av = 0;
                if (nnp)
-                       return -EPERM;
-               else
-                       return -EACCES;
+                       av |= PROCESS2__NNP_TRANSITION;
+               if (nosuid)
+                       av |= PROCESS2__NOSUID_TRANSITION;
+               rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
+                                 SECCLASS_PROCESS2, av, NULL);
+               if (!rc)
+                       return 0;
        }
-       return 0;
+
+       /*
+        * We also permit NNP or nosuid transitions to bounded SIDs,
+        * i.e. SIDs that are guaranteed to only be allowed a subset
+        * of the permissions of the current SID.
+        */
+       rc = security_bounded_transition(old_tsec->sid, new_tsec->sid);
+       if (!rc)
+               return 0;
+
+       /*
+        * On failure, preserve the errno values for NNP vs nosuid.
+        * NNP:  Operation not permitted for caller.
+        * nosuid:  Permission denied to file.
+        */
+       if (nnp)
+               return -EPERM;
+       return -EACCES;
 }
 
 static int selinux_bprm_set_creds(struct linux_binprm *bprm)
@@ -2356,7 +2376,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
 
        /* SELinux context only depends on initial program or script and not
         * the script interpreter */
-       if (bprm->cred_prepared)
+       if (bprm->called_set_creds)
                return 0;
 
        old_tsec = current_security();
@@ -2442,30 +2462,17 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
 
                /* Clear any possibly unsafe personality bits on exec: */
                bprm->per_clear |= PER_CLEAR_ON_SETID;
-       }
-
-       return 0;
-}
 
-static int selinux_bprm_secureexec(struct linux_binprm *bprm)
-{
-       const struct task_security_struct *tsec = current_security();
-       u32 sid, osid;
-       int atsecure = 0;
-
-       sid = tsec->sid;
-       osid = tsec->osid;
-
-       if (osid != sid) {
                /* Enable secure mode for SIDs transitions unless
                   the noatsecure permission is granted between
                   the two SIDs, i.e. ahp returns 0. */
-               atsecure = avc_has_perm(osid, sid,
-                                       SECCLASS_PROCESS,
-                                       PROCESS__NOATSECURE, NULL);
+               rc = avc_has_perm(old_tsec->sid, new_tsec->sid,
+                                 SECCLASS_PROCESS, PROCESS__NOATSECURE,
+                                 NULL);
+               bprm->secureexec |= !!rc;
        }
 
-       return !!atsecure;
+       return 0;
 }
 
 static int match_file(const void *p, struct file *file, unsigned fd)
@@ -6266,7 +6273,6 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
        LSM_HOOK_INIT(bprm_set_creds, selinux_bprm_set_creds),
        LSM_HOOK_INIT(bprm_committing_creds, selinux_bprm_committing_creds),
        LSM_HOOK_INIT(bprm_committed_creds, selinux_bprm_committed_creds),
-       LSM_HOOK_INIT(bprm_secureexec, selinux_bprm_secureexec),
 
        LSM_HOOK_INIT(sb_alloc_security, selinux_sb_alloc_security),
        LSM_HOOK_INIT(sb_free_security, selinux_sb_free_security),
@@ -6530,7 +6536,7 @@ security_initcall(selinux_init);
 
 #if defined(CONFIG_NETFILTER)
 
-static struct nf_hook_ops selinux_nf_ops[] = {
+static const struct nf_hook_ops selinux_nf_ops[] = {
        {
                .hook =         selinux_ipv4_postroute,
                .pf =           NFPROTO_IPV4,