diff options
| -rw-r--r-- | arch/powerpc/platforms/cell/spufs/inode.c | 18 | ||||
| -rw-r--r-- | fs/autofs4/dev-ioctl.c | 4 | ||||
| -rw-r--r-- | fs/cachefiles/rdwr.c | 8 | ||||
| -rw-r--r-- | fs/ecryptfs/kthread.c | 21 | ||||
| -rw-r--r-- | fs/exportfs/expfs.c | 13 | ||||
| -rw-r--r-- | fs/hppfs/hppfs.c | 20 | ||||
| -rw-r--r-- | fs/nfsd/vfs.c | 10 | ||||
| -rw-r--r-- | fs/notify/fanotify/fanotify_user.c | 8 | ||||
| -rw-r--r-- | fs/open.c | 17 | ||||
| -rw-r--r-- | fs/xfs/xfs_ioctl.c | 7 | ||||
| -rw-r--r-- | include/linux/fs.h | 3 | ||||
| -rw-r--r-- | ipc/mqueue.c | 117 | ||||
| -rw-r--r-- | security/selinux/hooks.c | 3 | ||||
| -rw-r--r-- | security/selinux/include/security.h | 2 | ||||
| -rw-r--r-- | security/selinux/selinuxfs.c | 6 |
15 files changed, 106 insertions, 151 deletions
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index 1c9cac0cf895..d544d7816df3 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c | |||
| @@ -317,7 +317,7 @@ out: | |||
| 317 | return ret; | 317 | return ret; |
| 318 | } | 318 | } |
| 319 | 319 | ||
| 320 | static int spufs_context_open(struct dentry *dentry, struct vfsmount *mnt) | 320 | static int spufs_context_open(struct path *path) |
| 321 | { | 321 | { |
| 322 | int ret; | 322 | int ret; |
| 323 | struct file *filp; | 323 | struct file *filp; |
| @@ -326,11 +326,7 @@ static int spufs_context_open(struct dentry *dentry, struct vfsmount *mnt) | |||
| 326 | if (ret < 0) | 326 | if (ret < 0) |
| 327 | return ret; | 327 | return ret; |
| 328 | 328 | ||
| 329 | /* | 329 | filp = dentry_open(path, O_RDONLY, current_cred()); |
| 330 | * get references for dget and mntget, will be released | ||
| 331 | * in error path of *_open(). | ||
| 332 | */ | ||
| 333 | filp = dentry_open(dget(dentry), mntget(mnt), O_RDONLY, current_cred()); | ||
| 334 | if (IS_ERR(filp)) { | 330 | if (IS_ERR(filp)) { |
| 335 | put_unused_fd(ret); | 331 | put_unused_fd(ret); |
| 336 | return PTR_ERR(filp); | 332 | return PTR_ERR(filp); |
| @@ -452,6 +448,7 @@ spufs_create_context(struct inode *inode, struct dentry *dentry, | |||
| 452 | int affinity; | 448 | int affinity; |
| 453 | struct spu_gang *gang; | 449 | struct spu_gang *gang; |
| 454 | struct spu_context *neighbor; | 450 | struct spu_context *neighbor; |
| 451 | struct path path = {.mnt = mnt, .dentry = dentry}; | ||
| 455 | 452 | ||
| 456 | ret = -EPERM; | 453 | ret = -EPERM; |
| 457 | if ((flags & SPU_CREATE_NOSCHED) && | 454 | if ((flags & SPU_CREATE_NOSCHED) && |
| @@ -494,7 +491,7 @@ spufs_create_context(struct inode *inode, struct dentry *dentry, | |||
| 494 | put_spu_context(neighbor); | 491 | put_spu_context(neighbor); |
| 495 | } | 492 | } |
| 496 | 493 | ||
| 497 | ret = spufs_context_open(dentry, mnt); | 494 | ret = spufs_context_open(&path); |
| 498 | if (ret < 0) { | 495 | if (ret < 0) { |
| 499 | WARN_ON(spufs_rmdir(inode, dentry)); | 496 | WARN_ON(spufs_rmdir(inode, dentry)); |
| 500 | if (affinity) | 497 | if (affinity) |
| @@ -551,7 +548,7 @@ out: | |||
| 551 | return ret; | 548 | return ret; |
| 552 | } | 549 | } |
| 553 | 550 | ||
| 554 | static int spufs_gang_open(struct dentry *dentry, struct vfsmount *mnt) | 551 | static int spufs_gang_open(struct path *path) |
| 555 | { | 552 | { |
| 556 | int ret; | 553 | int ret; |
| 557 | struct file *filp; | 554 | struct file *filp; |
| @@ -564,7 +561,7 @@ static int spufs_gang_open(struct dentry *dentry, struct vfsmount *mnt) | |||
| 564 | * get references for dget and mntget, will be released | 561 | * get references for dget and mntget, will be released |
| 565 | * in error path of *_open(). | 562 | * in error path of *_open(). |
| 566 | */ | 563 | */ |
| 567 | filp = dentry_open(dget(dentry), mntget(mnt), O_RDONLY, current_cred()); | 564 | filp = dentry_open(path, O_RDONLY, current_cred()); |
| 568 | if (IS_ERR(filp)) { | 565 | if (IS_ERR(filp)) { |
| 569 | put_unused_fd(ret); | 566 | put_unused_fd(ret); |
| 570 | return PTR_ERR(filp); | 567 | return PTR_ERR(filp); |
| @@ -579,13 +576,14 @@ static int spufs_create_gang(struct inode *inode, | |||
| 579 | struct dentry *dentry, | 576 | struct dentry *dentry, |
| 580 | struct vfsmount *mnt, umode_t mode) | 577 | struct vfsmount *mnt, umode_t mode) |
| 581 | { | 578 | { |
| 579 | struct path path = {.mnt = mnt, .dentry = dentry}; | ||
| 582 | int ret; | 580 | int ret; |
| 583 | 581 | ||
| 584 | ret = spufs_mkgang(inode, dentry, mode & S_IRWXUGO); | 582 | ret = spufs_mkgang(inode, dentry, mode & S_IRWXUGO); |
| 585 | if (ret) | 583 | if (ret) |
| 586 | goto out; | 584 | goto out; |
| 587 | 585 | ||
| 588 | ret = spufs_gang_open(dentry, mnt); | 586 | ret = spufs_gang_open(&path); |
| 589 | if (ret < 0) { | 587 | if (ret < 0) { |
| 590 | int err = simple_rmdir(inode, dentry); | 588 | int err = simple_rmdir(inode, dentry); |
| 591 | WARN_ON(err); | 589 | WARN_ON(err); |
diff --git a/fs/autofs4/dev-ioctl.c b/fs/autofs4/dev-ioctl.c index aa9103f8f01b..abf645c1703b 100644 --- a/fs/autofs4/dev-ioctl.c +++ b/fs/autofs4/dev-ioctl.c | |||
| @@ -257,8 +257,8 @@ static int autofs_dev_ioctl_open_mountpoint(const char *name, dev_t devid) | |||
| 257 | * corresponding to the autofs fs we want to open. | 257 | * corresponding to the autofs fs we want to open. |
| 258 | */ | 258 | */ |
| 259 | 259 | ||
| 260 | filp = dentry_open(path.dentry, path.mnt, O_RDONLY, | 260 | filp = dentry_open(&path, O_RDONLY, current_cred()); |
| 261 | current_cred()); | 261 | path_put(&path); |
| 262 | if (IS_ERR(filp)) { | 262 | if (IS_ERR(filp)) { |
| 263 | err = PTR_ERR(filp); | 263 | err = PTR_ERR(filp); |
| 264 | goto out; | 264 | goto out; |
diff --git a/fs/cachefiles/rdwr.c b/fs/cachefiles/rdwr.c index 0e3c0924cc3a..c0353dfac51f 100644 --- a/fs/cachefiles/rdwr.c +++ b/fs/cachefiles/rdwr.c | |||
| @@ -891,6 +891,7 @@ int cachefiles_write_page(struct fscache_storage *op, struct page *page) | |||
| 891 | struct cachefiles_cache *cache; | 891 | struct cachefiles_cache *cache; |
| 892 | mm_segment_t old_fs; | 892 | mm_segment_t old_fs; |
| 893 | struct file *file; | 893 | struct file *file; |
| 894 | struct path path; | ||
| 894 | loff_t pos, eof; | 895 | loff_t pos, eof; |
| 895 | size_t len; | 896 | size_t len; |
| 896 | void *data; | 897 | void *data; |
| @@ -916,10 +917,9 @@ int cachefiles_write_page(struct fscache_storage *op, struct page *page) | |||
| 916 | 917 | ||
| 917 | /* write the page to the backing filesystem and let it store it in its | 918 | /* write the page to the backing filesystem and let it store it in its |
| 918 | * own time */ | 919 | * own time */ |
| 919 | dget(object->backer); | 920 | path.mnt = cache->mnt; |
| 920 | mntget(cache->mnt); | 921 | path.dentry = object->backer; |
| 921 | file = dentry_open(object->backer, cache->mnt, O_RDWR, | 922 | file = dentry_open(&path, O_RDWR, cache->cache_cred); |
| 922 | cache->cache_cred); | ||
| 923 | if (IS_ERR(file)) { | 923 | if (IS_ERR(file)) { |
| 924 | ret = PTR_ERR(file); | 924 | ret = PTR_ERR(file); |
| 925 | } else { | 925 | } else { |
diff --git a/fs/ecryptfs/kthread.c b/fs/ecryptfs/kthread.c index c7d199dc7d24..809e67d05ca3 100644 --- a/fs/ecryptfs/kthread.c +++ b/fs/ecryptfs/kthread.c | |||
| @@ -29,8 +29,7 @@ | |||
| 29 | 29 | ||
| 30 | struct ecryptfs_open_req { | 30 | struct ecryptfs_open_req { |
| 31 | struct file **lower_file; | 31 | struct file **lower_file; |
| 32 | struct dentry *lower_dentry; | 32 | struct path path; |
| 33 | struct vfsmount *lower_mnt; | ||
| 34 | struct completion done; | 33 | struct completion done; |
| 35 | struct list_head kthread_ctl_list; | 34 | struct list_head kthread_ctl_list; |
| 36 | }; | 35 | }; |
| @@ -74,10 +73,7 @@ static int ecryptfs_threadfn(void *ignored) | |||
| 74 | struct ecryptfs_open_req, | 73 | struct ecryptfs_open_req, |
| 75 | kthread_ctl_list); | 74 | kthread_ctl_list); |
| 76 | list_del(&req->kthread_ctl_list); | 75 | list_del(&req->kthread_ctl_list); |
| 77 | dget(req->lower_dentry); | 76 | *req->lower_file = dentry_open(&req->path, |
| 78 | mntget(req->lower_mnt); | ||
| 79 | (*req->lower_file) = dentry_open( | ||
| 80 | req->lower_dentry, req->lower_mnt, | ||
| 81 | (O_RDWR | O_LARGEFILE), current_cred()); | 77 | (O_RDWR | O_LARGEFILE), current_cred()); |
| 82 | complete(&req->done); | 78 | complete(&req->done); |
| 83 | } | 79 | } |
| @@ -140,23 +136,22 @@ int ecryptfs_privileged_open(struct file **lower_file, | |||
| 140 | int flags = O_LARGEFILE; | 136 | int flags = O_LARGEFILE; |
| 141 | int rc = 0; | 137 | int rc = 0; |
| 142 | 138 | ||
| 139 | init_completion(&req.done); | ||
| 140 | req.lower_file = lower_file; | ||
| 141 | req.path.dentry = lower_dentry; | ||
| 142 | req.path.mnt = lower_mnt; | ||
| 143 | |||
| 143 | /* Corresponding dput() and mntput() are done when the | 144 | /* Corresponding dput() and mntput() are done when the |
| 144 | * lower file is fput() when all eCryptfs files for the inode are | 145 | * lower file is fput() when all eCryptfs files for the inode are |
| 145 | * released. */ | 146 | * released. */ |
| 146 | dget(lower_dentry); | ||
| 147 | mntget(lower_mnt); | ||
| 148 | flags |= IS_RDONLY(lower_dentry->d_inode) ? O_RDONLY : O_RDWR; | 147 | flags |= IS_RDONLY(lower_dentry->d_inode) ? O_RDONLY : O_RDWR; |
| 149 | (*lower_file) = dentry_open(lower_dentry, lower_mnt, flags, cred); | 148 | (*lower_file) = dentry_open(&req.path, flags, cred); |
| 150 | if (!IS_ERR(*lower_file)) | 149 | if (!IS_ERR(*lower_file)) |
| 151 | goto out; | 150 | goto out; |
| 152 | if ((flags & O_ACCMODE) == O_RDONLY) { | 151 | if ((flags & O_ACCMODE) == O_RDONLY) { |
| 153 | rc = PTR_ERR((*lower_file)); | 152 | rc = PTR_ERR((*lower_file)); |
| 154 | goto out; | 153 | goto out; |
| 155 | } | 154 | } |
| 156 | init_completion(&req.done); | ||
| 157 | req.lower_file = lower_file; | ||
| 158 | req.lower_dentry = lower_dentry; | ||
| 159 | req.lower_mnt = lower_mnt; | ||
| 160 | mutex_lock(&ecryptfs_kthread_ctl.mux); | 155 | mutex_lock(&ecryptfs_kthread_ctl.mux); |
| 161 | if (ecryptfs_kthread_ctl.flags & ECRYPTFS_KTHREAD_ZOMBIE) { | 156 | if (ecryptfs_kthread_ctl.flags & ECRYPTFS_KTHREAD_ZOMBIE) { |
| 162 | rc = -EIO; | 157 | rc = -EIO; |
diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c index b42063cf1b2d..29ab099e3e08 100644 --- a/fs/exportfs/expfs.c +++ b/fs/exportfs/expfs.c | |||
| @@ -19,19 +19,19 @@ | |||
| 19 | #define dprintk(fmt, args...) do{}while(0) | 19 | #define dprintk(fmt, args...) do{}while(0) |
| 20 | 20 | ||
| 21 | 21 | ||
| 22 | static int get_name(struct vfsmount *mnt, struct dentry *dentry, char *name, | 22 | static int get_name(const struct path *path, char *name, struct dentry *child); |
| 23 | struct dentry *child); | ||
| 24 | 23 | ||
| 25 | 24 | ||
| 26 | static int exportfs_get_name(struct vfsmount *mnt, struct dentry *dir, | 25 | static int exportfs_get_name(struct vfsmount *mnt, struct dentry *dir, |
| 27 | char *name, struct dentry *child) | 26 | char *name, struct dentry *child) |
| 28 | { | 27 | { |
| 29 | const struct export_operations *nop = dir->d_sb->s_export_op; | 28 | const struct export_operations *nop = dir->d_sb->s_export_op; |
| 29 | struct path path = {.mnt = mnt, .dentry = dir}; | ||
| 30 | 30 | ||
| 31 | if (nop->get_name) | 31 | if (nop->get_name) |
| 32 | return nop->get_name(dir, name, child); | 32 | return nop->get_name(dir, name, child); |
| 33 | else | 33 | else |
| 34 | return get_name(mnt, dir, name, child); | 34 | return get_name(&path, name, child); |
| 35 | } | 35 | } |
| 36 | 36 | ||
| 37 | /* | 37 | /* |
| @@ -249,11 +249,10 @@ static int filldir_one(void * __buf, const char * name, int len, | |||
| 249 | * calls readdir on the parent until it finds an entry with | 249 | * calls readdir on the parent until it finds an entry with |
| 250 | * the same inode number as the child, and returns that. | 250 | * the same inode number as the child, and returns that. |
| 251 | */ | 251 | */ |
| 252 | static int get_name(struct vfsmount *mnt, struct dentry *dentry, | 252 | static int get_name(const struct path *path, char *name, struct dentry *child) |
| 253 | char *name, struct dentry *child) | ||
| 254 | { | 253 | { |
| 255 | const struct cred *cred = current_cred(); | 254 | const struct cred *cred = current_cred(); |
| 256 | struct inode *dir = dentry->d_inode; | 255 | struct inode *dir = path->dentry->d_inode; |
| 257 | int error; | 256 | int error; |
| 258 | struct file *file; | 257 | struct file *file; |
| 259 | struct getdents_callback buffer; | 258 | struct getdents_callback buffer; |
| @@ -267,7 +266,7 @@ static int get_name(struct vfsmount *mnt, struct dentry *dentry, | |||
| 267 | /* | 266 | /* |
| 268 | * Open the directory ... | 267 | * Open the directory ... |
| 269 | */ | 268 | */ |
| 270 | file = dentry_open(dget(dentry), mntget(mnt), O_RDONLY, cred); | 269 | file = dentry_open(path, O_RDONLY, cred); |
| 271 | error = PTR_ERR(file); | 270 | error = PTR_ERR(file); |
| 272 | if (IS_ERR(file)) | 271 | if (IS_ERR(file)) |
| 273 | goto out; | 272 | goto out; |
diff --git a/fs/hppfs/hppfs.c b/fs/hppfs/hppfs.c index e5c06531dcc4..c1dffe47fde2 100644 --- a/fs/hppfs/hppfs.c +++ b/fs/hppfs/hppfs.c | |||
| @@ -420,8 +420,7 @@ static int hppfs_open(struct inode *inode, struct file *file) | |||
| 420 | { | 420 | { |
| 421 | const struct cred *cred = file->f_cred; | 421 | const struct cred *cred = file->f_cred; |
| 422 | struct hppfs_private *data; | 422 | struct hppfs_private *data; |
| 423 | struct vfsmount *proc_mnt; | 423 | struct path path; |
| 424 | struct dentry *proc_dentry; | ||
| 425 | char *host_file; | 424 | char *host_file; |
| 426 | int err, fd, type, filter; | 425 | int err, fd, type, filter; |
| 427 | 426 | ||
| @@ -434,12 +433,11 @@ static int hppfs_open(struct inode *inode, struct file *file) | |||
| 434 | if (host_file == NULL) | 433 | if (host_file == NULL) |
| 435 | goto out_free2; | 434 | goto out_free2; |
| 436 | 435 | ||
| 437 | proc_dentry = HPPFS_I(inode)->proc_dentry; | 436 | path.mnt = inode->i_sb->s_fs_info; |
| 438 | proc_mnt = inode->i_sb->s_fs_info; | 437 | path.dentry = HPPFS_I(inode)->proc_dentry; |
| 439 | 438 | ||
| 440 | /* XXX This isn't closed anywhere */ | 439 | /* XXX This isn't closed anywhere */ |
| 441 | data->proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt), | 440 | data->proc_file = dentry_open(&path, file_mode(file->f_mode), cred); |
| 442 | file_mode(file->f_mode), cred); | ||
| 443 | err = PTR_ERR(data->proc_file); | 441 | err = PTR_ERR(data->proc_file); |
| 444 | if (IS_ERR(data->proc_file)) | 442 | if (IS_ERR(data->proc_file)) |
| 445 | goto out_free1; | 443 | goto out_free1; |
| @@ -484,8 +482,7 @@ static int hppfs_dir_open(struct inode *inode, struct file *file) | |||
| 484 | { | 482 | { |
| 485 | const struct cred *cred = file->f_cred; | 483 | const struct cred *cred = file->f_cred; |
| 486 | struct hppfs_private *data; | 484 | struct hppfs_private *data; |
| 487 | struct vfsmount *proc_mnt; | 485 | struct path path; |
| 488 | struct dentry *proc_dentry; | ||
| 489 | int err; | 486 | int err; |
| 490 | 487 | ||
| 491 | err = -ENOMEM; | 488 | err = -ENOMEM; |
| @@ -493,10 +490,9 @@ static int hppfs_dir_open(struct inode *inode, struct file *file) | |||
| 493 | if (data == NULL) | 490 | if (data == NULL) |
| 494 | goto out; | 491 | goto out; |
| 495 | 492 | ||
| 496 | proc_dentry = HPPFS_I(inode)->proc_dentry; | 493 | path.mnt = inode->i_sb->s_fs_info; |
| 497 | proc_mnt = inode->i_sb->s_fs_info; | 494 | path.dentry = HPPFS_I(inode)->proc_dentry; |
| 498 | data->proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt), | 495 | data->proc_file = dentry_open(&path, file_mode(file->f_mode), cred); |
| 499 | file_mode(file->f_mode), cred); | ||
| 500 | err = PTR_ERR(data->proc_file); | 496 | err = PTR_ERR(data->proc_file); |
| 501 | if (IS_ERR(data->proc_file)) | 497 | if (IS_ERR(data->proc_file)) |
| 502 | goto out_free; | 498 | goto out_free; |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 05d9eee6be3a..4700a0a929d7 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
| @@ -745,7 +745,7 @@ __be32 | |||
| 745 | nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, | 745 | nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, |
| 746 | int may_flags, struct file **filp) | 746 | int may_flags, struct file **filp) |
| 747 | { | 747 | { |
| 748 | struct dentry *dentry; | 748 | struct path path; |
| 749 | struct inode *inode; | 749 | struct inode *inode; |
| 750 | int flags = O_RDONLY|O_LARGEFILE; | 750 | int flags = O_RDONLY|O_LARGEFILE; |
| 751 | __be32 err; | 751 | __be32 err; |
| @@ -762,8 +762,9 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, | |||
| 762 | if (err) | 762 | if (err) |
| 763 | goto out; | 763 | goto out; |
| 764 | 764 | ||
| 765 | dentry = fhp->fh_dentry; | 765 | path.mnt = fhp->fh_export->ex_path.mnt; |
| 766 | inode = dentry->d_inode; | 766 | path.dentry = fhp->fh_dentry; |
| 767 | inode = path.dentry->d_inode; | ||
| 767 | 768 | ||
| 768 | /* Disallow write access to files with the append-only bit set | 769 | /* Disallow write access to files with the append-only bit set |
| 769 | * or any access when mandatory locking enabled | 770 | * or any access when mandatory locking enabled |
| @@ -792,8 +793,7 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, | |||
| 792 | else | 793 | else |
| 793 | flags = O_WRONLY|O_LARGEFILE; | 794 | flags = O_WRONLY|O_LARGEFILE; |
| 794 | } | 795 | } |
| 795 | *filp = dentry_open(dget(dentry), mntget(fhp->fh_export->ex_path.mnt), | 796 | *filp = dentry_open(&path, flags, current_cred()); |
| 796 | flags, current_cred()); | ||
| 797 | if (IS_ERR(*filp)) | 797 | if (IS_ERR(*filp)) |
| 798 | host_err = PTR_ERR(*filp); | 798 | host_err = PTR_ERR(*filp); |
| 799 | else { | 799 | else { |
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c index 3568c8a8b138..d43803669739 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c | |||
| @@ -61,8 +61,6 @@ static struct fsnotify_event *get_one_event(struct fsnotify_group *group, | |||
| 61 | static int create_fd(struct fsnotify_group *group, struct fsnotify_event *event) | 61 | static int create_fd(struct fsnotify_group *group, struct fsnotify_event *event) |
| 62 | { | 62 | { |
| 63 | int client_fd; | 63 | int client_fd; |
| 64 | struct dentry *dentry; | ||
| 65 | struct vfsmount *mnt; | ||
| 66 | struct file *new_file; | 64 | struct file *new_file; |
| 67 | 65 | ||
| 68 | pr_debug("%s: group=%p event=%p\n", __func__, group, event); | 66 | pr_debug("%s: group=%p event=%p\n", __func__, group, event); |
| @@ -81,12 +79,10 @@ static int create_fd(struct fsnotify_group *group, struct fsnotify_event *event) | |||
| 81 | * we need a new file handle for the userspace program so it can read even if it was | 79 | * we need a new file handle for the userspace program so it can read even if it was |
| 82 | * originally opened O_WRONLY. | 80 | * originally opened O_WRONLY. |
| 83 | */ | 81 | */ |
| 84 | dentry = dget(event->path.dentry); | ||
| 85 | mnt = mntget(event->path.mnt); | ||
| 86 | /* it's possible this event was an overflow event. in that case dentry and mnt | 82 | /* it's possible this event was an overflow event. in that case dentry and mnt |
| 87 | * are NULL; That's fine, just don't call dentry open */ | 83 | * are NULL; That's fine, just don't call dentry open */ |
| 88 | if (dentry && mnt) | 84 | if (event->path.dentry && event->path.mnt) |
| 89 | new_file = dentry_open(dentry, mnt, | 85 | new_file = dentry_open(&event->path, |
| 90 | group->fanotify_data.f_flags | FMODE_NONOTIFY, | 86 | group->fanotify_data.f_flags | FMODE_NONOTIFY, |
| 91 | current_cred()); | 87 | current_cred()); |
| 92 | else | 88 | else |
| @@ -766,11 +766,7 @@ int finish_no_open(struct file *file, struct dentry *dentry) | |||
| 766 | } | 766 | } |
| 767 | EXPORT_SYMBOL(finish_no_open); | 767 | EXPORT_SYMBOL(finish_no_open); |
| 768 | 768 | ||
| 769 | /* | 769 | struct file *dentry_open(const struct path *path, int flags, |
| 770 | * dentry_open() will have done dput(dentry) and mntput(mnt) if it returns an | ||
| 771 | * error. | ||
| 772 | */ | ||
| 773 | struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags, | ||
| 774 | const struct cred *cred) | 770 | const struct cred *cred) |
| 775 | { | 771 | { |
| 776 | int error; | 772 | int error; |
| @@ -779,19 +775,16 @@ struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags, | |||
| 779 | validate_creds(cred); | 775 | validate_creds(cred); |
| 780 | 776 | ||
| 781 | /* We must always pass in a valid mount pointer. */ | 777 | /* We must always pass in a valid mount pointer. */ |
| 782 | BUG_ON(!mnt); | 778 | BUG_ON(!path->mnt); |
| 783 | 779 | ||
| 784 | error = -ENFILE; | 780 | error = -ENFILE; |
| 785 | f = get_empty_filp(); | 781 | f = get_empty_filp(); |
| 786 | if (f == NULL) { | 782 | if (f == NULL) |
| 787 | dput(dentry); | ||
| 788 | mntput(mnt); | ||
| 789 | return ERR_PTR(error); | 783 | return ERR_PTR(error); |
| 790 | } | ||
| 791 | 784 | ||
| 792 | f->f_flags = flags; | 785 | f->f_flags = flags; |
| 793 | f->f_path.mnt = mnt; | 786 | f->f_path = *path; |
| 794 | f->f_path.dentry = dentry; | 787 | path_get(&f->f_path); |
| 795 | error = do_dentry_open(f, NULL, cred); | 788 | error = do_dentry_open(f, NULL, cred); |
| 796 | if (!error) { | 789 | if (!error) { |
| 797 | error = open_check_o_direct(f); | 790 | error = open_check_o_direct(f); |
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index 3a05a41b5d76..1f1535d25a9b 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c | |||
| @@ -208,6 +208,7 @@ xfs_open_by_handle( | |||
| 208 | struct inode *inode; | 208 | struct inode *inode; |
| 209 | struct dentry *dentry; | 209 | struct dentry *dentry; |
| 210 | fmode_t fmode; | 210 | fmode_t fmode; |
| 211 | struct path path; | ||
| 211 | 212 | ||
| 212 | if (!capable(CAP_SYS_ADMIN)) | 213 | if (!capable(CAP_SYS_ADMIN)) |
| 213 | return -XFS_ERROR(EPERM); | 214 | return -XFS_ERROR(EPERM); |
| @@ -252,8 +253,10 @@ xfs_open_by_handle( | |||
| 252 | goto out_dput; | 253 | goto out_dput; |
| 253 | } | 254 | } |
| 254 | 255 | ||
| 255 | filp = dentry_open(dentry, mntget(parfilp->f_path.mnt), | 256 | path.mnt = parfilp->f_path.mnt; |
| 256 | hreq->oflags, cred); | 257 | path.dentry = dentry; |
| 258 | filp = dentry_open(&path, hreq->oflags, cred); | ||
| 259 | dput(dentry); | ||
| 257 | if (IS_ERR(filp)) { | 260 | if (IS_ERR(filp)) { |
| 258 | put_unused_fd(fd); | 261 | put_unused_fd(fd); |
| 259 | return PTR_ERR(filp); | 262 | return PTR_ERR(filp); |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 34acf51273dd..8fabb037a48d 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
| @@ -2060,8 +2060,7 @@ extern long do_sys_open(int dfd, const char __user *filename, int flags, | |||
| 2060 | extern struct file *filp_open(const char *, int, umode_t); | 2060 | extern struct file *filp_open(const char *, int, umode_t); |
| 2061 | extern struct file *file_open_root(struct dentry *, struct vfsmount *, | 2061 | extern struct file *file_open_root(struct dentry *, struct vfsmount *, |
| 2062 | const char *, int); | 2062 | const char *, int); |
| 2063 | extern struct file * dentry_open(struct dentry *, struct vfsmount *, int, | 2063 | extern struct file * dentry_open(const struct path *, int, const struct cred *); |
| 2064 | const struct cred *); | ||
| 2065 | extern int filp_close(struct file *, fl_owner_t id); | 2064 | extern int filp_close(struct file *, fl_owner_t id); |
| 2066 | extern char * getname(const char __user *); | 2065 | extern char * getname(const char __user *); |
| 2067 | enum { | 2066 | enum { |
diff --git a/ipc/mqueue.c b/ipc/mqueue.c index 2dee38d53c73..f8e54f5b9080 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c | |||
| @@ -721,8 +721,8 @@ static int mq_attr_ok(struct ipc_namespace *ipc_ns, struct mq_attr *attr) | |||
| 721 | /* | 721 | /* |
| 722 | * Invoked when creating a new queue via sys_mq_open | 722 | * Invoked when creating a new queue via sys_mq_open |
| 723 | */ | 723 | */ |
| 724 | static struct file *do_create(struct ipc_namespace *ipc_ns, struct dentry *dir, | 724 | static struct file *do_create(struct ipc_namespace *ipc_ns, struct inode *dir, |
| 725 | struct dentry *dentry, int oflag, umode_t mode, | 725 | struct path *path, int oflag, umode_t mode, |
| 726 | struct mq_attr *attr) | 726 | struct mq_attr *attr) |
| 727 | { | 727 | { |
| 728 | const struct cred *cred = current_cred(); | 728 | const struct cred *cred = current_cred(); |
| @@ -732,9 +732,9 @@ static struct file *do_create(struct ipc_namespace *ipc_ns, struct dentry *dir, | |||
| 732 | if (attr) { | 732 | if (attr) { |
| 733 | ret = mq_attr_ok(ipc_ns, attr); | 733 | ret = mq_attr_ok(ipc_ns, attr); |
| 734 | if (ret) | 734 | if (ret) |
| 735 | goto out; | 735 | return ERR_PTR(ret); |
| 736 | /* store for use during create */ | 736 | /* store for use during create */ |
| 737 | dentry->d_fsdata = attr; | 737 | path->dentry->d_fsdata = attr; |
| 738 | } else { | 738 | } else { |
| 739 | struct mq_attr def_attr; | 739 | struct mq_attr def_attr; |
| 740 | 740 | ||
| @@ -744,71 +744,51 @@ static struct file *do_create(struct ipc_namespace *ipc_ns, struct dentry *dir, | |||
| 744 | ipc_ns->mq_msgsize_default); | 744 | ipc_ns->mq_msgsize_default); |
| 745 | ret = mq_attr_ok(ipc_ns, &def_attr); | 745 | ret = mq_attr_ok(ipc_ns, &def_attr); |
| 746 | if (ret) | 746 | if (ret) |
| 747 | goto out; | 747 | return ERR_PTR(ret); |
| 748 | } | 748 | } |
| 749 | 749 | ||
| 750 | mode &= ~current_umask(); | 750 | mode &= ~current_umask(); |
| 751 | ret = mnt_want_write(ipc_ns->mq_mnt); | 751 | ret = mnt_want_write(path->mnt); |
| 752 | if (ret) | 752 | if (ret) |
| 753 | goto out; | 753 | return ERR_PTR(ret); |
| 754 | ret = vfs_create(dir->d_inode, dentry, mode, true); | 754 | ret = vfs_create(dir, path->dentry, mode, true); |
| 755 | dentry->d_fsdata = NULL; | 755 | path->dentry->d_fsdata = NULL; |
| 756 | if (ret) | 756 | if (!ret) |
| 757 | goto out_drop_write; | 757 | result = dentry_open(path, oflag, cred); |
| 758 | 758 | else | |
| 759 | result = dentry_open(dentry, ipc_ns->mq_mnt, oflag, cred); | 759 | result = ERR_PTR(ret); |
| 760 | /* | 760 | /* |
| 761 | * dentry_open() took a persistent mnt_want_write(), | 761 | * dentry_open() took a persistent mnt_want_write(), |
| 762 | * so we can now drop this one. | 762 | * so we can now drop this one. |
| 763 | */ | 763 | */ |
| 764 | mnt_drop_write(ipc_ns->mq_mnt); | 764 | mnt_drop_write(path->mnt); |
| 765 | return result; | 765 | return result; |
| 766 | |||
| 767 | out_drop_write: | ||
| 768 | mnt_drop_write(ipc_ns->mq_mnt); | ||
| 769 | out: | ||
| 770 | dput(dentry); | ||
| 771 | mntput(ipc_ns->mq_mnt); | ||
| 772 | return ERR_PTR(ret); | ||
| 773 | } | 766 | } |
| 774 | 767 | ||
| 775 | /* Opens existing queue */ | 768 | /* Opens existing queue */ |
| 776 | static struct file *do_open(struct ipc_namespace *ipc_ns, | 769 | static struct file *do_open(struct path *path, int oflag) |
| 777 | struct dentry *dentry, int oflag) | ||
| 778 | { | 770 | { |
| 779 | int ret; | ||
| 780 | const struct cred *cred = current_cred(); | ||
| 781 | |||
| 782 | static const int oflag2acc[O_ACCMODE] = { MAY_READ, MAY_WRITE, | 771 | static const int oflag2acc[O_ACCMODE] = { MAY_READ, MAY_WRITE, |
| 783 | MAY_READ | MAY_WRITE }; | 772 | MAY_READ | MAY_WRITE }; |
| 784 | 773 | int acc; | |
| 785 | if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY)) { | 774 | if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY)) |
| 786 | ret = -EINVAL; | 775 | return ERR_PTR(-EINVAL); |
| 787 | goto err; | 776 | acc = oflag2acc[oflag & O_ACCMODE]; |
| 788 | } | 777 | if (inode_permission(path->dentry->d_inode, acc)) |
| 789 | 778 | return ERR_PTR(-EACCES); | |
| 790 | if (inode_permission(dentry->d_inode, oflag2acc[oflag & O_ACCMODE])) { | 779 | return dentry_open(path, oflag, current_cred()); |
| 791 | ret = -EACCES; | ||
| 792 | goto err; | ||
| 793 | } | ||
| 794 | |||
| 795 | return dentry_open(dentry, ipc_ns->mq_mnt, oflag, cred); | ||
| 796 | |||
| 797 | err: | ||
| 798 | dput(dentry); | ||
| 799 | mntput(ipc_ns->mq_mnt); | ||
| 800 | return ERR_PTR(ret); | ||
| 801 | } | 780 | } |
| 802 | 781 | ||
| 803 | SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode, | 782 | SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode, |
| 804 | struct mq_attr __user *, u_attr) | 783 | struct mq_attr __user *, u_attr) |
| 805 | { | 784 | { |
| 806 | struct dentry *dentry; | 785 | struct path path; |
| 807 | struct file *filp; | 786 | struct file *filp; |
| 808 | char *name; | 787 | char *name; |
| 809 | struct mq_attr attr; | 788 | struct mq_attr attr; |
| 810 | int fd, error; | 789 | int fd, error; |
| 811 | struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns; | 790 | struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns; |
| 791 | struct dentry *root = ipc_ns->mq_mnt->mnt_root; | ||
| 812 | 792 | ||
| 813 | if (u_attr && copy_from_user(&attr, u_attr, sizeof(struct mq_attr))) | 793 | if (u_attr && copy_from_user(&attr, u_attr, sizeof(struct mq_attr))) |
| 814 | return -EFAULT; | 794 | return -EFAULT; |
| @@ -822,52 +802,49 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode, | |||
| 822 | if (fd < 0) | 802 | if (fd < 0) |
| 823 | goto out_putname; | 803 | goto out_putname; |
| 824 | 804 | ||
| 825 | mutex_lock(&ipc_ns->mq_mnt->mnt_root->d_inode->i_mutex); | 805 | error = 0; |
| 826 | dentry = lookup_one_len(name, ipc_ns->mq_mnt->mnt_root, strlen(name)); | 806 | mutex_lock(&root->d_inode->i_mutex); |
| 827 | if (IS_ERR(dentry)) { | 807 | path.dentry = lookup_one_len(name, root, strlen(name)); |
| 828 | error = PTR_ERR(dentry); | 808 | if (IS_ERR(path.dentry)) { |
| 809 | error = PTR_ERR(path.dentry); | ||
| 829 | goto out_putfd; | 810 | goto out_putfd; |
| 830 | } | 811 | } |
| 831 | mntget(ipc_ns->mq_mnt); | 812 | path.mnt = mntget(ipc_ns->mq_mnt); |
| 832 | 813 | ||
| 833 | if (oflag & O_CREAT) { | 814 | if (oflag & O_CREAT) { |
| 834 | if (dentry->d_inode) { /* entry already exists */ | 815 | if (path.dentry->d_inode) { /* entry already exists */ |
| 835 | audit_inode(name, dentry); | 816 | audit_inode(name, path.dentry); |
| 836 | if (oflag & O_EXCL) { | 817 | if (oflag & O_EXCL) { |
| 837 | error = -EEXIST; | 818 | error = -EEXIST; |
| 838 | goto out; | 819 | goto out; |
| 839 | } | 820 | } |
| 840 | filp = do_open(ipc_ns, dentry, oflag); | 821 | filp = do_open(&path, oflag); |
| 841 | } else { | 822 | } else { |
| 842 | filp = do_create(ipc_ns, ipc_ns->mq_mnt->mnt_root, | 823 | filp = do_create(ipc_ns, root->d_inode, |
| 843 | dentry, oflag, mode, | 824 | &path, oflag, mode, |
| 844 | u_attr ? &attr : NULL); | 825 | u_attr ? &attr : NULL); |
| 845 | } | 826 | } |
| 846 | } else { | 827 | } else { |
| 847 | if (!dentry->d_inode) { | 828 | if (!path.dentry->d_inode) { |
| 848 | error = -ENOENT; | 829 | error = -ENOENT; |
| 849 | goto out; | 830 | goto out; |
| 850 | } | 831 | } |
| 851 | audit_inode(name, dentry); | 832 | audit_inode(name, path.dentry); |
| 852 | filp = do_open(ipc_ns, dentry, oflag); | 833 | filp = do_open(&path, oflag); |
| 853 | } | 834 | } |
| 854 | 835 | ||
| 855 | if (IS_ERR(filp)) { | 836 | if (!IS_ERR(filp)) |
| 837 | fd_install(fd, filp); | ||
| 838 | else | ||
| 856 | error = PTR_ERR(filp); | 839 | error = PTR_ERR(filp); |
| 857 | goto out_putfd; | ||
| 858 | } | ||
| 859 | |||
| 860 | fd_install(fd, filp); | ||
| 861 | goto out_upsem; | ||
| 862 | |||
| 863 | out: | 840 | out: |
| 864 | dput(dentry); | 841 | path_put(&path); |
| 865 | mntput(ipc_ns->mq_mnt); | ||
| 866 | out_putfd: | 842 | out_putfd: |
| 867 | put_unused_fd(fd); | 843 | if (error) { |
| 868 | fd = error; | 844 | put_unused_fd(fd); |
| 869 | out_upsem: | 845 | fd = error; |
| 870 | mutex_unlock(&ipc_ns->mq_mnt->mnt_root->d_inode->i_mutex); | 846 | } |
| 847 | mutex_unlock(&root->d_inode->i_mutex); | ||
| 871 | out_putname: | 848 | out_putname: |
| 872 | putname(name); | 849 | putname(name); |
| 873 | return fd; | 850 | return fd; |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 372ec6502aa8..e423f5fe67fa 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
| @@ -2157,8 +2157,7 @@ static inline void flush_unauthorized_files(const struct cred *cred, | |||
| 2157 | get_file(devnull); | 2157 | get_file(devnull); |
| 2158 | } else { | 2158 | } else { |
| 2159 | devnull = dentry_open( | 2159 | devnull = dentry_open( |
| 2160 | dget(selinux_null), | 2160 | &selinux_null, |
| 2161 | mntget(selinuxfs_mount), | ||
| 2162 | O_RDWR, cred); | 2161 | O_RDWR, cred); |
| 2163 | if (IS_ERR(devnull)) { | 2162 | if (IS_ERR(devnull)) { |
| 2164 | devnull = NULL; | 2163 | devnull = NULL; |
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index dde2005407aa..6d3885165d14 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h | |||
| @@ -221,7 +221,7 @@ extern void selinux_status_update_policyload(int seqno); | |||
| 221 | extern void selinux_complete_init(void); | 221 | extern void selinux_complete_init(void); |
| 222 | extern int selinux_disable(void); | 222 | extern int selinux_disable(void); |
| 223 | extern void exit_sel_fs(void); | 223 | extern void exit_sel_fs(void); |
| 224 | extern struct dentry *selinux_null; | 224 | extern struct path selinux_null; |
| 225 | extern struct vfsmount *selinuxfs_mount; | 225 | extern struct vfsmount *selinuxfs_mount; |
| 226 | extern void selnl_notify_setenforce(int val); | 226 | extern void selnl_notify_setenforce(int val); |
| 227 | extern void selnl_notify_policyload(u32 seqno); | 227 | extern void selnl_notify_policyload(u32 seqno); |
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index 3ad290251288..298e695d6822 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c | |||
| @@ -1297,7 +1297,7 @@ out: | |||
| 1297 | 1297 | ||
| 1298 | #define NULL_FILE_NAME "null" | 1298 | #define NULL_FILE_NAME "null" |
| 1299 | 1299 | ||
| 1300 | struct dentry *selinux_null; | 1300 | struct path selinux_null; |
| 1301 | 1301 | ||
| 1302 | static ssize_t sel_read_avc_cache_threshold(struct file *filp, char __user *buf, | 1302 | static ssize_t sel_read_avc_cache_threshold(struct file *filp, char __user *buf, |
| 1303 | size_t count, loff_t *ppos) | 1303 | size_t count, loff_t *ppos) |
| @@ -1838,7 +1838,7 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent) | |||
| 1838 | 1838 | ||
| 1839 | init_special_inode(inode, S_IFCHR | S_IRUGO | S_IWUGO, MKDEV(MEM_MAJOR, 3)); | 1839 | init_special_inode(inode, S_IFCHR | S_IRUGO | S_IWUGO, MKDEV(MEM_MAJOR, 3)); |
| 1840 | d_add(dentry, inode); | 1840 | d_add(dentry, inode); |
| 1841 | selinux_null = dentry; | 1841 | selinux_null.dentry = dentry; |
| 1842 | 1842 | ||
| 1843 | dentry = sel_make_dir(sb->s_root, "avc", &sel_last_ino); | 1843 | dentry = sel_make_dir(sb->s_root, "avc", &sel_last_ino); |
| 1844 | if (IS_ERR(dentry)) { | 1844 | if (IS_ERR(dentry)) { |
| @@ -1912,7 +1912,7 @@ static int __init init_sel_fs(void) | |||
| 1912 | return err; | 1912 | return err; |
| 1913 | } | 1913 | } |
| 1914 | 1914 | ||
| 1915 | selinuxfs_mount = kern_mount(&sel_fs_type); | 1915 | selinux_null.mnt = selinuxfs_mount = kern_mount(&sel_fs_type); |
| 1916 | if (IS_ERR(selinuxfs_mount)) { | 1916 | if (IS_ERR(selinuxfs_mount)) { |
| 1917 | printk(KERN_ERR "selinuxfs: could not mount!\n"); | 1917 | printk(KERN_ERR "selinuxfs: could not mount!\n"); |
| 1918 | err = PTR_ERR(selinuxfs_mount); | 1918 | err = PTR_ERR(selinuxfs_mount); |
