]> Git Repo - linux.git/commitdiff
Merge git://git.infradead.org/users/eparis/selinux
authorPaul Moore <[email protected]>
Wed, 18 Sep 2013 17:52:20 +0000 (13:52 -0400)
committerPaul Moore <[email protected]>
Wed, 18 Sep 2013 17:52:20 +0000 (13:52 -0400)
Conflicts:
security/selinux/hooks.c

Pull Eric's existing SELinux tree as there are a number of patches in
there that are not yet upstream.  There was some minor fixup needed to
resolve a conflict in security/selinux/hooks.c:selinux_set_mnt_opts()
between the labeled NFS patches and Eric's security_fs_use()
simplification patch.

1  2 
include/linux/security.h
security/capability.c
security/security.c
security/selinux/hooks.c
security/selinux/include/security.h
security/selinux/ss/policydb.c

diff --combined include/linux/security.h
index 7ce53ae1266bf04c0305f8b695dc240818a7d4ca,e5a5e8a41e5597d8095726daaf8c12994a879aaf..8d23951a3805668959542ce02a339dca41c207cd
@@@ -26,7 -26,6 +26,7 @@@
  #include <linux/capability.h>
  #include <linux/slab.h>
  #include <linux/err.h>
 +#include <linux/string.h>
  
  struct linux_binprm;
  struct cred;
@@@ -61,9 -60,6 +61,9 @@@ struct mm_struct
  #define SECURITY_CAP_NOAUDIT 0
  #define SECURITY_CAP_AUDIT 1
  
 +/* LSM Agnostic defines for sb_set_mnt_opts */
 +#define SECURITY_LSM_NATIVE_LABELS    1
 +
  struct ctl_table;
  struct audit_krule;
  struct user_namespace;
@@@ -310,15 -306,6 +310,15 @@@ static inline void security_free_mnt_op
   *    Parse a string of security data filling in the opts structure
   *    @options string containing all mount options known by the LSM
   *    @opts binary data structure usable by the LSM
 + * @dentry_init_security:
 + *    Compute a context for a dentry as the inode is not yet available
 + *    since NFSv4 has no label backed by an EA anyway.
 + *    @dentry dentry to use in calculating the context.
 + *    @mode mode used to determine resource type.
 + *    @name name of the last path component used to create file
 + *    @ctx pointer to place the pointer to the resulting context in.
 + *    @ctxlen point to place the length of the resulting context.
 + *
   *
   * Security hooks for inode operations.
   *
   * @xfrm_policy_delete_security:
   *    @ctx contains the xfrm_sec_ctx.
   *    Authorize deletion of xp->security.
-  * @xfrm_state_alloc_security:
+  * @xfrm_state_alloc:
   *    @x contains the xfrm_state being added to the Security Association
   *    Database by the XFRM system.
   *    @sec_ctx contains the security context information being provided by
   *    the user-level SA generation program (e.g., setkey or racoon).
-  *    @secid contains the secid from which to take the mls portion of the context.
   *    Allocate a security structure to the x->security field; the security
   *    field is initialized to NULL when the xfrm_state is allocated. Set the
-  *    context to correspond to either sec_ctx or polsec, with the mls portion
-  *    taken from secid in the latter case.
-  *    Return 0 if operation was successful (memory to allocate, legal context).
+  *    context to correspond to sec_ctx. Return 0 if operation was successful
+  *    (memory to allocate, legal context).
+  * @xfrm_state_alloc_acquire:
+  *    @x contains the xfrm_state being added to the Security Association
+  *    Database by the XFRM system.
+  *    @polsec contains the policy's security context.
+  *    @secid contains the secid from which to take the mls portion of the
+  *    context.
+  *    Allocate a security structure to the x->security field; the security
+  *    field is initialized to NULL when the xfrm_state is allocated. Set the
+  *    context to correspond to secid. Return 0 if operation was successful
+  *    (memory to allocate, legal context).
   * @xfrm_state_free_security:
   *    @x contains the xfrm_state.
   *    Deallocate x->security.
   *    @pages contains the number of pages.
   *    Return 0 if permission is granted.
   *
 + * @ismaclabel:
 + *    Check if the extended attribute specified by @name
 + *    represents a MAC label. Returns 1 if name is a MAC
 + *    attribute otherwise returns 0.
 + *    @name full extended attribute name to check against
 + *    LSM as a MAC label.
 + *
   * @secid_to_secctx:
   *    Convert secid to security context.  If secdata is NULL the length of
   *    the result will be returned in seclen, but no secdata will be returned.
   *    @ctxlen contains the length of @ctx.
   *
   * @inode_getsecctx:
 - *    Returns a string containing all relevant security context information
 + *    On success, returns 0 and fills out @ctx and @ctxlen with the security
 + *    context for the given @inode.
   *
   *    @inode we wish to get the security context of.
   *    @ctx is a pointer in which to place the allocated security context.
@@@ -1460,16 -1447,10 +1468,16 @@@ struct security_operations 
        int (*sb_pivotroot) (struct path *old_path,
                             struct path *new_path);
        int (*sb_set_mnt_opts) (struct super_block *sb,
 -                              struct security_mnt_opts *opts);
 +                              struct security_mnt_opts *opts,
 +                              unsigned long kern_flags,
 +                              unsigned long *set_kern_flags);
        int (*sb_clone_mnt_opts) (const struct super_block *oldsb,
                                   struct super_block *newsb);
        int (*sb_parse_opts_str) (char *options, struct security_mnt_opts *opts);
 +      int (*dentry_init_security) (struct dentry *dentry, int mode,
 +                                      struct qstr *name, void **ctx,
 +                                      u32 *ctxlen);
 +
  
  #ifdef CONFIG_SECURITY_PATH
        int (*path_unlink) (struct path *dir, struct dentry *dentry);
  
        int (*getprocattr) (struct task_struct *p, char *name, char **value);
        int (*setprocattr) (struct task_struct *p, char *name, void *value, size_t size);
 +      int (*ismaclabel) (const char *name);
        int (*secid_to_secctx) (u32 secid, char **secdata, u32 *seclen);
        int (*secctx_to_secid) (const char *secdata, u32 seclen, u32 *secid);
        void (*release_secctx) (char *secdata, u32 seclen);
        int (*xfrm_policy_clone_security) (struct xfrm_sec_ctx *old_ctx, struct xfrm_sec_ctx **new_ctx);
        void (*xfrm_policy_free_security) (struct xfrm_sec_ctx *ctx);
        int (*xfrm_policy_delete_security) (struct xfrm_sec_ctx *ctx);
-       int (*xfrm_state_alloc_security) (struct xfrm_state *x,
-               struct xfrm_user_sec_ctx *sec_ctx,
-               u32 secid);
+       int (*xfrm_state_alloc) (struct xfrm_state *x,
+                                struct xfrm_user_sec_ctx *sec_ctx);
+       int (*xfrm_state_alloc_acquire) (struct xfrm_state *x,
+                                        struct xfrm_sec_ctx *polsec,
+                                        u32 secid);
        void (*xfrm_state_free_security) (struct xfrm_state *x);
        int (*xfrm_state_delete_security) (struct xfrm_state *x);
        int (*xfrm_policy_lookup) (struct xfrm_sec_ctx *ctx, u32 fl_secid, u8 dir);
@@@ -1753,16 -1735,10 +1763,16 @@@ int security_sb_mount(const char *dev_n
                      const char *type, unsigned long flags, void *data);
  int security_sb_umount(struct vfsmount *mnt, int flags);
  int security_sb_pivotroot(struct path *old_path, struct path *new_path);
 -int security_sb_set_mnt_opts(struct super_block *sb, struct security_mnt_opts *opts);
 +int security_sb_set_mnt_opts(struct super_block *sb,
 +                              struct security_mnt_opts *opts,
 +                              unsigned long kern_flags,
 +                              unsigned long *set_kern_flags);
  int security_sb_clone_mnt_opts(const struct super_block *oldsb,
                                struct super_block *newsb);
  int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts);
 +int security_dentry_init_security(struct dentry *dentry, int mode,
 +                                      struct qstr *name, void **ctx,
 +                                      u32 *ctxlen);
  
  int security_inode_alloc(struct inode *inode);
  void security_inode_free(struct inode *inode);
@@@ -1874,7 -1850,6 +1884,7 @@@ void security_d_instantiate(struct dent
  int security_getprocattr(struct task_struct *p, char *name, char **value);
  int security_setprocattr(struct task_struct *p, char *name, void *value, size_t size);
  int security_netlink_send(struct sock *sk, struct sk_buff *skb);
 +int security_ismaclabel(const char *name);
  int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen);
  int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid);
  void security_release_secctx(char *secdata, u32 seclen);
@@@ -2046,9 -2021,7 +2056,9 @@@ static inline int security_sb_pivotroot
  }
  
  static inline int security_sb_set_mnt_opts(struct super_block *sb,
 -                                         struct security_mnt_opts *opts)
 +                                         struct security_mnt_opts *opts,
 +                                         unsigned long kern_flags,
 +                                         unsigned long *set_kern_flags)
  {
        return 0;
  }
@@@ -2072,16 -2045,6 +2082,16 @@@ static inline int security_inode_alloc(
  static inline void security_inode_free(struct inode *inode)
  { }
  
 +static inline int security_dentry_init_security(struct dentry *dentry,
 +                                               int mode,
 +                                               struct qstr *name,
 +                                               void **ctx,
 +                                               u32 *ctxlen)
 +{
 +      return -EOPNOTSUPP;
 +}
 +
 +
  static inline int security_inode_init_security(struct inode *inode,
                                                struct inode *dir,
                                                const struct qstr *qstr,
@@@ -2567,11 -2530,6 +2577,11 @@@ static inline int security_netlink_send
        return cap_netlink_send(sk, skb);
  }
  
 +static inline int security_ismaclabel(const char *name)
 +{
 +      return 0;
 +}
 +
  static inline int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
  {
        return -EOPNOTSUPP;
diff --combined security/capability.c
index 32b515766df17c984c6a1c56c86fa67dba4ee25d,67afc679719afe438b04610fd2418ca00dce8934..b6d779b6aa25864e99557a77bbe2f06856d1f5ea
@@@ -91,10 -91,7 +91,10 @@@ static int cap_sb_pivotroot(struct pat
  }
  
  static int cap_sb_set_mnt_opts(struct super_block *sb,
 -                             struct security_mnt_opts *opts)
 +                             struct security_mnt_opts *opts,
 +                             unsigned long kern_flags,
 +                             unsigned long *set_kern_flags)
 +
  {
        if (unlikely(opts->num_mnt_opts))
                return -EOPNOTSUPP;
@@@ -112,13 -109,6 +112,13 @@@ static int cap_sb_parse_opts_str(char *
        return 0;
  }
  
 +static int cap_dentry_init_security(struct dentry *dentry, int mode,
 +                                      struct qstr *name, void **ctx,
 +                                      u32 *ctxlen)
 +{
 +      return 0;
 +}
 +
  static int cap_inode_alloc_security(struct inode *inode)
  {
        return 0;
@@@ -777,9 -767,15 +777,15 @@@ static int cap_xfrm_policy_delete_secur
        return 0;
  }
  
- static int cap_xfrm_state_alloc_security(struct xfrm_state *x,
-                                        struct xfrm_user_sec_ctx *sec_ctx,
-                                        u32 secid)
+ static int cap_xfrm_state_alloc(struct xfrm_state *x,
+                               struct xfrm_user_sec_ctx *sec_ctx)
+ {
+       return 0;
+ }
+ static int cap_xfrm_state_alloc_acquire(struct xfrm_state *x,
+                                       struct xfrm_sec_ctx *polsec,
+                                       u32 secid)
  {
        return 0;
  }
@@@ -826,11 -822,6 +832,11 @@@ static int cap_setprocattr(struct task_
        return -EINVAL;
  }
  
 +static int cap_ismaclabel(const char *name)
 +{
 +      return 0;
 +}
 +
  static int cap_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
  {
        return -EOPNOTSUPP;
@@@ -858,7 -849,7 +864,7 @@@ static int cap_inode_setsecctx(struct d
  
  static int cap_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
  {
 -      return 0;
 +      return -EOPNOTSUPP;
  }
  #ifdef CONFIG_KEYS
  static int cap_key_alloc(struct key *key, const struct cred *cred,
@@@ -946,7 -937,6 +952,7 @@@ void __init security_fixup_ops(struct s
        set_to_cap_if_null(ops, sb_set_mnt_opts);
        set_to_cap_if_null(ops, sb_clone_mnt_opts);
        set_to_cap_if_null(ops, sb_parse_opts_str);
 +      set_to_cap_if_null(ops, dentry_init_security);
        set_to_cap_if_null(ops, inode_alloc_security);
        set_to_cap_if_null(ops, inode_free_security);
        set_to_cap_if_null(ops, inode_init_security);
        set_to_cap_if_null(ops, d_instantiate);
        set_to_cap_if_null(ops, getprocattr);
        set_to_cap_if_null(ops, setprocattr);
 +      set_to_cap_if_null(ops, ismaclabel);
        set_to_cap_if_null(ops, secid_to_secctx);
        set_to_cap_if_null(ops, secctx_to_secid);
        set_to_cap_if_null(ops, release_secctx);
        set_to_cap_if_null(ops, xfrm_policy_clone_security);
        set_to_cap_if_null(ops, xfrm_policy_free_security);
        set_to_cap_if_null(ops, xfrm_policy_delete_security);
-       set_to_cap_if_null(ops, xfrm_state_alloc_security);
+       set_to_cap_if_null(ops, xfrm_state_alloc);
+       set_to_cap_if_null(ops, xfrm_state_alloc_acquire);
        set_to_cap_if_null(ops, xfrm_state_free_security);
        set_to_cap_if_null(ops, xfrm_state_delete_security);
        set_to_cap_if_null(ops, xfrm_policy_lookup);
diff --combined security/security.c
index 94b35aef6871a9978cf21799cfec3385502bc555,57e25c962968e542d531305e2ae6810ad15a0043..94048028bdd113cee690a755b468666e608979b7
@@@ -12,7 -12,6 +12,7 @@@
   */
  
  #include <linux/capability.h>
 +#include <linux/dcache.h>
  #include <linux/module.h>
  #include <linux/init.h>
  #include <linux/kernel.h>
@@@ -294,12 -293,9 +294,12 @@@ int security_sb_pivotroot(struct path *
  }
  
  int security_sb_set_mnt_opts(struct super_block *sb,
 -                              struct security_mnt_opts *opts)
 +                              struct security_mnt_opts *opts,
 +                              unsigned long kern_flags,
 +                              unsigned long *set_kern_flags)
  {
 -      return security_ops->sb_set_mnt_opts(sb, opts);
 +      return security_ops->sb_set_mnt_opts(sb, opts, kern_flags,
 +                                              set_kern_flags);
  }
  EXPORT_SYMBOL(security_sb_set_mnt_opts);
  
@@@ -328,15 -324,6 +328,15 @@@ void security_inode_free(struct inode *
        security_ops->inode_free_security(inode);
  }
  
 +int security_dentry_init_security(struct dentry *dentry, int mode,
 +                                      struct qstr *name, void **ctx,
 +                                      u32 *ctxlen)
 +{
 +      return security_ops->dentry_init_security(dentry, mode, name,
 +                                                      ctx, ctxlen);
 +}
 +EXPORT_SYMBOL(security_dentry_init_security);
 +
  int security_inode_init_security(struct inode *inode, struct inode *dir,
                                 const struct qstr *qstr,
                                 const initxattrs initxattrs, void *fs_data)
@@@ -660,7 -647,6 +660,7 @@@ int security_inode_listsecurity(struct 
                return 0;
        return security_ops->inode_listsecurity(inode, buffer, buffer_size);
  }
 +EXPORT_SYMBOL(security_inode_listsecurity);
  
  void security_inode_getsecid(const struct inode *inode, u32 *secid)
  {
@@@ -1061,12 -1047,6 +1061,12 @@@ int security_netlink_send(struct sock *
        return security_ops->netlink_send(sk, skb);
  }
  
 +int security_ismaclabel(const char *name)
 +{
 +      return security_ops->ismaclabel(name);
 +}
 +EXPORT_SYMBOL(security_ismaclabel);
 +
  int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
  {
        return security_ops->secid_to_secctx(secid, secdata, seclen);
@@@ -1342,22 -1322,17 +1342,17 @@@ int security_xfrm_policy_delete(struct 
        return security_ops->xfrm_policy_delete_security(ctx);
  }
  
- int security_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx)
+ int security_xfrm_state_alloc(struct xfrm_state *x,
+                             struct xfrm_user_sec_ctx *sec_ctx)
  {
-       return security_ops->xfrm_state_alloc_security(x, sec_ctx, 0);
+       return security_ops->xfrm_state_alloc(x, sec_ctx);
  }
  EXPORT_SYMBOL(security_xfrm_state_alloc);
  
  int security_xfrm_state_alloc_acquire(struct xfrm_state *x,
                                      struct xfrm_sec_ctx *polsec, u32 secid)
  {
-       if (!polsec)
-               return 0;
-       /*
-        * We want the context to be taken from secid which is usually
-        * from the sock.
-        */
-       return security_ops->xfrm_state_alloc_security(x, NULL, secid);
+       return security_ops->xfrm_state_alloc_acquire(x, polsec, secid);
  }
  
  int security_xfrm_state_delete(struct xfrm_state *x)
diff --combined security/selinux/hooks.c
index c956390a9136b75a7fb8ed17ded49c69310b31cf,c156f5eb1aea26b7b4d8b281e32974563f281449..c09211a4d7da2b88398d702b87defb1f3a1d2f00
@@@ -81,7 -81,6 +81,7 @@@
  #include <linux/syslog.h>
  #include <linux/user_namespace.h>
  #include <linux/export.h>
 +#include <linux/security.h>
  #include <linux/msg.h>
  #include <linux/shm.h>
  
@@@ -95,7 -94,9 +95,9 @@@
  #include "audit.h"
  #include "avc_ss.h"
  
- #define NUM_SEL_MNT_OPTS 5
+ #define SB_TYPE_FMT "%s%s%s"
+ #define SB_SUBTYPE(sb) (sb->s_subtype && sb->s_subtype[0])
+ #define SB_TYPE_ARGS(sb) sb->s_type->name, SB_SUBTYPE(sb) ? "." : "", SB_SUBTYPE(sb) ? sb->s_subtype : ""
  
  extern struct security_operations *security_ops;
  
@@@ -139,12 -140,28 +141,28 @@@ static struct kmem_cache *sel_inode_cac
   * This function checks the SECMARK reference counter to see if any SECMARK
   * targets are currently configured, if the reference counter is greater than
   * zero SECMARK is considered to be enabled.  Returns true (1) if SECMARK is
-  * enabled, false (0) if SECMARK is disabled.
+  * enabled, false (0) if SECMARK is disabled.  If the always_check_network
+  * policy capability is enabled, SECMARK is always considered enabled.
   *
   */
  static int selinux_secmark_enabled(void)
  {
-       return (atomic_read(&selinux_secmark_refcount) > 0);
+       return (selinux_policycap_alwaysnetwork || atomic_read(&selinux_secmark_refcount));
+ }
+ /**
+  * selinux_peerlbl_enabled - Check to see if peer labeling is currently enabled
+  *
+  * Description:
+  * This function checks if NetLabel or labeled IPSEC is enabled.  Returns true
+  * (1) if any are enabled or false (0) if neither are enabled.  If the
+  * always_check_network policy capability is enabled, peer labeling
+  * is always considered enabled.
+  *
+  */
+ static int selinux_peerlbl_enabled(void)
+ {
+       return (selinux_policycap_alwaysnetwork || netlbl_enabled() || selinux_xfrm_enabled());
  }
  
  /*
@@@ -285,14 -302,13 +303,14 @@@ static void superblock_free_security(st
  
  /* The file system's label must be initialized prior to use. */
  
 -static const char *labeling_behaviors[6] = {
 +static const char *labeling_behaviors[7] = {
        "uses xattr",
        "uses transition SIDs",
        "uses task SIDs",
        "uses genfs_contexts",
        "not configured for labeling",
        "uses mountpoint labeling",
 +      "uses native labeling",
  };
  
  static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dentry);
@@@ -309,8 -325,11 +327,11 @@@ enum 
        Opt_defcontext = 3,
        Opt_rootcontext = 4,
        Opt_labelsupport = 5,
+       Opt_nextmntopt = 6,
  };
  
+ #define NUM_SEL_MNT_OPTS      (Opt_nextmntopt - 1)
  static const match_table_t tokens = {
        {Opt_context, CONTEXT_STR "%s"},
        {Opt_fscontext, FSCONTEXT_STR "%s"},
@@@ -355,6 -374,29 +376,29 @@@ static int may_context_mount_inode_rela
        return rc;
  }
  
+ static int selinux_is_sblabel_mnt(struct super_block *sb)
+ {
+       struct superblock_security_struct *sbsec = sb->s_security;
+       if (sbsec->behavior == SECURITY_FS_USE_XATTR ||
+           sbsec->behavior == SECURITY_FS_USE_TRANS ||
+           sbsec->behavior == SECURITY_FS_USE_TASK)
+               return 1;
+       /* Special handling for sysfs. Is genfs but also has setxattr handler*/
+       if (strncmp(sb->s_type->name, "sysfs", sizeof("sysfs")) == 0)
+               return 1;
+       /*
+        * Special handling for rootfs. Is genfs but supports
+        * setting SELinux context on in-core inodes.
+        */
+       if (strncmp(sb->s_type->name, "rootfs", sizeof("rootfs")) == 0)
+               return 1;
+       return 0;
+ }
  static int sb_finish_set_opts(struct super_block *sb)
  {
        struct superblock_security_struct *sbsec = sb->s_security;
                   the first boot of the SELinux kernel before we have
                   assigned xattr values to the filesystem. */
                if (!root_inode->i_op->getxattr) {
-                       printk(KERN_WARNING "SELinux: (dev %s, type %s) has no "
-                              "xattr support\n", sb->s_id, sb->s_type->name);
+                       printk(KERN_WARNING "SELinux: (dev %s, type "SB_TYPE_FMT") has no "
+                              "xattr support\n", sb->s_id, SB_TYPE_ARGS(sb));
                        rc = -EOPNOTSUPP;
                        goto out;
                }
                if (rc < 0 && rc != -ENODATA) {
                        if (rc == -EOPNOTSUPP)
                                printk(KERN_WARNING "SELinux: (dev %s, type "
-                                      "%s) has no security xattr handler\n",
-                                      sb->s_id, sb->s_type->name);
+                                      SB_TYPE_FMT") has no security xattr handler\n",
+                                      sb->s_id, SB_TYPE_ARGS(sb));
                        else
                                printk(KERN_WARNING "SELinux: (dev %s, type "
-                                      "%s) getxattr errno %d\n", sb->s_id,
-                                      sb->s_type->name, -rc);
+                                      SB_TYPE_FMT") getxattr errno %d\n", sb->s_id,
+                                      SB_TYPE_ARGS(sb), -rc);
                        goto out;
                }
        }
  
-       sbsec->flags |= (SE_SBINITIALIZED | SE_SBLABELSUPP);
        if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
-               printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n",
-                      sb->s_id, sb->s_type->name);
+               printk(KERN_ERR "SELinux: initialized (dev %s, type "SB_TYPE_FMT"), unknown behavior\n",
+                      sb->s_id, SB_TYPE_ARGS(sb));
        else
-               printk(KERN_DEBUG "SELinux: initialized (dev %s, type %s), %s\n",
-                      sb->s_id, sb->s_type->name,
+               printk(KERN_DEBUG "SELinux: initialized (dev %s, type "SB_TYPE_FMT"), %s\n",
+                      sb->s_id, SB_TYPE_ARGS(sb),
                       labeling_behaviors[sbsec->behavior-1]);
  
-       if (sbsec->behavior == SECURITY_FS_USE_GENFS ||
-           sbsec->behavior == SECURITY_FS_USE_MNTPOINT ||
-           sbsec->behavior == SECURITY_FS_USE_NONE ||
-           sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
-               sbsec->flags &= ~SE_SBLABELSUPP;
-       /* Special handling for sysfs. Is genfs but also has setxattr handler*/
-       if (strncmp(sb->s_type->name, "sysfs", sizeof("sysfs")) == 0)
-               sbsec->flags |= SE_SBLABELSUPP;
+       sbsec->flags |= SE_SBINITIALIZED;
+       if (selinux_is_sblabel_mnt(sb))
+               sbsec->flags |= SBLABEL_MNT;
  
        /* Initialize the root inode. */
        rc = inode_doinit_with_dentry(root_inode, root);
@@@ -460,15 -494,18 +496,18 @@@ static int selinux_get_mnt_opts(const s
        if (!ss_initialized)
                return -EINVAL;
  
+       /* make sure we always check enough bits to cover the mask */
+       BUILD_BUG_ON(SE_MNTMASK >= (1 << NUM_SEL_MNT_OPTS));
        tmp = sbsec->flags & SE_MNTMASK;
        /* count the number of mount options for this sb */
-       for (i = 0; i < 8; i++) {
+       for (i = 0; i < NUM_SEL_MNT_OPTS; i++) {
                if (tmp & 0x01)
                        opts->num_mnt_opts++;
                tmp >>= 1;
        }
        /* Check if the Label support flag is set */
-       if (sbsec->flags & SE_SBLABELSUPP)
+       if (sbsec->flags & SBLABEL_MNT)
                opts->num_mnt_opts++;
  
        opts->mnt_opts = kcalloc(opts->num_mnt_opts, sizeof(char *), GFP_ATOMIC);
                opts->mnt_opts[i] = context;
                opts->mnt_opts_flags[i++] = ROOTCONTEXT_MNT;
        }
-       if (sbsec->flags & SE_SBLABELSUPP) {
+       if (sbsec->flags & SBLABEL_MNT) {
                opts->mnt_opts[i] = NULL;
-               opts->mnt_opts_flags[i++] = SE_SBLABELSUPP;
+               opts->mnt_opts_flags[i++] = SBLABEL_MNT;
        }
  
        BUG_ON(i != opts->num_mnt_opts);
@@@ -554,14 -591,11 +593,13 @@@ static int bad_option(struct superblock
   * labeling information.
   */
  static int selinux_set_mnt_opts(struct super_block *sb,
 -                              struct security_mnt_opts *opts)
 +                              struct security_mnt_opts *opts,
 +                              unsigned long kern_flags,
 +                              unsigned long *set_kern_flags)
  {
        const struct cred *cred = current_cred();
        int rc = 0, i;
        struct superblock_security_struct *sbsec = sb->s_security;
-       const char *name = sb->s_type->name;
        struct inode *inode = sbsec->sb->s_root->d_inode;
        struct inode_security_struct *root_isec = inode->i_security;
        u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
                        "before the security server is initialized\n");
                goto out;
        }
 +      if (kern_flags && !set_kern_flags) {
 +              /* Specifying internal flags without providing a place to
 +               * place the results is not allowed */
 +              rc = -EINVAL;
 +              goto out;
 +      }
  
        /*
         * Binary mount data FS will come through this function twice.  Once
        for (i = 0; i < num_opts; i++) {
                u32 sid;
  
-               if (flags[i] == SE_SBLABELSUPP)
+               if (flags[i] == SBLABEL_MNT)
                        continue;
                rc = security_context_to_sid(mount_options[i],
                                             strlen(mount_options[i]), &sid);
                if (rc) {
                        printk(KERN_WARNING "SELinux: security_context_to_sid"
-                              "(%s) failed for (dev %s, type %s) errno=%d\n",
-                              mount_options[i], sb->s_id, name, rc);
+                              "(%s) failed for (dev %s, type "SB_TYPE_FMT") errno=%d\n",
+                              mount_options[i], sb->s_id, SB_TYPE_ARGS(sb), rc);
                        goto out;
                }
                switch (flags[i]) {
        if (strcmp(sb->s_type->name, "proc") == 0)
                sbsec->flags |= SE_SBPROC;
  
 -      /* Determine the labeling behavior to use for this filesystem type. */
 -      rc = security_fs_use(sb);
 -      if (rc) {
 -              printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n",
 -                     __func__, sb->s_type->name, rc);
 -              goto out;
 +      if (!sbsec->behavior) {
 +              /*
 +               * Determine the labeling behavior to use for this
 +               * filesystem type.
 +               */
-               rc = security_fs_use((sbsec->flags & SE_SBPROC) ?
-                                       "proc" : sb->s_type->name,
-                                       &sbsec->behavior, &sbsec->sid);
++              rc = security_fs_use(sb);
 +              if (rc) {
 +                      printk(KERN_WARNING
 +                              "%s: security_fs_use(%s) returned %d\n",
 +                                      __func__, sb->s_type->name, rc);
 +                      goto out;
 +              }
        }
 -
        /* sets the context of the superblock for the fs being mounted. */
        if (fscontext_sid) {
                rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, cred);
         * sets the label used on all file below the mountpoint, and will set
         * the superblock context if not already set.
         */
 +      if (kern_flags & SECURITY_LSM_NATIVE_LABELS && !context_sid) {
 +              sbsec->behavior = SECURITY_FS_USE_NATIVE;
 +              *set_kern_flags |= SECURITY_LSM_NATIVE_LABELS;
 +      }
 +
        if (context_sid) {
                if (!fscontext_sid) {
                        rc = may_context_mount_sb_relabel(context_sid, sbsec,
        }
  
        if (defcontext_sid) {
 -              if (sbsec->behavior != SECURITY_FS_USE_XATTR) {
 +              if (sbsec->behavior != SECURITY_FS_USE_XATTR &&
 +                      sbsec->behavior != SECURITY_FS_USE_NATIVE) {
                        rc = -EINVAL;
                        printk(KERN_WARNING "SELinux: defcontext option is "
                               "invalid for this filesystem type\n");
@@@ -770,7 -785,8 +806,8 @@@ out
  out_double_mount:
        rc = -EINVAL;
        printk(KERN_WARNING "SELinux: mount invalid.  Same superblock, different "
-              "security settings for (dev %s, type %s)\n", sb->s_id, name);
+              "security settings for (dev %s, type "SB_TYPE_FMT")\n", sb->s_id,
+              SB_TYPE_ARGS(sb));
        goto out;
  }
  
@@@ -1003,7 -1019,7 +1040,7 @@@ static int superblock_doinit(struct sup
                goto out_err;
  
  out:
 -      rc = selinux_set_mnt_opts(sb, &opts);
 +      rc = selinux_set_mnt_opts(sb, &opts, 0, NULL);
  
  out_err:
        security_free_mnt_opts(&opts);
@@@ -1037,7 -1053,7 +1074,7 @@@ static void selinux_write_opts(struct s
                case DEFCONTEXT_MNT:
                        prefix = DEFCONTEXT_STR;
                        break;
-               case SE_SBLABELSUPP:
+               case SBLABEL_MNT:
                        seq_putc(m, ',');
                        seq_puts(m, LABELSUPP_STR);
                        continue;
@@@ -1245,8 -1261,6 +1282,8 @@@ static int inode_doinit_with_dentry(str
        }
  
        switch (sbsec->behavior) {
 +      case SECURITY_FS_USE_NATIVE:
 +              break;
        case SECURITY_FS_USE_XATTR:
                if (!inode->i_op->getxattr) {
                        isec->sid = sbsec->def_sid;
@@@ -1572,18 -1586,6 +1609,18 @@@ static inline int path_has_perm(const s
        return inode_has_perm(cred, inode, av, &ad, 0);
  }
  
 +/* Same as path_has_perm, but uses the inode from the file struct. */
 +static inline int file_path_has_perm(const struct cred *cred,
 +                                   struct file *file,
 +                                   u32 av)
 +{
 +      struct common_audit_data ad;
 +
 +      ad.type = LSM_AUDIT_DATA_PATH;
 +      ad.u.path = file->f_path;
 +      return inode_has_perm(cred, file_inode(file), av, &ad, 0);
 +}
 +
  /* Check whether a task can use an open file descriptor to
     access an inode in a given way.  Check access to the
     descriptor itself, and then use dentry_has_perm to
@@@ -1650,7 -1652,7 +1687,7 @@@ static int may_create(struct inode *dir
        if (rc)
                return rc;
  
-       if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) {
+       if (!newsid || !(sbsec->flags & SBLABEL_MNT)) {
                rc = security_transition_sid(sid, dsec->sid, tclass,
                                             &dentry->d_name, &newsid);
                if (rc)
@@@ -2178,14 -2180,14 +2215,14 @@@ static inline void flush_unauthorized_f
                        struct tty_file_private *file_priv;
  
                        /* Revalidate access to controlling tty.
 -                         Use path_has_perm on the tty path directly rather
 -                         than using file_has_perm, as this particular open
 -                         file may belong to another process and we are only
 -                         interested in the inode-based check here. */
 +                         Use file_path_has_perm on the tty path directly
 +                         rather than using file_has_perm, as this particular
 +                         open file may belong to another process and we are
 +                         only interested in the inode-based check here. */
                        file_priv = list_first_entry(&tty->tty_files,
                                                struct tty_file_private, list);
                        file = file_priv->file;
 -                      if (path_has_perm(cred, &file->f_path, FILE__READ | FILE__WRITE))
 +                      if (file_path_has_perm(cred, file, FILE__READ | FILE__WRITE))
                                drop_tty = 1;
                }
                spin_unlock(&tty_files_lock);
@@@ -2438,14 -2440,14 +2475,14 @@@ static int selinux_sb_remount(struct su
                u32 sid;
                size_t len;
  
-               if (flags[i] == SE_SBLABELSUPP)
+               if (flags[i] == SBLABEL_MNT)
                        continue;
                len = strlen(mount_options[i]);
                rc = security_context_to_sid(mount_options[i], len, &sid);
                if (rc) {
                        printk(KERN_WARNING "SELinux: security_context_to_sid"
-                              "(%s) failed for (dev %s, type %s) errno=%d\n",
-                              mount_options[i], sb->s_id, sb->s_type->name, rc);
+                              "(%s) failed for (dev %s, type "SB_TYPE_FMT") errno=%d\n",
+                              mount_options[i], sb->s_id, SB_TYPE_ARGS(sb), rc);
                        goto out_free_opts;
                }
                rc = -EINVAL;
@@@ -2483,8 -2485,8 +2520,8 @@@ out_free_secdata
        return rc;
  out_bad_option:
        printk(KERN_WARNING "SELinux: unable to change security options "
-              "during remount (dev %s, type=%s)\n", sb->s_id,
-              sb->s_type->name);
+              "during remount (dev %s, type "SB_TYPE_FMT")\n", sb->s_id,
+              SB_TYPE_ARGS(sb));
        goto out_free_opts;
  }
  
@@@ -2552,40 -2554,6 +2589,40 @@@ static void selinux_inode_free_security
        inode_free_security(inode);
  }
  
 +static int selinux_dentry_init_security(struct dentry *dentry, int mode,
 +                                      struct qstr *name, void **ctx,
 +                                      u32 *ctxlen)
 +{
 +      const struct cred *cred = current_cred();
 +      struct task_security_struct *tsec;
 +      struct inode_security_struct *dsec;
 +      struct superblock_security_struct *sbsec;
 +      struct inode *dir = dentry->d_parent->d_inode;
 +      u32 newsid;
 +      int rc;
 +
 +      tsec = cred->security;
 +      dsec = dir->i_security;
 +      sbsec = dir->i_sb->s_security;
 +
 +      if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {
 +              newsid = tsec->create_sid;
 +      } else {
 +              rc = security_transition_sid(tsec->sid, dsec->sid,
 +                                           inode_mode_to_security_class(mode),
 +                                           name,
 +                                           &newsid);
 +              if (rc) {
 +                      printk(KERN_WARNING
 +                              "%s: security_transition_sid failed, rc=%d\n",
 +                             __func__, -rc);
 +                      return rc;
 +              }
 +      }
 +
 +      return security_sid_to_context(newsid, (char **)ctx, ctxlen);
 +}
 +
  static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
                                       const struct qstr *qstr, char **name,
                                       void **value, size_t *len)
        if ((sbsec->flags & SE_SBINITIALIZED) &&
            (sbsec->behavior == SECURITY_FS_USE_MNTPOINT))
                newsid = sbsec->mntpoint_sid;
-       else if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) {
+       else if (!newsid || !(sbsec->flags & SBLABEL_MNT)) {
                rc = security_transition_sid(sid, dsec->sid,
                                             inode_mode_to_security_class(inode->i_mode),
                                             qstr, &newsid);
                isec->initialized = 1;
        }
  
-       if (!ss_initialized || !(sbsec->flags & SE_SBLABELSUPP))
+       if (!ss_initialized || !(sbsec->flags & SBLABEL_MNT))
                return -EOPNOTSUPP;
  
        if (name) {
@@@ -2836,7 -2804,7 +2873,7 @@@ static int selinux_inode_setxattr(struc
                return selinux_inode_setotherxattr(dentry, name);
  
        sbsec = inode->i_sb->s_security;
-       if (!(sbsec->flags & SE_SBLABELSUPP))
+       if (!(sbsec->flags & SBLABEL_MNT))
                return -EOPNOTSUPP;
  
        if (!inode_owner_or_capable(inode))
@@@ -2920,10 -2888,7 +2957,10 @@@ static void selinux_inode_post_setxattr
                return;
        }
  
 +      isec->sclass = inode_mode_to_security_class(inode->i_mode);
        isec->sid = newsid;
 +      isec->initialized = 1;
 +
        return;
  }
  
@@@ -3011,7 -2976,6 +3048,7 @@@ static int selinux_inode_setsecurity(st
        if (rc)
                return rc;
  
 +      isec->sclass = inode_mode_to_security_class(inode->i_mode);
        isec->sid = newsid;
        isec->initialized = 1;
        return 0;
@@@ -3334,7 -3298,7 +3371,7 @@@ static int selinux_file_open(struct fil
         * new inode label or new policy.
         * This check is not redundant - do not remove.
         */
 -      return path_has_perm(cred, &file->f_path, open_file_to_av(file));
 +      return file_path_has_perm(cred, file, open_file_to_av(file));
  }
  
  /* task security operations */
@@@ -3797,8 -3761,12 +3834,12 @@@ static int selinux_skb_peerlbl_sid(stru
        u32 nlbl_sid;
        u32 nlbl_type;
  
-       selinux_skb_xfrm_sid(skb, &xfrm_sid);
-       selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
+       err = selinux_skb_xfrm_sid(skb, &xfrm_sid);
+       if (unlikely(err))
+               return -EACCES;
+       err = selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid);
+       if (unlikely(err))
+               return -EACCES;
  
        err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid);
        if (unlikely(err)) {
@@@ -4252,7 -4220,7 +4293,7 @@@ static int selinux_socket_sock_rcv_skb(
                return selinux_sock_rcv_skb_compat(sk, skb, family);
  
        secmark_active = selinux_secmark_enabled();
-       peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
+       peerlbl_active = selinux_peerlbl_enabled();
        if (!secmark_active && !peerlbl_active)
                return 0;
  
@@@ -4634,7 -4602,7 +4675,7 @@@ static unsigned int selinux_ip_forward(
  
        secmark_active = selinux_secmark_enabled();
        netlbl_active = netlbl_enabled();
-       peerlbl_active = netlbl_active || selinux_xfrm_enabled();
+       peerlbl_active = selinux_peerlbl_enabled();
        if (!secmark_active && !peerlbl_active)
                return NF_ACCEPT;
  
@@@ -4786,7 -4754,7 +4827,7 @@@ static unsigned int selinux_ip_postrout
                return NF_ACCEPT;
  #endif
        secmark_active = selinux_secmark_enabled();
-       peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled();
+       peerlbl_active = selinux_peerlbl_enabled();
        if (!secmark_active && !peerlbl_active)
                return NF_ACCEPT;
  
@@@ -5495,11 -5463,6 +5536,11 @@@ abort_change
        return error;
  }
  
 +static int selinux_ismaclabel(const char *name)
 +{
 +      return (strcmp(name, XATTR_SELINUX_SUFFIX) == 0);
 +}
 +
  static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
  {
        return security_sid_to_context(secid, secdata, seclen);
@@@ -5642,7 -5605,6 +5683,7 @@@ static struct security_operations selin
        .sb_clone_mnt_opts =            selinux_sb_clone_mnt_opts,
        .sb_parse_opts_str =            selinux_parse_opts_str,
  
 +      .dentry_init_security =         selinux_dentry_init_security,
  
        .inode_alloc_security =         selinux_inode_alloc_security,
        .inode_free_security =          selinux_inode_free_security,
        .getprocattr =                  selinux_getprocattr,
        .setprocattr =                  selinux_setprocattr,
  
 +      .ismaclabel =                   selinux_ismaclabel,
        .secid_to_secctx =              selinux_secid_to_secctx,
        .secctx_to_secid =              selinux_secctx_to_secid,
        .release_secctx =               selinux_release_secctx,
        .xfrm_policy_clone_security =   selinux_xfrm_policy_clone,
        .xfrm_policy_free_security =    selinux_xfrm_policy_free,
        .xfrm_policy_delete_security =  selinux_xfrm_policy_delete,
-       .xfrm_state_alloc_security =    selinux_xfrm_state_alloc,
+       .xfrm_state_alloc =             selinux_xfrm_state_alloc,
+       .xfrm_state_alloc_acquire =     selinux_xfrm_state_alloc_acquire,
        .xfrm_state_free_security =     selinux_xfrm_state_free,
        .xfrm_state_delete_security =   selinux_xfrm_state_delete,
        .xfrm_policy_lookup =           selinux_xfrm_policy_lookup,
index 8fd8e18ea34019c863d91ba88268b8c4018f3410,7aad3a1389d155d0f5f1bfc209264df5f0d9b0e9..fe341ae370049b39ac2012d665a64dd4dc9af198
  /* Mask for just the mount related flags */
  #define SE_MNTMASK    0x0f
  /* Super block security struct flags for mount options */
+ /* BE CAREFUL, these need to be the low order bits for selinux_get_mnt_opts */
  #define CONTEXT_MNT   0x01
  #define FSCONTEXT_MNT 0x02
  #define ROOTCONTEXT_MNT       0x04
  #define DEFCONTEXT_MNT        0x08
+ #define SBLABEL_MNT   0x10
  /* Non-mount related flags */
- #define SE_SBINITIALIZED      0x10
- #define SE_SBPROC             0x20
- #define SE_SBLABELSUPP        0x40
+ #define SE_SBINITIALIZED      0x0100
+ #define SE_SBPROC             0x0200
  
  #define CONTEXT_STR   "context="
  #define FSCONTEXT_STR "fscontext="
@@@ -68,12 -69,15 +69,15 @@@ extern int selinux_enabled
  enum {
        POLICYDB_CAPABILITY_NETPEER,
        POLICYDB_CAPABILITY_OPENPERM,
+       POLICYDB_CAPABILITY_REDHAT1,
+       POLICYDB_CAPABILITY_ALWAYSNETWORK,
        __POLICYDB_CAPABILITY_MAX
  };
  #define POLICYDB_CAPABILITY_MAX (__POLICYDB_CAPABILITY_MAX - 1)
  
  extern int selinux_policycap_netpeer;
  extern int selinux_policycap_openperm;
+ extern int selinux_policycap_alwaysnetwork;
  
  /*
   * type_datum properties
@@@ -169,11 -173,8 +173,10 @@@ int security_get_allow_unknown(void)
  #define SECURITY_FS_USE_GENFS         4 /* use the genfs support */
  #define SECURITY_FS_USE_NONE          5 /* no labeling support */
  #define SECURITY_FS_USE_MNTPOINT      6 /* use mountpoint labeling */
 +#define SECURITY_FS_USE_NATIVE                7 /* use native label support */
 +#define SECURITY_FS_USE_MAX           7 /* Highest SECURITY_FS_USE_XXX */
  
- int security_fs_use(const char *fstype, unsigned int *behavior,
-       u32 *sid);
+ int security_fs_use(struct super_block *sb);
  
  int security_genfs_sid(const char *fstype, char *name, u16 sclass,
        u32 *sid);
index c8adde3aff8fdbe93fb2f867e55f71b9879685a5,3fc8969b499c5e3f6f4898c8c1f7583df8b11e9c..f6195ebde3c94eef0cdf1cf92933246069b25059
@@@ -2168,10 -2168,7 +2168,10 @@@ static int ocontext_read(struct policyd
  
                                rc = -EINVAL;
                                c->v.behavior = le32_to_cpu(buf[0]);
 -                              if (c->v.behavior > SECURITY_FS_USE_NONE)
 +                              /* Determined at runtime, not in policy DB. */
 +                              if (c->v.behavior == SECURITY_FS_USE_MNTPOINT)
 +                                      goto out;
 +                              if (c->v.behavior > SECURITY_FS_USE_MAX)
                                        goto out;
  
                                rc = -ENOMEM;
@@@ -3203,9 -3200,8 +3203,8 @@@ static int range_write_helper(void *key
  
  static int range_write(struct policydb *p, void *fp)
  {
-       size_t nel;
        __le32 buf[1];
-       int rc;
+       int rc, nel;
        struct policy_data pd;
  
        pd.p = p;
This page took 0.108849 seconds and 4 git commands to generate.