Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/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
torvalds committed Aug 1, 2012
2 parents eff0d13 + dbc6e02 commit a0e881b
Show file tree
Hide file tree
Showing 84 changed files with 1,326 additions and 639 deletions.
4 changes: 2 additions & 2 deletions Documentation/filesystems/Locking
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
42 changes: 42 additions & 0 deletions Documentation/sysctl/fs.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
77 changes: 25 additions & 52 deletions arch/powerpc/platforms/cell/spufs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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)) {
Expand All @@ -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;
}

Expand Down Expand Up @@ -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;
}

Expand All @@ -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;
}

Expand Down
2 changes: 1 addition & 1 deletion arch/powerpc/platforms/cell/spufs/syscalls.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
9 changes: 2 additions & 7 deletions drivers/base/devtmpfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
}

Expand Down
2 changes: 1 addition & 1 deletion drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
31 changes: 5 additions & 26 deletions drivers/staging/bcm/Misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand All @@ -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;
}

Expand Down Expand Up @@ -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)
Expand All @@ -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 */
/*
Expand Down
7 changes: 3 additions & 4 deletions drivers/staging/gdm72xx/sdio_boot.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}

Expand Down
Loading

0 comments on commit a0e881b

Please sign in to comment.