From 1df9f0a73178718969ae47d813b8e7aab2cf073c Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Wed, 4 Feb 2009 09:07:02 -0500 Subject: Integrity: IMA file free imbalance The number of calls to ima_path_check()/ima_file_free() should be balanced. An extra call to fput(), indicates the file could have been accessed without first being measured. Although f_count is incremented/decremented in places other than fget/fput, like fget_light/fput_light and get_file, the current task must already hold a file refcnt. The call to __fput() is delayed until the refcnt becomes 0, resulting in ima_file_free() flagging any changes. - add hook to increment opencount for IPC shared memory(SYSV), shmat files, and /dev/zero - moved NULL iint test in opencount_get() Signed-off-by: Mimi Zohar Acked-by: Serge Hallyn Signed-off-by: James Morris --- ipc/shm.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'ipc') diff --git a/ipc/shm.c b/ipc/shm.c index 38a055758a9b..d39bd7637b1c 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -39,6 +39,7 @@ #include #include #include +#include #include @@ -381,6 +382,7 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params) error = PTR_ERR(file); if (IS_ERR(file)) goto no_file; + ima_shm_check(file); id = ipc_addid(&shm_ids(ns), &shp->shm_perm, ns->shm_ctlmni); if (id < 0) { @@ -888,6 +890,7 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr) file = alloc_file(path.mnt, path.dentry, f_mode, &shm_file_operations); if (!file) goto out_free; + ima_shm_check(file); file->private_data = sfd; file->f_mapping = shp->shm_file->f_mapping; -- cgit v1.2.3 From db1dd4d376134eba0e08af523b61cc566a4ea1cd Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Fri, 6 Feb 2009 15:25:24 -0700 Subject: Use f_lock to protect f_flags Traditionally, changes to struct file->f_flags have been done under BKL protection, or with no protection at all. This patch causes all f_flags changes after file open/creation time to be done under protection of f_lock. This allows the removal of some BKL usage and fixes a number of longstanding (if microscopic) races. Reviewed-by: Christoph Hellwig Cc: Al Viro Signed-off-by: Jonathan Corbet --- drivers/char/tty_io.c | 5 ++--- drivers/usb/gadget/file_storage.c | 7 ++++++- fs/fcntl.c | 2 ++ fs/ioctl.c | 7 ++++--- fs/nfsd/vfs.c | 5 ++++- include/linux/fs.h | 2 +- ipc/mqueue.c | 2 ++ sound/core/oss/pcm_oss.c | 2 ++ sound/oss/au1550_ac97.c | 2 ++ sound/oss/audio.c | 2 ++ sound/oss/sh_dac_audio.c | 2 ++ sound/oss/swarm_cs4297a.c | 2 ++ sound/oss/vwsnd.c | 2 ++ 13 files changed, 33 insertions(+), 9 deletions(-) (limited to 'ipc') diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index bc84e125c6bc..224f271d8cbe 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -2162,13 +2162,12 @@ static int fionbio(struct file *file, int __user *p) if (get_user(nonblock, p)) return -EFAULT; - /* file->f_flags is still BKL protected in the fs layer - vomit */ - lock_kernel(); + spin_lock(&file->f_lock); if (nonblock) file->f_flags |= O_NONBLOCK; else file->f_flags &= ~O_NONBLOCK; - unlock_kernel(); + spin_unlock(&file->f_lock); return 0; } diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index 1ab9dac7e12d..33bb76cef33c 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -1711,7 +1711,9 @@ static int do_write(struct fsg_dev *fsg) curlun->sense_data = SS_WRITE_PROTECTED; return -EINVAL; } + spin_lock(&curlun->filp->f_lock); curlun->filp->f_flags &= ~O_SYNC; // Default is not to wait + spin_unlock(&curlun->filp->f_lock); /* Get the starting Logical Block Address and check that it's * not too big */ @@ -1728,8 +1730,11 @@ static int do_write(struct fsg_dev *fsg) curlun->sense_data = SS_INVALID_FIELD_IN_CDB; return -EINVAL; } - if (fsg->cmnd[1] & 0x08) // FUA + if (fsg->cmnd[1] & 0x08) { // FUA + spin_lock(&curlun->filp->f_lock); curlun->filp->f_flags |= O_SYNC; + spin_unlock(&curlun->filp->f_lock); + } } if (lba >= curlun->num_sectors) { curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; diff --git a/fs/fcntl.c b/fs/fcntl.c index bd215cc791da..04df8570a2d2 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -189,7 +189,9 @@ static int setfl(int fd, struct file * filp, unsigned long arg) } } + spin_lock(&filp->f_lock); filp->f_flags = (arg & SETFL_MASK) | (filp->f_flags & ~SETFL_MASK); + spin_unlock(&filp->f_lock); out: unlock_kernel(); return error; diff --git a/fs/ioctl.c b/fs/ioctl.c index 240ec63984cb..421aab465dab 100644 --- a/fs/ioctl.c +++ b/fs/ioctl.c @@ -404,10 +404,12 @@ static int ioctl_fionbio(struct file *filp, int __user *argp) if (O_NONBLOCK != O_NDELAY) flag |= O_NDELAY; #endif + spin_lock(&filp->f_lock); if (on) filp->f_flags |= flag; else filp->f_flags &= ~flag; + spin_unlock(&filp->f_lock); return error; } @@ -432,10 +434,12 @@ static int ioctl_fioasync(unsigned int fd, struct file *filp, if (error) return error; + spin_lock(&filp->f_lock); if (on) filp->f_flags |= FASYNC; else filp->f_flags &= ~FASYNC; + spin_unlock(&filp->f_lock); return error; } @@ -499,10 +503,7 @@ int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, break; case FIONBIO: - /* BKL needed to avoid races tweaking f_flags */ - lock_kernel(); error = ioctl_fionbio(filp, argp); - unlock_kernel(); break; case FIOASYNC: diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 6e50aaa56ca2..c165a6403df0 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -998,8 +998,11 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, if (!EX_ISSYNC(exp)) stable = 0; - if (stable && !EX_WGATHER(exp)) + if (stable && !EX_WGATHER(exp)) { + spin_lock(&file->f_lock); file->f_flags |= O_SYNC; + spin_unlock(&file->f_lock); + } /* Write the data. */ oldfs = get_fs(); set_fs(KERNEL_DS); diff --git a/include/linux/fs.h b/include/linux/fs.h index 2011600d12c7..7428c6d35e65 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -848,7 +848,7 @@ struct file { #define f_dentry f_path.dentry #define f_vfsmnt f_path.mnt const struct file_operations *f_op; - spinlock_t f_lock; /* f_ep_links */ + spinlock_t f_lock; /* f_ep_links, f_flags */ atomic_long_t f_count; unsigned int f_flags; fmode_t f_mode; diff --git a/ipc/mqueue.c b/ipc/mqueue.c index 54b4077fed79..a8ddadbc7459 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -1156,10 +1156,12 @@ SYSCALL_DEFINE3(mq_getsetattr, mqd_t, mqdes, omqstat.mq_flags = filp->f_flags & O_NONBLOCK; if (u_mqstat) { audit_mq_getsetattr(mqdes, &mqstat); + spin_lock(&filp->f_lock); if (mqstat.mq_flags & O_NONBLOCK) filp->f_flags |= O_NONBLOCK; else filp->f_flags &= ~O_NONBLOCK; + spin_unlock(&filp->f_lock); inode->i_atime = inode->i_ctime = CURRENT_TIME; } diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 0a1798eafb0b..d4460f18e76c 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -1895,7 +1895,9 @@ static int snd_pcm_oss_set_fragment(struct snd_pcm_oss_file *pcm_oss_file, unsig static int snd_pcm_oss_nonblock(struct file * file) { + spin_lock(&file->f_lock); file->f_flags |= O_NONBLOCK; + spin_unlock(&file->f_lock); return 0; } diff --git a/sound/oss/au1550_ac97.c b/sound/oss/au1550_ac97.c index 81e1f443d094..4191acccbcdb 100644 --- a/sound/oss/au1550_ac97.c +++ b/sound/oss/au1550_ac97.c @@ -1627,7 +1627,9 @@ au1550_ioctl(struct inode *inode, struct file *file, unsigned int cmd, sizeof(abinfo)) ? -EFAULT : 0; case SNDCTL_DSP_NONBLOCK: + spin_lock(&file->f_lock); file->f_flags |= O_NONBLOCK; + spin_unlock(&file->f_lock); return 0; case SNDCTL_DSP_GETODELAY: diff --git a/sound/oss/audio.c b/sound/oss/audio.c index 89bd27a5e865..b69c05b7ea7b 100644 --- a/sound/oss/audio.c +++ b/sound/oss/audio.c @@ -433,7 +433,9 @@ int audio_ioctl(int dev, struct file *file, unsigned int cmd, void __user *arg) return dma_ioctl(dev, cmd, arg); case SNDCTL_DSP_NONBLOCK: + spin_lock(&file->f_lock); file->f_flags |= O_NONBLOCK; + spin_unlock(&file->f_lock); return 0; case SNDCTL_DSP_GETCAPS: diff --git a/sound/oss/sh_dac_audio.c b/sound/oss/sh_dac_audio.c index e5d423994918..78cfb66e4c59 100644 --- a/sound/oss/sh_dac_audio.c +++ b/sound/oss/sh_dac_audio.c @@ -135,7 +135,9 @@ static int dac_audio_ioctl(struct inode *inode, struct file *file, return put_user(AFMT_U8, (int *)arg); case SNDCTL_DSP_NONBLOCK: + spin_lock(&file->f_lock); file->f_flags |= O_NONBLOCK; + spin_unlock(&file->f_lock); return 0; case SNDCTL_DSP_GETCAPS: diff --git a/sound/oss/swarm_cs4297a.c b/sound/oss/swarm_cs4297a.c index 41562ecde5bb..1edab7b4ea83 100644 --- a/sound/oss/swarm_cs4297a.c +++ b/sound/oss/swarm_cs4297a.c @@ -2200,7 +2200,9 @@ static int cs4297a_ioctl(struct inode *inode, struct file *file, sizeof(abinfo)) ? -EFAULT : 0; case SNDCTL_DSP_NONBLOCK: + spin_lock(&file->f_lock); file->f_flags |= O_NONBLOCK; + spin_unlock(&file->f_lock); return 0; case SNDCTL_DSP_GETODELAY: diff --git a/sound/oss/vwsnd.c b/sound/oss/vwsnd.c index 78b8acc7c3b9..187f72750e8f 100644 --- a/sound/oss/vwsnd.c +++ b/sound/oss/vwsnd.c @@ -2673,7 +2673,9 @@ static int vwsnd_audio_do_ioctl(struct inode *inode, case SNDCTL_DSP_NONBLOCK: /* _SIO ('P',14) */ DBGX("SNDCTL_DSP_NONBLOCK\n"); + spin_lock(&file->f_lock); file->f_flags |= O_NONBLOCK; + spin_unlock(&file->f_lock); return 0; case SNDCTL_DSP_RESET: /* _SIO ('P', 0) */ -- cgit v1.2.3 From ce3b0f8d5c2203301fc87f3aaaed73e5819e2a48 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 29 Mar 2009 19:08:22 -0400 Subject: New helper - current_umask() current->fs->umask is what most of fs_struct users are doing. Put that into a helper function. Signed-off-by: Al Viro --- arch/powerpc/platforms/cell/spufs/inode.c | 2 +- fs/btrfs/acl.c | 2 +- fs/btrfs/ioctl.c | 2 +- fs/cifs/dir.c | 4 ++-- fs/cifs/inode.c | 4 ++-- fs/ext2/acl.c | 2 +- fs/ext3/acl.c | 2 +- fs/ext4/acl.c | 2 +- fs/fat/inode.c | 2 +- fs/fs_struct.c | 6 ++++++ fs/generic_acl.c | 2 +- fs/gfs2/acl.c | 2 +- fs/hfsplus/options.c | 2 +- fs/hpfs/super.c | 2 +- fs/jffs2/acl.c | 2 +- fs/jfs/acl.c | 2 +- fs/namei.c | 6 +++--- fs/nfs/nfs3proc.c | 6 +++--- fs/nfs/nfs4proc.c | 2 +- fs/ocfs2/acl.c | 2 +- fs/omfs/inode.c | 2 +- fs/reiserfs/xattr_acl.c | 2 +- fs/xfs/linux-2.6/xfs_iops.c | 4 ++-- include/linux/fs.h | 2 ++ ipc/mqueue.c | 2 +- net/unix/af_unix.c | 2 +- 26 files changed, 39 insertions(+), 31 deletions(-) (limited to 'ipc') diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index 64f068540d0d..706eb5c7e2ee 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c @@ -635,7 +635,7 @@ long spufs_create(struct nameidata *nd, unsigned int flags, mode_t mode, if (dentry->d_inode) goto out_dput; - mode &= ~current->fs->umask; + mode &= ~current_umask(); if (flags & SPU_CREATE_GANG) ret = spufs_create_gang(nd->path.dentry->d_inode, diff --git a/fs/btrfs/acl.c b/fs/btrfs/acl.c index 1d53b62dbba5..7fdd184a528d 100644 --- a/fs/btrfs/acl.c +++ b/fs/btrfs/acl.c @@ -256,7 +256,7 @@ int btrfs_init_acl(struct inode *inode, struct inode *dir) } if (!acl) - inode->i_mode &= ~current->fs->umask; + inode->i_mode &= ~current_umask(); } if (IS_POSIXACL(dir) && acl) { diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index bca729fc80c8..7594bec1be10 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -267,7 +267,7 @@ static noinline int btrfs_mksubvol(struct path *parent, char *name, goto out_dput; if (!IS_POSIXACL(parent->dentry->d_inode)) - mode &= ~current->fs->umask; + mode &= ~current_umask(); error = mnt_want_write(parent->mnt); if (error) diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 2f35cccfcd8d..54dce78fbb73 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -254,7 +254,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, return -ENOMEM; } - mode &= ~current->fs->umask; + mode &= ~current_umask(); if (oplockEnabled) oplock = REQ_OPLOCK; @@ -479,7 +479,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, rc = -ENOMEM; else if (pTcon->unix_ext) { struct cifs_unix_set_info_args args = { - .mode = mode & ~current->fs->umask, + .mode = mode & ~current_umask(), .ctime = NO_CHANGE_64, .atime = NO_CHANGE_64, .mtime = NO_CHANGE_64, diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index a8797cc60805..f121a80fdd6f 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -1125,7 +1125,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) goto mkdir_out; } - mode &= ~current->fs->umask; + mode &= ~current_umask(); rc = CIFSPOSIXCreate(xid, pTcon, SMB_O_DIRECTORY | SMB_O_CREAT, mode, NULL /* netfid */, pInfo, &oplock, full_path, cifs_sb->local_nls, @@ -1204,7 +1204,7 @@ mkdir_get_info: if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2)) direntry->d_inode->i_nlink = 2; - mode &= ~current->fs->umask; + mode &= ~current_umask(); /* must turn on setgid bit if parent dir has it */ if (inode->i_mode & S_ISGID) mode |= S_ISGID; diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c index ae8c4f850b27..d46e38cb85c5 100644 --- a/fs/ext2/acl.c +++ b/fs/ext2/acl.c @@ -318,7 +318,7 @@ ext2_init_acl(struct inode *inode, struct inode *dir) return PTR_ERR(acl); } if (!acl) - inode->i_mode &= ~current->fs->umask; + inode->i_mode &= ~current_umask(); } if (test_opt(inode->i_sb, POSIX_ACL) && acl) { struct posix_acl *clone; diff --git a/fs/ext3/acl.c b/fs/ext3/acl.c index b60bb241880c..d81ef2fdb08e 100644 --- a/fs/ext3/acl.c +++ b/fs/ext3/acl.c @@ -323,7 +323,7 @@ ext3_init_acl(handle_t *handle, struct inode *inode, struct inode *dir) return PTR_ERR(acl); } if (!acl) - inode->i_mode &= ~current->fs->umask; + inode->i_mode &= ~current_umask(); } if (test_opt(inode->i_sb, POSIX_ACL) && acl) { struct posix_acl *clone; diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c index 694ed6fadcc8..647e0d65a284 100644 --- a/fs/ext4/acl.c +++ b/fs/ext4/acl.c @@ -323,7 +323,7 @@ ext4_init_acl(handle_t *handle, struct inode *inode, struct inode *dir) return PTR_ERR(acl); } if (!acl) - inode->i_mode &= ~current->fs->umask; + inode->i_mode &= ~current_umask(); } if (test_opt(inode->i_sb, POSIX_ACL) && acl) { struct posix_acl *clone; diff --git a/fs/fat/inode.c b/fs/fat/inode.c index de0004fe6e00..ab657db4c94e 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -930,7 +930,7 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug, opts->fs_uid = current_uid(); opts->fs_gid = current_gid(); - opts->fs_fmask = opts->fs_dmask = current->fs->umask; + opts->fs_fmask = current_umask(); opts->allow_utime = -1; opts->codepage = fat_default_codepage; opts->iocharset = fat_default_iocharset; diff --git a/fs/fs_struct.c b/fs/fs_struct.c index 41cff72b377b..6ac219338670 100644 --- a/fs/fs_struct.c +++ b/fs/fs_struct.c @@ -138,6 +138,12 @@ int unshare_fs_struct(void) } EXPORT_SYMBOL_GPL(unshare_fs_struct); +int current_umask(void) +{ + return current->fs->umask; +} +EXPORT_SYMBOL(current_umask); + /* to be mentioned only in INIT_TASK */ struct fs_struct init_fs = { .users = 1, diff --git a/fs/generic_acl.c b/fs/generic_acl.c index 995d63b2e747..e0b53aa7bbec 100644 --- a/fs/generic_acl.c +++ b/fs/generic_acl.c @@ -134,7 +134,7 @@ generic_acl_init(struct inode *inode, struct inode *dir, mode_t mode = inode->i_mode; int error; - inode->i_mode = mode & ~current->fs->umask; + inode->i_mode = mode & ~current_umask(); if (!S_ISLNK(inode->i_mode)) acl = ops->getacl(dir, ACL_TYPE_DEFAULT); if (acl) { diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c index 43764f4fa763..fa881bdc3d85 100644 --- a/fs/gfs2/acl.c +++ b/fs/gfs2/acl.c @@ -215,7 +215,7 @@ int gfs2_acl_create(struct gfs2_inode *dip, struct gfs2_inode *ip) if (error) return error; if (!acl) { - mode &= ~current->fs->umask; + mode &= ~current_umask(); if (mode != ip->i_inode.i_mode) error = munge_mode(ip, mode); return error; diff --git a/fs/hfsplus/options.c b/fs/hfsplus/options.c index bab7f8d1bdfa..3fcbb0e1f6fc 100644 --- a/fs/hfsplus/options.c +++ b/fs/hfsplus/options.c @@ -48,7 +48,7 @@ void hfsplus_fill_defaults(struct hfsplus_sb_info *opts) opts->creator = HFSPLUS_DEF_CR_TYPE; opts->type = HFSPLUS_DEF_CR_TYPE; - opts->umask = current->fs->umask; + opts->umask = current_umask(); opts->uid = current_uid(); opts->gid = current_gid(); opts->part = -1; diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c index 0d049b8919c4..c696d01bc8f7 100644 --- a/fs/hpfs/super.c +++ b/fs/hpfs/super.c @@ -477,7 +477,7 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent) uid = current_uid(); gid = current_gid(); - umask = current->fs->umask; + umask = current_umask(); lowercase = 0; conv = CONV_BINARY; eas = 2; diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c index d98713777a1b..77ccf8cb0823 100644 --- a/fs/jffs2/acl.c +++ b/fs/jffs2/acl.c @@ -336,7 +336,7 @@ int jffs2_init_acl_pre(struct inode *dir_i, struct inode *inode, int *i_mode) return PTR_ERR(acl); if (!acl) { - *i_mode &= ~current->fs->umask; + *i_mode &= ~current_umask(); } else { if (S_ISDIR(*i_mode)) jffs2_iset_acl(inode, &f->i_acl_default, acl); diff --git a/fs/jfs/acl.c b/fs/jfs/acl.c index a166c1669e82..06ca1b8d2054 100644 --- a/fs/jfs/acl.c +++ b/fs/jfs/acl.c @@ -182,7 +182,7 @@ int jfs_init_acl(tid_t tid, struct inode *inode, struct inode *dir) cleanup: posix_acl_release(acl); } else - inode->i_mode &= ~current->fs->umask; + inode->i_mode &= ~current_umask(); JFS_IP(inode)->mode2 = (JFS_IP(inode)->mode2 & 0xffff0000) | inode->i_mode; diff --git a/fs/namei.c b/fs/namei.c index 4c65a6460138..964c0249444b 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1578,7 +1578,7 @@ static int __open_namei_create(struct nameidata *nd, struct path *path, struct dentry *dir = nd->path.dentry; if (!IS_POSIXACL(dir->d_inode)) - mode &= ~current->fs->umask; + mode &= ~current_umask(); error = security_path_mknod(&nd->path, path->dentry, mode, 0); if (error) goto out_unlock; @@ -1989,7 +1989,7 @@ SYSCALL_DEFINE4(mknodat, int, dfd, const char __user *, filename, int, mode, goto out_unlock; } if (!IS_POSIXACL(nd.path.dentry->d_inode)) - mode &= ~current->fs->umask; + mode &= ~current_umask(); error = may_mknod(mode); if (error) goto out_dput; @@ -2067,7 +2067,7 @@ SYSCALL_DEFINE3(mkdirat, int, dfd, const char __user *, pathname, int, mode) goto out_unlock; if (!IS_POSIXACL(nd.path.dentry->d_inode)) - mode &= ~current->fs->umask; + mode &= ~current_umask(); error = mnt_want_write(nd.path.mnt); if (error) goto out_dput; diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index c55be7a7679e..e47d4400fb87 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c @@ -328,7 +328,7 @@ nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, data->arg.create.verifier[1] = current->pid; } - sattr->ia_mode &= ~current->fs->umask; + sattr->ia_mode &= ~current_umask(); for (;;) { status = nfs3_do_create(dir, dentry, data); @@ -528,7 +528,7 @@ nfs3_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr) dprintk("NFS call mkdir %s\n", dentry->d_name.name); - sattr->ia_mode &= ~current->fs->umask; + sattr->ia_mode &= ~current_umask(); data = nfs3_alloc_createdata(); if (data == NULL) @@ -639,7 +639,7 @@ nfs3_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr, dprintk("NFS call mknod %s %u:%u\n", dentry->d_name.name, MAJOR(rdev), MINOR(rdev)); - sattr->ia_mode &= ~current->fs->umask; + sattr->ia_mode &= ~current_umask(); data = nfs3_alloc_createdata(); if (data == NULL) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 8dde84b988d9..bbee587dd597 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -1509,7 +1509,7 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd) attr.ia_mode = nd->intent.open.create_mode; attr.ia_valid = ATTR_MODE; if (!IS_POSIXACL(dir)) - attr.ia_mode &= ~current->fs->umask; + attr.ia_mode &= ~current_umask(); } else { attr.ia_valid = 0; BUG_ON(nd->intent.open.flags & O_CREAT); diff --git a/fs/ocfs2/acl.c b/fs/ocfs2/acl.c index 12dfb44c22e5..fbeaec762103 100644 --- a/fs/ocfs2/acl.c +++ b/fs/ocfs2/acl.c @@ -296,7 +296,7 @@ int ocfs2_init_acl(handle_t *handle, return PTR_ERR(acl); } if (!acl) - inode->i_mode &= ~current->fs->umask; + inode->i_mode &= ~current_umask(); } if ((osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) && acl) { struct posix_acl *clone; diff --git a/fs/omfs/inode.c b/fs/omfs/inode.c index 633e9dc972bb..aa6fc30772af 100644 --- a/fs/omfs/inode.c +++ b/fs/omfs/inode.c @@ -421,7 +421,7 @@ static int omfs_fill_super(struct super_block *sb, void *data, int silent) sbi->s_uid = current_uid(); sbi->s_gid = current_gid(); - sbi->s_dmask = sbi->s_fmask = current->fs->umask; + sbi->s_dmask = sbi->s_fmask = current_umask(); if (!parse_options((char *) data, sbi)) goto end; diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c index d423416d93d1..c303c426fe2b 100644 --- a/fs/reiserfs/xattr_acl.c +++ b/fs/reiserfs/xattr_acl.c @@ -428,7 +428,7 @@ reiserfs_inherit_default_acl(struct reiserfs_transaction_handle *th, } else { apply_umask: /* no ACL, apply umask */ - inode->i_mode &= ~current->fs->umask; + inode->i_mode &= ~current_umask(); } return err; diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index 7aa53fefc67f..2940612e3aeb 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c @@ -227,7 +227,7 @@ xfs_vn_mknod( xfs_dentry_to_name(&name, dentry); if (IS_POSIXACL(dir) && !default_acl) - mode &= ~current->fs->umask; + mode &= ~current_umask(); switch (mode & S_IFMT) { case S_IFCHR: @@ -416,7 +416,7 @@ xfs_vn_symlink( mode_t mode; mode = S_IFLNK | - (irix_symlink_mode ? 0777 & ~current->fs->umask : S_IRWXUGO); + (irix_symlink_mode ? 0777 & ~current_umask() : S_IRWXUGO); xfs_dentry_to_name(&name, dentry); error = xfs_symlink(XFS_I(dir), &name, symname, mode, &cip, NULL); diff --git a/include/linux/fs.h b/include/linux/fs.h index 87e7bfc5ebd7..3d7bd5447ca3 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1741,6 +1741,8 @@ extern void drop_collected_mounts(struct vfsmount *); extern int vfs_statfs(struct dentry *, struct kstatfs *); +extern int current_umask(void); + /* /sys/fs */ extern struct kobject *fs_kobj; diff --git a/ipc/mqueue.c b/ipc/mqueue.c index a8ddadbc7459..916785363f0f 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -602,7 +602,7 @@ static struct file *do_create(struct dentry *dir, struct dentry *dentry, dentry->d_fsdata = attr; } - mode &= ~current->fs->umask; + mode &= ~current_umask(); ret = mnt_want_write(mqueue_mnt); if (ret) goto out; diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index baac91049b0e..9dcc6e7f96ec 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -832,7 +832,7 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) * All right, let's create it. */ mode = S_IFSOCK | - (SOCK_INODE(sock)->i_mode & ~current->fs->umask); + (SOCK_INODE(sock)->i_mode & ~current_umask()); err = mnt_want_write(nd.path.mnt); if (err) goto out_mknod_dput; -- cgit v1.2.3 From e562aebc6ccd4385cbbf24debe88ab4bb500c5b4 Mon Sep 17 00:00:00 2001 From: Tony Battersby Date: Thu, 2 Apr 2009 16:58:26 -0700 Subject: ipc: make shm_get_stat() more robust shm_get_stat() assumes idr_find(&shm_ids(ns).ipcs_idr) returns "struct shmid_kernel *"; all other callers assume that it returns "struct kern_ipc_perm *". This works because "struct kern_ipc_perm" is currently the first member of "struct shmid_kernel", but it would be better to use container_of() to prevent future breakage. Signed-off-by: Tony Battersby Cc: Jiri Olsa Cc: Jiri Kosina Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- ipc/shm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'ipc') diff --git a/ipc/shm.c b/ipc/shm.c index f239d87e0d37..faa46da99ebe 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -555,12 +555,14 @@ static void shm_get_stat(struct ipc_namespace *ns, unsigned long *rss, in_use = shm_ids(ns).in_use; for (total = 0, next_id = 0; total < in_use; next_id++) { + struct kern_ipc_perm *ipc; struct shmid_kernel *shp; struct inode *inode; - shp = idr_find(&shm_ids(ns).ipcs_idr, next_id); - if (shp == NULL) + ipc = idr_find(&shm_ids(ns).ipcs_idr, next_id); + if (ipc == NULL) continue; + shp = container_of(ipc, struct shmid_kernel, shm_perm); inode = shp->shm_file->f_path.dentry->d_inode; -- cgit v1.2.3 From 11dea1900931ac73184b2f5163a13d24a4e572ea Mon Sep 17 00:00:00 2001 From: "Serge E. Hallyn" Date: Thu, 2 Apr 2009 16:58:27 -0700 Subject: proc_sysctl: use CONFIG_PROC_SYSCTL around ipc and utsname proc_handlers As pointed out by Cedric Le Goater (in response to Alexey's original comment wrt mqns), ipc_sysctl.c and utsname_sysctl.c are using CONFIG_PROC_FS, not CONFIG_PROC_SYSCTL, to determine whether to define the proc_handlers. Change that. Signed-off-by: Serge E. Hallyn Cc: Cedric Le Goater Acked-by: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- ipc/ipc_sysctl.c | 2 +- kernel/utsname_sysctl.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'ipc') diff --git a/ipc/ipc_sysctl.c b/ipc/ipc_sysctl.c index 4a7a12c95abe..40eab7314aeb 100644 --- a/ipc/ipc_sysctl.c +++ b/ipc/ipc_sysctl.c @@ -26,7 +26,7 @@ static void *get_ipc(ctl_table *table) return which; } -#ifdef CONFIG_PROC_FS +#ifdef CONFIG_PROC_SYSCTL static int proc_ipc_dointvec(ctl_table *table, int write, struct file *filp, void __user *buffer, size_t *lenp, loff_t *ppos) { diff --git a/kernel/utsname_sysctl.c b/kernel/utsname_sysctl.c index 3b34b3545936..92359cc747a7 100644 --- a/kernel/utsname_sysctl.c +++ b/kernel/utsname_sysctl.c @@ -37,7 +37,7 @@ static void put_uts(ctl_table *table, int write, void *which) up_write(&uts_sem); } -#ifdef CONFIG_PROC_FS +#ifdef CONFIG_PROC_SYSCTL /* * Special case of dostring for the UTS structure. This has locks * to observe. Should this be in kernel/sys.c ???? -- cgit v1.2.3