Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 30 Apr 2013 23:27:51 +0000 (16:27 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 30 Apr 2013 23:27:51 +0000 (16:27 -0700)
Pull security subsystem update from James Morris:
 "Just some minor updates across the subsystem"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security:
  ima: eliminate passing d_name.name to process_measurement()
  TPM: Retry SaveState command in suspend path
  tpm/tpm_i2c_infineon: Add small comment about return value of __i2c_transfer
  tpm/tpm_i2c_infineon.c: Add OF attributes type and name to the of_device_id table entries
  tpm_i2c_stm_st33: Remove duplicate inclusion of header files
  tpm: Add support for new Infineon I2C TPM (SLB 9645 TT 1.2 I2C)
  char/tpm: Convert struct i2c_msg initialization to C99 format
  drivers/char/tpm/tpm_ppi: use strlcpy instead of strncpy
  tpm/tpm_i2c_stm_st33: formatting and white space changes
  Smack: include magic.h in smackfs.c
  selinux: make security_sb_clone_mnt_opts return an error on context mismatch
  seccomp: allow BPF_XOR based ALU instructions.
  Fix NULL pointer dereference in smack_inode_unlink() and smack_inode_rmdir()
  Smack: add support for modification of existing rules
  smack: SMACK_MAGIC to include/uapi/linux/magic.h
  Smack: add missing support for transmute bit in smack_str_from_perm()
  Smack: prevent revoke-subject from failing when unseen label is written to it
  tomoyo: use DEFINE_SRCU() to define tomoyo_ss
  tomoyo: use DEFINE_SRCU() to define tomoyo_ss

1  2 
fs/nfs/super.c
include/linux/security.h
security/capability.c
security/security.c
security/selinux/hooks.c

diff --combined fs/nfs/super.c
@@@ -335,7 -335,6 +335,7 @@@ struct file_system_type nfs4_fs_type = 
        .fs_flags       = FS_RENAME_DOES_D_MOVE|FS_BINARY_MOUNTDATA,
  };
  MODULE_ALIAS_FS("nfs4");
 +MODULE_ALIAS("nfs4");
  EXPORT_SYMBOL_GPL(nfs4_fs_type);
  
  static int __init register_nfs4_fs(void)
@@@ -920,7 -919,7 +920,7 @@@ static struct nfs_parsed_mount_data *nf
                data->mount_server.port = NFS_UNSPEC_PORT;
                data->nfs_server.port   = NFS_UNSPEC_PORT;
                data->nfs_server.protocol = XPRT_TRANSPORT_TCP;
 -              data->auth_flavors[0]   = RPC_AUTH_UNIX;
 +              data->auth_flavors[0]   = RPC_AUTH_MAXFLAVOR;
                data->auth_flavor_len   = 1;
                data->minorversion      = 0;
                data->need_mount        = true;
@@@ -1608,57 -1607,49 +1608,57 @@@ out_security_failure
  }
  
  /*
 - * Match the requested auth flavors with the list returned by
 - * the server.  Returns zero and sets the mount's authentication
 - * flavor on success; returns -EACCES if server does not support
 - * the requested flavor.
 + * Select a security flavor for this mount.  The selected flavor
 + * is planted in args->auth_flavors[0].
   */
 -static int nfs_walk_authlist(struct nfs_parsed_mount_data *args,
 -                           struct nfs_mount_request *request)
 +static void nfs_select_flavor(struct nfs_parsed_mount_data *args,
 +                            struct nfs_mount_request *request)
  {
 -      unsigned int i, j, server_authlist_len = *(request->auth_flav_len);
 +      unsigned int i, count = *(request->auth_flav_len);
 +      rpc_authflavor_t flavor;
 +
 +      if (args->auth_flavors[0] != RPC_AUTH_MAXFLAVOR)
 +              goto out;
 +
 +      /*
 +       * The NFSv2 MNT operation does not return a flavor list.
 +       */
 +      if (args->mount_server.version != NFS_MNT3_VERSION)
 +              goto out_default;
  
        /*
         * Certain releases of Linux's mountd return an empty
 -       * flavor list.  To prevent behavioral regression with
 -       * these servers (ie. rejecting mounts that used to
 -       * succeed), revert to pre-2.6.32 behavior (no checking)
 -       * if the returned flavor list is empty.
 +       * flavor list in some cases.
         */
 -      if (server_authlist_len == 0)
 -              return 0;
 +      if (count == 0)
 +              goto out_default;
  
        /*
 -       * We avoid sophisticated negotiating here, as there are
 -       * plenty of cases where we can get it wrong, providing
 -       * either too little or too much security.
 -       *
         * RFC 2623, section 2.7 suggests we SHOULD prefer the
         * flavor listed first.  However, some servers list
 -       * AUTH_NULL first.  Our caller plants AUTH_SYS, the
 -       * preferred default, in args->auth_flavors[0] if user
 -       * didn't specify sec= mount option.
 +       * AUTH_NULL first.  Avoid ever choosing AUTH_NULL.
         */
 -      for (i = 0; i < args->auth_flavor_len; i++)
 -              for (j = 0; j < server_authlist_len; j++)
 -                      if (args->auth_flavors[i] == request->auth_flavs[j]) {
 -                              dfprintk(MOUNT, "NFS: using auth flavor %d\n",
 -                                      request->auth_flavs[j]);
 -                              args->auth_flavors[0] = request->auth_flavs[j];
 -                              return 0;
 -                      }
 +      for (i = 0; i < count; i++) {
 +              struct rpcsec_gss_info info;
 +
 +              flavor = request->auth_flavs[i];
 +              switch (flavor) {
 +              case RPC_AUTH_UNIX:
 +                      goto out_set;
 +              case RPC_AUTH_NULL:
 +                      continue;
 +              default:
 +                      if (rpcauth_get_gssinfo(flavor, &info) == 0)
 +                              goto out_set;
 +              }
 +      }
  
 -      dfprintk(MOUNT, "NFS: server does not support requested auth flavor\n");
 -      nfs_umount(request);
 -      return -EACCES;
 +out_default:
 +      flavor = RPC_AUTH_UNIX;
 +out_set:
 +      args->auth_flavors[0] = flavor;
 +out:
 +      dfprintk(MOUNT, "NFS: using auth flavor %d\n", args->auth_flavors[0]);
  }
  
  /*
@@@ -1721,8 -1712,12 +1721,8 @@@ static int nfs_request_mount(struct nfs
                return status;
        }
  
 -      /*
 -       * MNTv1 (NFSv2) does not support auth flavor negotiation.
 -       */
 -      if (args->mount_server.version != NFS_MNT3_VERSION)
 -              return 0;
 -      return nfs_walk_authlist(args, &request);
 +      nfs_select_flavor(args, &request);
 +      return 0;
  }
  
  struct dentry *nfs_try_mount(int flags, const char *dev_name,
@@@ -2385,10 -2380,9 +2385,9 @@@ int nfs_clone_sb_security(struct super_
                          struct nfs_mount_info *mount_info)
  {
        /* clone any lsm security options from the parent to the new sb */
-       security_sb_clone_mnt_opts(mount_info->cloned->sb, s);
        if (mntroot->d_inode->i_op != NFS_SB(s)->nfs_client->rpc_ops->dir_inode_ops)
                return -ESTALE;
-       return 0;
+       return security_sb_clone_mnt_opts(mount_info->cloned->sb, s);
  }
  EXPORT_SYMBOL_GPL(nfs_clone_sb_security);
  
diff --combined include/linux/security.h
@@@ -1012,10 -1012,6 +1012,10 @@@ static inline void security_free_mnt_op
   *    This hook can be used by the module to update any security state
   *    associated with the TUN device's security structure.
   *    @security pointer to the TUN devices's security structure.
 + * @skb_owned_by:
 + *    This hook sets the packet's owning sock.
 + *    @skb is the packet.
 + *    @sk the sock which owns the packet.
   *
   * Security hooks for XFRM operations.
   *
@@@ -1440,7 -1436,7 +1440,7 @@@ struct security_operations 
                             struct path *new_path);
        int (*sb_set_mnt_opts) (struct super_block *sb,
                                struct security_mnt_opts *opts);
-       void (*sb_clone_mnt_opts) (const struct super_block *oldsb,
+       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 (*tun_dev_attach_queue) (void *security);
        int (*tun_dev_attach) (struct sock *sk, void *security);
        int (*tun_dev_open) (void *security);
 +      void (*skb_owned_by) (struct sk_buff *skb, struct sock *sk);
  #endif        /* CONFIG_SECURITY_NETWORK */
  
  #ifdef CONFIG_SECURITY_NETWORK_XFRM
@@@ -1726,7 -1721,7 +1726,7 @@@ int security_sb_mount(const char *dev_n
  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);
void security_sb_clone_mnt_opts(const struct super_block *oldsb,
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);
  
@@@ -2016,9 -2011,11 +2016,11 @@@ static inline int security_sb_set_mnt_o
        return 0;
  }
  
- static inline void security_sb_clone_mnt_opts(const struct super_block *oldsb,
+ static inline int security_sb_clone_mnt_opts(const struct super_block *oldsb,
                                              struct super_block *newsb)
- { }
+ {
+       return 0;
+ }
  
  static inline int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts)
  {
@@@ -2593,8 -2590,6 +2595,8 @@@ int security_tun_dev_attach_queue(void 
  int security_tun_dev_attach(struct sock *sk, void *security);
  int security_tun_dev_open(void *security);
  
 +void security_skb_owned_by(struct sk_buff *skb, struct sock *sk);
 +
  #else /* CONFIG_SECURITY_NETWORK */
  static inline int security_unix_stream_connect(struct sock *sock,
                                               struct sock *other,
@@@ -2786,11 -2781,6 +2788,11 @@@ static inline int security_tun_dev_open
  {
        return 0;
  }
 +
 +static inline void security_skb_owned_by(struct sk_buff *skb, struct sock *sk)
 +{
 +}
 +
  #endif        /* CONFIG_SECURITY_NETWORK */
  
  #ifdef CONFIG_SECURITY_NETWORK_XFRM
diff --combined security/capability.c
@@@ -98,9 -98,10 +98,10 @@@ static int cap_sb_set_mnt_opts(struct s
        return 0;
  }
  
- static void cap_sb_clone_mnt_opts(const struct super_block *oldsb,
+ static int cap_sb_clone_mnt_opts(const struct super_block *oldsb,
                                  struct super_block *newsb)
  {
+       return 0;
  }
  
  static int cap_sb_parse_opts_str(char *options, struct security_mnt_opts *opts)
@@@ -737,11 -738,6 +738,11 @@@ static int cap_tun_dev_open(void *secur
  {
        return 0;
  }
 +
 +static void cap_skb_owned_by(struct sk_buff *skb, struct sock *sk)
 +{
 +}
 +
  #endif        /* CONFIG_SECURITY_NETWORK */
  
  #ifdef CONFIG_SECURITY_NETWORK_XFRM
@@@ -1076,7 -1072,6 +1077,7 @@@ void __init security_fixup_ops(struct s
        set_to_cap_if_null(ops, tun_dev_open);
        set_to_cap_if_null(ops, tun_dev_attach_queue);
        set_to_cap_if_null(ops, tun_dev_attach);
 +      set_to_cap_if_null(ops, skb_owned_by);
  #endif        /* CONFIG_SECURITY_NETWORK */
  #ifdef CONFIG_SECURITY_NETWORK_XFRM
        set_to_cap_if_null(ops, xfrm_policy_alloc_security);
diff --combined security/security.c
@@@ -299,10 -299,10 +299,10 @@@ int security_sb_set_mnt_opts(struct sup
  }
  EXPORT_SYMBOL(security_sb_set_mnt_opts);
  
void security_sb_clone_mnt_opts(const struct super_block *oldsb,
int security_sb_clone_mnt_opts(const struct super_block *oldsb,
                                struct super_block *newsb)
  {
-       security_ops->sb_clone_mnt_opts(oldsb, newsb);
+       return security_ops->sb_clone_mnt_opts(oldsb, newsb);
  }
  EXPORT_SYMBOL(security_sb_clone_mnt_opts);
  
@@@ -1290,11 -1290,6 +1290,11 @@@ int security_tun_dev_open(void *securit
  }
  EXPORT_SYMBOL(security_tun_dev_open);
  
 +void security_skb_owned_by(struct sk_buff *skb, struct sock *sk)
 +{
 +      security_ops->skb_owned_by(skb, sk);
 +}
 +
  #endif        /* CONFIG_SECURITY_NETWORK */
  
  #ifdef CONFIG_SECURITY_NETWORK_XFRM
diff --combined security/selinux/hooks.c
@@@ -51,7 -51,6 +51,7 @@@
  #include <linux/tty.h>
  #include <net/icmp.h>
  #include <net/ip.h>           /* for local_port_range[] */
 +#include <net/sock.h>
  #include <net/tcp.h>          /* struct or_callable used in sock_rcv_skb */
  #include <net/net_namespace.h>
  #include <net/netlabel.h>
@@@ -751,7 -750,37 +751,37 @@@ out_double_mount
        goto out;
  }
  
- static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
+ static int selinux_cmp_sb_context(const struct super_block *oldsb,
+                                   const struct super_block *newsb)
+ {
+       struct superblock_security_struct *old = oldsb->s_security;
+       struct superblock_security_struct *new = newsb->s_security;
+       char oldflags = old->flags & SE_MNTMASK;
+       char newflags = new->flags & SE_MNTMASK;
+       if (oldflags != newflags)
+               goto mismatch;
+       if ((oldflags & FSCONTEXT_MNT) && old->sid != new->sid)
+               goto mismatch;
+       if ((oldflags & CONTEXT_MNT) && old->mntpoint_sid != new->mntpoint_sid)
+               goto mismatch;
+       if ((oldflags & DEFCONTEXT_MNT) && old->def_sid != new->def_sid)
+               goto mismatch;
+       if (oldflags & ROOTCONTEXT_MNT) {
+               struct inode_security_struct *oldroot = oldsb->s_root->d_inode->i_security;
+               struct inode_security_struct *newroot = newsb->s_root->d_inode->i_security;
+               if (oldroot->sid != newroot->sid)
+                       goto mismatch;
+       }
+       return 0;
+ mismatch:
+       printk(KERN_WARNING "SELinux: mount invalid.  Same superblock, "
+                           "different security settings for (dev %s, "
+                           "type %s)\n", newsb->s_id, newsb->s_type->name);
+       return -EBUSY;
+ }
+ static int selinux_sb_clone_mnt_opts(const struct super_block *oldsb,
                                        struct super_block *newsb)
  {
        const struct superblock_security_struct *oldsbsec = oldsb->s_security;
         * mount options.  thus we can safely deal with this superblock later
         */
        if (!ss_initialized)
-               return;
+               return 0;
  
        /* how can we clone if the old one wasn't set up?? */
        BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED));
  
-       /* if fs is reusing a sb, just let its options stand... */
+       /* if fs is reusing a sb, make sure that the contexts match */
        if (newsbsec->flags & SE_SBINITIALIZED)
-               return;
+               return selinux_cmp_sb_context(oldsb, newsb);
  
        mutex_lock(&newsbsec->lock);
  
  
        sb_finish_set_opts(newsb);
        mutex_unlock(&newsbsec->lock);
+       return 0;
  }
  
  static int selinux_parse_opts_str(char *options,
@@@ -4364,11 -4394,6 +4395,11 @@@ static void selinux_inet_conn_establish
        selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid);
  }
  
 +static void selinux_skb_owned_by(struct sk_buff *skb, struct sock *sk)
 +{
 +      skb_set_owner_w(skb, sk);
 +}
 +
  static int selinux_secmark_relabel_packet(u32 sid)
  {
        const struct task_security_struct *__tsec;
@@@ -5670,7 -5695,6 +5701,7 @@@ static struct security_operations selin
        .tun_dev_attach_queue =         selinux_tun_dev_attach_queue,
        .tun_dev_attach =               selinux_tun_dev_attach,
        .tun_dev_open =                 selinux_tun_dev_open,
 +      .skb_owned_by =                 selinux_skb_owned_by,
  
  #ifdef CONFIG_SECURITY_NETWORK_XFRM
        .xfrm_policy_alloc_security =   selinux_xfrm_policy_alloc,