Permalink
Browse files

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel…

…/git/viro/vfs

Pull second vfs pile from Al Viro:
 "The stuff in there: fsfreeze deadlock fixes by Jan (essentially, the
  deadlock reproduced by xfstests 068), symlink and hardlink restriction
  patches, plus assorted cleanups and fixes.

  Note that another fsfreeze deadlock (emergency thaw one) is *not*
  dealt with - the series by Fernando conflicts a lot with Jan's, breaks
  userland ABI (FIFREEZE semantics gets changed) and trades the deadlock
  for massive vfsmount leak; this is going to be handled next cycle.
  There probably will be another pull request, but that stuff won't be
  in it."

Fix up trivial conflicts due to unrelated changes next to each other in
drivers/{staging/gdm72xx/usb_boot.c, usb/gadget/storage_common.c}

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (54 commits)
  delousing target_core_file a bit
  Documentation: Correct s_umount state for freeze_fs/unfreeze_fs
  fs: Remove old freezing mechanism
  ext2: Implement freezing
  btrfs: Convert to new freezing mechanism
  nilfs2: Convert to new freezing mechanism
  ntfs: Convert to new freezing mechanism
  fuse: Convert to new freezing mechanism
  gfs2: Convert to new freezing mechanism
  ocfs2: Convert to new freezing mechanism
  xfs: Convert to new freezing code
  ext4: Convert to new freezing mechanism
  fs: Protect write paths by sb_start_write - sb_end_write
  fs: Skip atime update on frozen filesystem
  fs: Add freezing handling to mnt_want_write() / mnt_drop_write()
  fs: Improve filesystem freezing handling
  switch the protection of percpu_counter list to spinlock
  nfsd: Push mnt_want_write() outside of i_mutex
  btrfs: Push mnt_want_write() outside of i_mutex
  fat: Push mnt_want_write() outside of i_mutex
  ...
  • Loading branch information...
2 parents eff0d13 + dbc6e02 commit a0e881b7c189fa2bd76c024dbff91e79511c971d @torvalds torvalds committed Aug 1, 2012
Showing with 1,326 additions and 639 deletions.
  1. +2 −2 Documentation/filesystems/Locking
  2. +42 −0 Documentation/sysctl/fs.txt
  3. +25 −52 arch/powerpc/platforms/cell/spufs/inode.c
  4. +1 −1 arch/powerpc/platforms/cell/spufs/syscalls.c
  5. +2 −7 drivers/base/devtmpfs.c
  6. +1 −1 drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
  7. +5 −26 drivers/staging/bcm/Misc.c
  8. +3 −4 drivers/staging/gdm72xx/sdio_boot.c
  9. +9 −13 drivers/staging/gdm72xx/usb_boot.c
  10. +5 −27 drivers/target/target_core_file.c
  11. +5 −7 drivers/usb/gadget/storage_common.c
  12. +3 −3 drivers/usb/gadget/u_uac1.c
  13. +2 −0 drivers/video/fb_defio.c
  14. +3 −0 fs/9p/vfs_file.c
  15. +0 −3 fs/btrfs/disk-io.c
  16. +2 −1 fs/btrfs/file.c
  17. +5 −1 fs/btrfs/inode.c
  18. +10 −5 fs/btrfs/ioctl.c
  19. +7 −0 fs/btrfs/transaction.c
  20. +10 −18 fs/buffer.c
  21. +3 −0 fs/ceph/addr.c
  22. +10 −20 fs/ecryptfs/inode.c
  23. +6 −13 fs/exec.c
  24. +4 −1 fs/ext2/inode.c
  25. +33 −0 fs/ext2/super.c
  26. +10 −5 fs/ext4/inode.c
  27. +6 −0 fs/ext4/mmp.c
  28. +7 −24 fs/ext4/super.c
  29. +7 −8 fs/fat/file.c
  30. +2 −2 fs/file_table.c
  31. +2 −2 fs/fuse/file.c
  32. +6 −12 fs/gfs2/file.c
  33. +4 −0 fs/gfs2/trans.c
  34. +8 −4 fs/inode.c
  35. +4 −0 fs/internal.h
  36. +7 −7 fs/lockd/clntproc.c
  37. +1 −0 fs/lockd/svc4proc.c
  38. +0 −1 fs/lockd/svclock.c
  39. +1 −0 fs/lockd/svcproc.c
  40. +213 −100 fs/namei.c
  41. +77 −20 fs/namespace.c
  42. +5 −4 fs/nfsd/nfs4recover.c
  43. +1 −0 fs/nfsd/nfsfh.c
  44. +8 −1 fs/nfsd/nfsproc.c
  45. +40 −39 fs/nfsd/vfs.c
  46. +9 −2 fs/nfsd/vfs.h
  47. +11 −7 fs/nilfs2/file.c
  48. +0 −2 fs/nilfs2/ioctl.c
  49. +4 −1 fs/nilfs2/segment.c
  50. +2 −1 fs/ntfs/file.c
  51. +9 −2 fs/ocfs2/file.c
  52. +12 −2 fs/ocfs2/ioctl.c
  53. +6 −1 fs/ocfs2/journal.c
  54. +2 −0 fs/ocfs2/mmap.c
  55. +1 −10 fs/ocfs2/refcounttree.c
  56. +9 −6 fs/open.c
  57. +26 −49 fs/pipe.c
  58. +3 −0 fs/splice.c
  59. +230 −22 fs/super.c
  60. +2 −0 fs/sysfs/bin.c
  61. +18 −0 fs/xfs/xfs_aops.c
  62. +7 −3 fs/xfs/xfs_file.c
  63. +52 −3 fs/xfs/xfs_ioctl.c
  64. +12 −0 fs/xfs/xfs_ioctl32.c
  65. +2 −2 fs/xfs/xfs_iomap.c
  66. +1 −1 fs/xfs/xfs_mount.c
  67. +0 −3 fs/xfs/xfs_mount.h
  68. +1 −1 fs/xfs/xfs_sync.c
  69. +14 −3 fs/xfs/xfs_trans.c
  70. +2 −0 fs/xfs/xfs_trans.h
  71. +4 −0 include/linux/audit.h
  72. +142 −12 include/linux/fs.h
  73. +1 −0 include/linux/mm.h
  74. +1 −0 include/linux/namei.h
  75. +1 −0 include/linux/nfsd/nfsfh.h
  76. +2 −0 include/linux/pipe_fs_i.h
  77. +21 −0 kernel/audit.c
  78. +18 −0 kernel/sysctl.c
  79. +7 −7 lib/percpu_counter.c
  80. +29 −2 mm/filemap.c
  81. +4 −2 mm/filemap_xip.c
  82. +7 −7 mm/memory.c
  83. +43 −50 net/unix/af_unix.c
  84. +4 −4 sound/sound_firmware.c
@@ -138,8 +138,8 @@ evict_inode:
put_super: write
write_super: read
sync_fs: read
-freeze_fs: read
-unfreeze_fs: read
+freeze_fs: write
+unfreeze_fs: write
statfs: maybe(read) (see below)
remount_fs: write
umount_begin: no
@@ -32,6 +32,8 @@ Currently, these files are in /proc/sys/fs:
- nr_open
- overflowuid
- overflowgid
+- protected_hardlinks
+- protected_symlinks
- suid_dumpable
- super-max
- super-nr
@@ -157,6 +159,46 @@ The default is 65534.
==============================================================
+protected_hardlinks:
+
+A long-standing class of security issues is the hardlink-based
+time-of-check-time-of-use race, most commonly seen in world-writable
+directories like /tmp. The common method of exploitation of this flaw
+is to cross privilege boundaries when following a given hardlink (i.e. a
+root process follows a hardlink created by another user). Additionally,
+on systems without separated partitions, this stops unauthorized users
+from "pinning" vulnerable setuid/setgid files against being upgraded by
+the administrator, or linking to special files.
+
+When set to "0", hardlink creation behavior is unrestricted.
+
+When set to "1" hardlinks cannot be created by users if they do not
+already own the source file, or do not have read/write access to it.
+
+This protection is based on the restrictions in Openwall and grsecurity.
+
+==============================================================
+
+protected_symlinks:
+
+A long-standing class of security issues is the symlink-based
+time-of-check-time-of-use race, most commonly seen in world-writable
+directories like /tmp. The common method of exploitation of this flaw
+is to cross privilege boundaries when following a given symlink (i.e. a
+root process follows a symlink belonging to another user). For a likely
+incomplete list of hundreds of examples across the years, please see:
+http://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=/tmp
+
+When set to "0", symlink following behavior is unrestricted.
+
+When set to "1" symlinks are permitted to be followed only when outside
+a sticky world-writable directory, or when the uid of the symlink and
+follower match, or when the directory owner matches the symlink's owner.
+
+This protection is based on the restrictions in Openwall and grsecurity.
+
+==============================================================
+
suid_dumpable:
This value can be used to query and set the core dump mode for setuid
@@ -186,10 +186,13 @@ static void spufs_prune_dir(struct dentry *dir)
static int spufs_rmdir(struct inode *parent, struct dentry *dir)
{
/* remove all entries */
+ int res;
spufs_prune_dir(dir);
d_drop(dir);
-
- return simple_rmdir(parent, dir);
+ res = simple_rmdir(parent, dir);
+ /* We have to give up the mm_struct */
+ spu_forget(SPUFS_I(dir->d_inode)->i_ctx);
+ return res;
}
static int spufs_fill_dir(struct dentry *dir,
@@ -245,9 +248,6 @@ static int spufs_dir_close(struct inode *inode, struct file *file)
mutex_unlock(&parent->i_mutex);
WARN_ON(ret);
- /* We have to give up the mm_struct */
- spu_forget(ctx);
-
return dcache_dir_close(inode, file);
}
@@ -450,28 +450,24 @@ spufs_create_context(struct inode *inode, struct dentry *dentry,
struct spu_context *neighbor;
struct path path = {.mnt = mnt, .dentry = dentry};
- ret = -EPERM;
if ((flags & SPU_CREATE_NOSCHED) &&
!capable(CAP_SYS_NICE))
- goto out_unlock;
+ return -EPERM;
- ret = -EINVAL;
if ((flags & (SPU_CREATE_NOSCHED | SPU_CREATE_ISOLATE))
== SPU_CREATE_ISOLATE)
- goto out_unlock;
+ return -EINVAL;
- ret = -ENODEV;
if ((flags & SPU_CREATE_ISOLATE) && !isolated_loader)
- goto out_unlock;
+ return -ENODEV;
gang = NULL;
neighbor = NULL;
affinity = flags & (SPU_CREATE_AFFINITY_MEM | SPU_CREATE_AFFINITY_SPU);
if (affinity) {
gang = SPUFS_I(inode)->i_gang;
- ret = -EINVAL;
if (!gang)
- goto out_unlock;
+ return -EINVAL;
mutex_lock(&gang->aff_mutex);
neighbor = spufs_assert_affinity(flags, gang, aff_filp);
if (IS_ERR(neighbor)) {
@@ -492,22 +488,12 @@ spufs_create_context(struct inode *inode, struct dentry *dentry,
}
ret = spufs_context_open(&path);
- if (ret < 0) {
+ if (ret < 0)
WARN_ON(spufs_rmdir(inode, dentry));
- if (affinity)
- mutex_unlock(&gang->aff_mutex);
- mutex_unlock(&inode->i_mutex);
- spu_forget(SPUFS_I(dentry->d_inode)->i_ctx);
- goto out;
- }
out_aff_unlock:
if (affinity)
mutex_unlock(&gang->aff_mutex);
-out_unlock:
- mutex_unlock(&inode->i_mutex);
-out:
- dput(dentry);
return ret;
}
@@ -580,18 +566,13 @@ static int spufs_create_gang(struct inode *inode,
int ret;
ret = spufs_mkgang(inode, dentry, mode & S_IRWXUGO);
- if (ret)
- goto out;
-
- ret = spufs_gang_open(&path);
- if (ret < 0) {
- int err = simple_rmdir(inode, dentry);
- WARN_ON(err);
+ if (!ret) {
+ ret = spufs_gang_open(&path);
+ if (ret < 0) {
+ int err = simple_rmdir(inode, dentry);
+ WARN_ON(err);
+ }
}
-
-out:
- mutex_unlock(&inode->i_mutex);
- dput(dentry);
return ret;
}
@@ -601,40 +582,32 @@ static struct file_system_type spufs_type;
long spufs_create(struct path *path, struct dentry *dentry,
unsigned int flags, umode_t mode, struct file *filp)
{
+ struct inode *dir = path->dentry->d_inode;
int ret;
- ret = -EINVAL;
/* check if we are on spufs */
if (path->dentry->d_sb->s_type != &spufs_type)
- goto out;
+ return -EINVAL;
/* don't accept undefined flags */
if (flags & (~SPU_CREATE_FLAG_ALL))
- goto out;
+ return -EINVAL;
/* only threads can be underneath a gang */
- if (path->dentry != path->dentry->d_sb->s_root) {
- if ((flags & SPU_CREATE_GANG) ||
- !SPUFS_I(path->dentry->d_inode)->i_gang)
- goto out;
- }
+ if (path->dentry != path->dentry->d_sb->s_root)
+ if ((flags & SPU_CREATE_GANG) || !SPUFS_I(dir)->i_gang)
+ return -EINVAL;
mode &= ~current_umask();
if (flags & SPU_CREATE_GANG)
- ret = spufs_create_gang(path->dentry->d_inode,
- dentry, path->mnt, mode);
+ ret = spufs_create_gang(dir, dentry, path->mnt, mode);
else
- ret = spufs_create_context(path->dentry->d_inode,
- dentry, path->mnt, flags, mode,
+ ret = spufs_create_context(dir, dentry, path->mnt, flags, mode,
filp);
if (ret >= 0)
- fsnotify_mkdir(path->dentry->d_inode, dentry);
- return ret;
+ fsnotify_mkdir(dir, dentry);
-out:
- mutex_unlock(&path->dentry->d_inode->i_mutex);
- dput(dentry);
return ret;
}
@@ -70,7 +70,7 @@ static long do_spu_create(const char __user *pathname, unsigned int flags,
ret = PTR_ERR(dentry);
if (!IS_ERR(dentry)) {
ret = spufs_create(&path, dentry, flags, mode, neighbor);
- path_put(&path);
+ done_path_create(&path, dentry);
}
return ret;
View
@@ -156,9 +156,7 @@ static int dev_mkdir(const char *name, umode_t mode)
if (!err)
/* mark as kernel-created inode */
dentry->d_inode->i_private = &thread;
- dput(dentry);
- mutex_unlock(&path.dentry->d_inode->i_mutex);
- path_put(&path);
+ done_path_create(&path, dentry);
return err;
}
@@ -218,10 +216,7 @@ static int handle_create(const char *nodename, umode_t mode, struct device *dev)
/* mark as kernel-created inode */
dentry->d_inode->i_private = &thread;
}
- dput(dentry);
-
- mutex_unlock(&path.dentry->d_inode->i_mutex);
- path_put(&path);
+ done_path_create(&path, dentry);
return err;
}
@@ -1188,7 +1188,7 @@ int brcmf_write_to_file(struct brcmf_pub *drvr, const u8 *buf, int size)
kfree(buf);
/* close file before return */
if (fp)
- filp_close(fp, current->files);
+ filp_close(fp, NULL);
/* restore previous address limit */
set_fs(old_fs);
View
@@ -157,12 +157,7 @@ static int create_worker_threads(struct bcm_mini_adapter *psAdapter)
static struct file *open_firmware_file(struct bcm_mini_adapter *Adapter, const char *path)
{
- struct file *flp = NULL;
- mm_segment_t oldfs;
- oldfs = get_fs();
- set_fs(get_ds());
- flp = filp_open(path, O_RDONLY, S_IRWXU);
- set_fs(oldfs);
+ struct file *flp = filp_open(path, O_RDONLY, S_IRWXU);
if (IS_ERR(flp)) {
pr_err(DRV_NAME "Unable To Open File %s, err %ld", path, PTR_ERR(flp));
flp = NULL;
@@ -183,14 +178,12 @@ static int BcmFileDownload(struct bcm_mini_adapter *Adapter, const char *path, u
{
int errorno = 0;
struct file *flp = NULL;
- mm_segment_t oldfs;
struct timeval tv = {0};
flp = open_firmware_file(Adapter, path);
if (!flp) {
- errorno = -ENOENT;
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Unable to Open %s\n", path);
- goto exit_download;
+ return -ENOENT;
}
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Opened file is = %s and length =0x%lx to be downloaded at =0x%x", path, (unsigned long)flp->f_dentry->d_inode->i_size, loc);
do_gettimeofday(&tv);
@@ -201,23 +194,15 @@ static int BcmFileDownload(struct bcm_mini_adapter *Adapter, const char *path, u
errorno = -EIO;
goto exit_download;
}
- oldfs = get_fs();
- set_fs(get_ds());
vfs_llseek(flp, 0, 0);
- set_fs(oldfs);
if (Adapter->bcm_file_readback_from_chip(Adapter->pvInterfaceAdapter, flp, loc)) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Failed to read back firmware!");
errorno = -EIO;
goto exit_download;
}
exit_download:
- oldfs = get_fs();
- set_fs(get_ds());
- if (flp && !(IS_ERR(flp)))
- filp_close(flp, current->files);
- set_fs(oldfs);
-
+ filp_close(flp, NULL);
return errorno;
}
@@ -1056,10 +1041,8 @@ int InitCardAndDownloadFirmware(struct bcm_mini_adapter *ps_adapter)
static int bcm_parse_target_params(struct bcm_mini_adapter *Adapter)
{
struct file *flp = NULL;
- mm_segment_t oldfs = {0};
char *buff;
int len = 0;
- loff_t pos = 0;
buff = kmalloc(BUFFER_1K, GFP_KERNEL);
if (!buff)
@@ -1079,20 +1062,16 @@ static int bcm_parse_target_params(struct bcm_mini_adapter *Adapter)
Adapter->pstargetparams = NULL;
return -ENOENT;
}
- oldfs = get_fs();
- set_fs(get_ds());
- len = vfs_read(flp, (void __user __force *)buff, BUFFER_1K, &pos);
- set_fs(oldfs);
+ len = kernel_read(flp, 0, buff, BUFFER_1K);
+ filp_close(flp, NULL);
if (len != sizeof(STARGETPARAMS)) {
BCM_DEBUG_PRINT(Adapter, DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL, "Mismatch in Target Param Structure!\n");
kfree(buff);
kfree(Adapter->pstargetparams);
Adapter->pstargetparams = NULL;
- filp_close(flp, current->files);
return -ENOENT;
}
- filp_close(flp, current->files);
/* Check for autolink in config params */
/*
@@ -66,9 +66,8 @@ static int download_image(struct sdio_func *func, char *img_name)
return -ENOENT;
}
- if (filp->f_dentry)
- inode = filp->f_dentry->d_inode;
- if (!inode || !S_ISREG(inode->i_mode)) {
+ inode = filp->f_dentry->d_inode;
+ if (!S_ISREG(inode->i_mode)) {
printk(KERN_ERR "Invalid file type: %s\n", img_name);
ret = -EINVAL;
goto out;
@@ -123,7 +122,7 @@ static int download_image(struct sdio_func *func, char *img_name)
pno++;
}
out:
- filp_close(filp, current->files);
+ filp_close(filp, NULL);
return ret;
}
Oops, something went wrong.

0 comments on commit a0e881b

Please sign in to comment.