aboutsummaryrefslogtreecommitdiffstats
path: root/fs/open.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/open.c')
-rw-r--r--fs/open.c59
1 files changed, 27 insertions, 32 deletions
diff --git a/fs/open.c b/fs/open.c
index 83cdb9dee0c1..c0a426d5766c 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -425,39 +425,33 @@ out:
425 */ 425 */
426asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode) 426asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode)
427{ 427{
428 const struct cred *old_cred;
429 struct cred *override_cred;
428 struct path path; 430 struct path path;
429 struct inode *inode; 431 struct inode *inode;
430 int old_fsuid, old_fsgid;
431 kernel_cap_t uninitialized_var(old_cap); /* !SECURE_NO_SETUID_FIXUP */
432 int res; 432 int res;
433 433
434 if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */ 434 if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */
435 return -EINVAL; 435 return -EINVAL;
436 436
437 old_fsuid = current->fsuid; 437 override_cred = prepare_creds();
438 old_fsgid = current->fsgid; 438 if (!override_cred)
439 return -ENOMEM;
439 440
440 current->fsuid = current->uid; 441 override_cred->fsuid = override_cred->uid;
441 current->fsgid = current->gid; 442 override_cred->fsgid = override_cred->gid;
442 443
443 if (!issecure(SECURE_NO_SETUID_FIXUP)) { 444 if (!issecure(SECURE_NO_SETUID_FIXUP)) {
444 /* 445 /* Clear the capabilities if we switch to a non-root user */
445 * Clear the capabilities if we switch to a non-root user 446 if (override_cred->uid)
446 */ 447 cap_clear(override_cred->cap_effective);
447#ifndef CONFIG_SECURITY_FILE_CAPABILITIES
448 /*
449 * FIXME: There is a race here against sys_capset. The
450 * capabilities can change yet we will restore the old
451 * value below. We should hold task_capabilities_lock,
452 * but we cannot because user_path_at can sleep.
453 */
454#endif /* ndef CONFIG_SECURITY_FILE_CAPABILITIES */
455 if (current->uid)
456 old_cap = cap_set_effective(__cap_empty_set);
457 else 448 else
458 old_cap = cap_set_effective(current->cap_permitted); 449 override_cred->cap_effective =
450 override_cred->cap_permitted;
459 } 451 }
460 452
453 old_cred = override_creds(override_cred);
454
461 res = user_path_at(dfd, filename, LOOKUP_FOLLOW, &path); 455 res = user_path_at(dfd, filename, LOOKUP_FOLLOW, &path);
462 if (res) 456 if (res)
463 goto out; 457 goto out;
@@ -494,12 +488,8 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode)
494out_path_release: 488out_path_release:
495 path_put(&path); 489 path_put(&path);
496out: 490out:
497 current->fsuid = old_fsuid; 491 revert_creds(old_cred);
498 current->fsgid = old_fsgid; 492 put_cred(override_cred);
499
500 if (!issecure(SECURE_NO_SETUID_FIXUP))
501 cap_set_effective(old_cap);
502
503 return res; 493 return res;
504} 494}
505 495
@@ -792,7 +782,8 @@ static inline int __get_file_write_access(struct inode *inode,
792 782
793static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, 783static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
794 int flags, struct file *f, 784 int flags, struct file *f,
795 int (*open)(struct inode *, struct file *)) 785 int (*open)(struct inode *, struct file *),
786 const struct cred *cred)
796{ 787{
797 struct inode *inode; 788 struct inode *inode;
798 int error; 789 int error;
@@ -816,7 +807,7 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
816 f->f_op = fops_get(inode->i_fop); 807 f->f_op = fops_get(inode->i_fop);
817 file_move(f, &inode->i_sb->s_files); 808 file_move(f, &inode->i_sb->s_files);
818 809
819 error = security_dentry_open(f); 810 error = security_dentry_open(f, cred);
820 if (error) 811 if (error)
821 goto cleanup_all; 812 goto cleanup_all;
822 813
@@ -891,6 +882,8 @@ cleanup_file:
891struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry, 882struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry,
892 int (*open)(struct inode *, struct file *)) 883 int (*open)(struct inode *, struct file *))
893{ 884{
885 const struct cred *cred = current_cred();
886
894 if (IS_ERR(nd->intent.open.file)) 887 if (IS_ERR(nd->intent.open.file))
895 goto out; 888 goto out;
896 if (IS_ERR(dentry)) 889 if (IS_ERR(dentry))
@@ -898,7 +891,7 @@ struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry
898 nd->intent.open.file = __dentry_open(dget(dentry), mntget(nd->path.mnt), 891 nd->intent.open.file = __dentry_open(dget(dentry), mntget(nd->path.mnt),
899 nd->intent.open.flags - 1, 892 nd->intent.open.flags - 1,
900 nd->intent.open.file, 893 nd->intent.open.file,
901 open); 894 open, cred);
902out: 895out:
903 return nd->intent.open.file; 896 return nd->intent.open.file;
904out_err: 897out_err:
@@ -917,6 +910,7 @@ EXPORT_SYMBOL_GPL(lookup_instantiate_filp);
917 */ 910 */
918struct file *nameidata_to_filp(struct nameidata *nd, int flags) 911struct file *nameidata_to_filp(struct nameidata *nd, int flags)
919{ 912{
913 const struct cred *cred = current_cred();
920 struct file *filp; 914 struct file *filp;
921 915
922 /* Pick up the filp from the open intent */ 916 /* Pick up the filp from the open intent */
@@ -924,7 +918,7 @@ struct file *nameidata_to_filp(struct nameidata *nd, int flags)
924 /* Has the filesystem initialised the file for us? */ 918 /* Has the filesystem initialised the file for us? */
925 if (filp->f_path.dentry == NULL) 919 if (filp->f_path.dentry == NULL)
926 filp = __dentry_open(nd->path.dentry, nd->path.mnt, flags, filp, 920 filp = __dentry_open(nd->path.dentry, nd->path.mnt, flags, filp,
927 NULL); 921 NULL, cred);
928 else 922 else
929 path_put(&nd->path); 923 path_put(&nd->path);
930 return filp; 924 return filp;
@@ -934,7 +928,8 @@ struct file *nameidata_to_filp(struct nameidata *nd, int flags)
934 * dentry_open() will have done dput(dentry) and mntput(mnt) if it returns an 928 * dentry_open() will have done dput(dentry) and mntput(mnt) if it returns an
935 * error. 929 * error.
936 */ 930 */
937struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags) 931struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags,
932 const struct cred *cred)
938{ 933{
939 int error; 934 int error;
940 struct file *f; 935 struct file *f;
@@ -959,7 +954,7 @@ struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
959 return ERR_PTR(error); 954 return ERR_PTR(error);
960 } 955 }
961 956
962 return __dentry_open(dentry, mnt, flags, f, NULL); 957 return __dentry_open(dentry, mnt, flags, f, NULL, cred);
963} 958}
964EXPORT_SYMBOL(dentry_open); 959EXPORT_SYMBOL(dentry_open);
965 960