Merge branch 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 21 May 2018 18:54:57 +0000 (11:54 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 21 May 2018 18:54:57 +0000 (11:54 -0700)
Pull vfs fixes from Al Viro:
 "Assorted fixes all over the place"

* 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
  aio: fix io_destroy(2) vs. lookup_ioctx() race
  ext2: fix a block leak
  nfsd: vfs_mkdir() might succeed leaving dentry negative unhashed
  cachefiles: vfs_mkdir() might succeed leaving dentry negative unhashed
  unfuck sysfs_mount()
  kernfs: deal with kernfs_fill_super() failures
  cramfs: Fix IS_ENABLED typo
  befs_lookup(): use d_splice_alias()
  affs_lookup: switch to d_splice_alias()
  affs_lookup(): close a race with affs_remove_link()
  fix breakage caused by d_find_alias() semantics change
  fs: don't scan the inode cache before SB_BORN is set
  do d_instantiate/unlock_new_inode combinations safely
  iov_iter: fix memory leak in pipe_get_pages_alloc()
  iov_iter: fix return type of __pipe_get_pages()

1  2 
fs/btrfs/inode.c
fs/ecryptfs/inode.c
security/selinux/hooks.c

diff --combined fs/btrfs/inode.c
index 8e604e7071f14cf166652369e6f167fab5b5f462,9e97cbb4f00668ceffa7cc80aa4653cef876c806..d3862e7e4feee53c4c752916eeca5b6a4a045c84
@@@ -31,7 -31,6 +31,7 @@@
  #include <linux/uio.h>
  #include <linux/magic.h>
  #include <linux/iversion.h>
 +#include <asm/unaligned.h>
  #include "ctree.h"
  #include "disk-io.h"
  #include "transaction.h"
@@@ -1742,12 -1741,12 +1742,12 @@@ static void btrfs_add_delalloc_inodes(s
        spin_unlock(&root->delalloc_lock);
  }
  
 -static void btrfs_del_delalloc_inode(struct btrfs_root *root,
 -                                   struct btrfs_inode *inode)
 +
 +void __btrfs_del_delalloc_inode(struct btrfs_root *root,
 +                              struct btrfs_inode *inode)
  {
        struct btrfs_fs_info *fs_info = btrfs_sb(inode->vfs_inode.i_sb);
  
 -      spin_lock(&root->delalloc_lock);
        if (!list_empty(&inode->delalloc_inodes)) {
                list_del_init(&inode->delalloc_inodes);
                clear_bit(BTRFS_INODE_IN_DELALLOC_LIST,
                        spin_unlock(&fs_info->delalloc_root_lock);
                }
        }
 +}
 +
 +static void btrfs_del_delalloc_inode(struct btrfs_root *root,
 +                                   struct btrfs_inode *inode)
 +{
 +      spin_lock(&root->delalloc_lock);
 +      __btrfs_del_delalloc_inode(root, inode);
        spin_unlock(&root->delalloc_lock);
  }
  
@@@ -5913,13 -5905,11 +5913,13 @@@ static int btrfs_filldir(void *addr, in
                struct dir_entry *entry = addr;
                char *name = (char *)(entry + 1);
  
 -              ctx->pos = entry->offset;
 -              if (!dir_emit(ctx, name, entry->name_len, entry->ino,
 -                            entry->type))
 +              ctx->pos = get_unaligned(&entry->offset);
 +              if (!dir_emit(ctx, name, get_unaligned(&entry->name_len),
 +                                       get_unaligned(&entry->ino),
 +                                       get_unaligned(&entry->type)))
                        return 1;
 -              addr += sizeof(struct dir_entry) + entry->name_len;
 +              addr += sizeof(struct dir_entry) +
 +                      get_unaligned(&entry->name_len);
                ctx->pos++;
        }
        return 0;
@@@ -6009,15 -5999,14 +6009,15 @@@ again
                }
  
                entry = addr;
 -              entry->name_len = name_len;
 +              put_unaligned(name_len, &entry->name_len);
                name_ptr = (char *)(entry + 1);
                read_extent_buffer(leaf, name_ptr, (unsigned long)(di + 1),
                                   name_len);
 -              entry->type = btrfs_filetype_table[btrfs_dir_type(leaf, di)];
 +              put_unaligned(btrfs_filetype_table[btrfs_dir_type(leaf, di)],
 +                              &entry->type);
                btrfs_dir_item_key_to_cpu(leaf, di, &location);
 -              entry->ino = location.objectid;
 -              entry->offset = found_key.offset;
 +              put_unaligned(location.objectid, &entry->ino);
 +              put_unaligned(found_key.offset, &entry->offset);
                entries++;
                addr += sizeof(struct dir_entry) + name_len;
                total_len += sizeof(struct dir_entry) + name_len;
@@@ -6586,8 -6575,7 +6586,7 @@@ static int btrfs_mknod(struct inode *di
                goto out_unlock_inode;
        } else {
                btrfs_update_inode(trans, root, inode);
-               unlock_new_inode(inode);
-               d_instantiate(dentry, inode);
+               d_instantiate_new(dentry, inode);
        }
  
  out_unlock:
@@@ -6663,8 -6651,7 +6662,7 @@@ static int btrfs_create(struct inode *d
                goto out_unlock_inode;
  
        BTRFS_I(inode)->io_tree.ops = &btrfs_extent_io_ops;
-       unlock_new_inode(inode);
-       d_instantiate(dentry, inode);
+       d_instantiate_new(dentry, inode);
  
  out_unlock:
        btrfs_end_transaction(trans);
@@@ -6809,12 -6796,7 +6807,7 @@@ static int btrfs_mkdir(struct inode *di
        if (err)
                goto out_fail_inode;
  
-       d_instantiate(dentry, inode);
-       /*
-        * mkdir is special.  We're unlocking after we call d_instantiate
-        * to avoid a race with nfsd calling d_instantiate.
-        */
-       unlock_new_inode(inode);
+       d_instantiate_new(dentry, inode);
        drop_on_err = 0;
  
  out_fail:
@@@ -10257,8 -10239,7 +10250,7 @@@ static int btrfs_symlink(struct inode *
                goto out_unlock_inode;
        }
  
-       unlock_new_inode(inode);
-       d_instantiate(dentry, inode);
+       d_instantiate_new(dentry, inode);
  
  out_unlock:
        btrfs_end_transaction(trans);
diff --combined fs/ecryptfs/inode.c
index 97d17eaeba0731fb5d755c7a3106af1abaf2cff0,7bba8f2693b2d5cff40b7b8484f7cf75137d892b..49121e5a8de228acfb1ea126250e5ad94e4ec812
@@@ -283,8 -283,7 +283,7 @@@ ecryptfs_create(struct inode *directory
                iget_failed(ecryptfs_inode);
                goto out;
        }
-       unlock_new_inode(ecryptfs_inode);
-       d_instantiate(ecryptfs_dentry, ecryptfs_inode);
+       d_instantiate_new(ecryptfs_dentry, ecryptfs_inode);
  out:
        return rc;
  }
@@@ -395,7 -394,8 +394,7 @@@ static struct dentry *ecryptfs_lookup(s
  
        mount_crypt_stat = &ecryptfs_superblock_to_private(
                                ecryptfs_dentry->d_sb)->mount_crypt_stat;
 -      if (mount_crypt_stat
 -          && (mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES)) {
 +      if (mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES) {
                rc = ecryptfs_encrypt_and_encode_filename(
                        &encrypted_and_encoded_name, &len,
                        mount_crypt_stat, name, len);
diff --combined security/selinux/hooks.c
index be5817df0a9d98eab91b059d814f27322d8e7665,398d165f884e759b3227c076cc98d324985c037d..179dd20bec0a26669d4e00420144903644e07c82
@@@ -1568,8 -1568,15 +1568,15 @@@ static int inode_doinit_with_dentry(str
                        /* Called from d_instantiate or d_splice_alias. */
                        dentry = dget(opt_dentry);
                } else {
-                       /* Called from selinux_complete_init, try to find a dentry. */
+                       /*
+                        * Called from selinux_complete_init, try to find a dentry.
+                        * Some filesystems really want a connected one, so try
+                        * that first.  We could split SECURITY_FS_USE_XATTR in
+                        * two, depending upon that...
+                        */
                        dentry = d_find_alias(inode);
+                       if (!dentry)
+                               dentry = d_find_any_alias(inode);
                }
                if (!dentry) {
                        /*
                if ((sbsec->flags & SE_SBGENFS) && !S_ISLNK(inode->i_mode)) {
                        /* We must have a dentry to determine the label on
                         * procfs inodes */
-                       if (opt_dentry)
+                       if (opt_dentry) {
                                /* Called from d_instantiate or
                                 * d_splice_alias. */
                                dentry = dget(opt_dentry);
-                       else
+                       } else {
                                /* Called from selinux_complete_init, try to
-                                * find a dentry. */
+                                * find a dentry.  Some filesystems really want
+                                * a connected one, so try that first.
+                                */
                                dentry = d_find_alias(inode);
+                               if (!dentry)
+                                       dentry = d_find_any_alias(inode);
+                       }
                        /*
                         * This can be hit on boot when a file is accessed
                         * before the policy is loaded.  When we load policy we
@@@ -4576,7 -4588,6 +4588,7 @@@ static int selinux_socket_post_create(s
  static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen)
  {
        struct sock *sk = sock->sk;
 +      struct sk_security_struct *sksec = sk->sk_security;
        u16 family;
        int err;
  
        family = sk->sk_family;
        if (family == PF_INET || family == PF_INET6) {
                char *addrp;
 -              struct sk_security_struct *sksec = sk->sk_security;
                struct common_audit_data ad;
                struct lsm_network_audit net = {0,};
                struct sockaddr_in *addr4 = NULL;
                struct sockaddr_in6 *addr6 = NULL;
 +              u16 family_sa = address->sa_family;
                unsigned short snum;
                u32 sid, node_perm;
  
                 * need to check address->sa_family as it is possible to have
                 * sk->sk_family = PF_INET6 with addr->sa_family = AF_INET.
                 */
 -              switch (address->sa_family) {
 +              switch (family_sa) {
 +              case AF_UNSPEC:
                case AF_INET:
                        if (addrlen < sizeof(struct sockaddr_in))
                                return -EINVAL;
                        addr4 = (struct sockaddr_in *)address;
 +                      if (family_sa == AF_UNSPEC) {
 +                              /* see __inet_bind(), we only want to allow
 +                               * AF_UNSPEC if the address is INADDR_ANY
 +                               */
 +                              if (addr4->sin_addr.s_addr != htonl(INADDR_ANY))
 +                                      goto err_af;
 +                              family_sa = AF_INET;
 +                      }
                        snum = ntohs(addr4->sin_port);
                        addrp = (char *)&addr4->sin_addr.s_addr;
                        break;
                        addrp = (char *)&addr6->sin6_addr.s6_addr;
                        break;
                default:
 -                      /* Note that SCTP services expect -EINVAL, whereas
 -                       * others expect -EAFNOSUPPORT.
 -                       */
 -                      if (sksec->sclass == SECCLASS_SCTP_SOCKET)
 -                              return -EINVAL;
 -                      else
 -                              return -EAFNOSUPPORT;
 +                      goto err_af;
                }
  
 +              ad.type = LSM_AUDIT_DATA_NET;
 +              ad.u.net = &net;
 +              ad.u.net->sport = htons(snum);
 +              ad.u.net->family = family_sa;
 +
                if (snum) {
                        int low, high;
  
                                                      snum, &sid);
                                if (err)
                                        goto out;
 -                              ad.type = LSM_AUDIT_DATA_NET;
 -                              ad.u.net = &net;
 -                              ad.u.net->sport = htons(snum);
 -                              ad.u.net->family = family;
                                err = avc_has_perm(&selinux_state,
                                                   sksec->sid, sid,
                                                   sksec->sclass,
                        break;
                }
  
 -              err = sel_netnode_sid(addrp, family, &sid);
 +              err = sel_netnode_sid(addrp, family_sa, &sid);
                if (err)
                        goto out;
  
 -              ad.type = LSM_AUDIT_DATA_NET;
 -              ad.u.net = &net;
 -              ad.u.net->sport = htons(snum);
 -              ad.u.net->family = family;
 -
 -              if (address->sa_family == AF_INET)
 +              if (family_sa == AF_INET)
                        ad.u.net->v4info.saddr = addr4->sin_addr.s_addr;
                else
                        ad.u.net->v6info.saddr = addr6->sin6_addr;
        }
  out:
        return err;
 +err_af:
 +      /* Note that SCTP services expect -EINVAL, others -EAFNOSUPPORT. */
 +      if (sksec->sclass == SECCLASS_SCTP_SOCKET)
 +              return -EINVAL;
 +      return -EAFNOSUPPORT;
  }
  
  /* This supports connect(2) and SCTP connect services such as sctp_connectx(3)
@@@ -4776,7 -4783,7 +4788,7 @@@ static int selinux_socket_connect_helpe
                ad.type = LSM_AUDIT_DATA_NET;
                ad.u.net = &net;
                ad.u.net->dport = htons(snum);
 -              ad.u.net->family = sk->sk_family;
 +              ad.u.net->family = address->sa_family;
                err = avc_has_perm(&selinux_state,
                                   sksec->sid, sid, sksec->sclass, perm, &ad);
                if (err)
@@@ -5277,7 -5284,6 +5289,7 @@@ static int selinux_sctp_bind_connect(st
        while (walk_size < addrlen) {
                addr = addr_buf;
                switch (addr->sa_family) {
 +              case AF_UNSPEC:
                case AF_INET:
                        len = sizeof(struct sockaddr_in);
                        break;
                        len = sizeof(struct sockaddr_in6);
                        break;
                default:
 -                      return -EAFNOSUPPORT;
 +                      return -EINVAL;
                }
  
                err = -EINVAL;