diff options
Diffstat (limited to 'fs/open.c')
| -rw-r--r-- | fs/open.c | 66 |
1 files changed, 33 insertions, 33 deletions
| @@ -272,6 +272,8 @@ static long do_sys_truncate(const char __user *pathname, loff_t length) | |||
| 272 | goto put_write_and_out; | 272 | goto put_write_and_out; |
| 273 | 273 | ||
| 274 | error = locks_verify_truncate(inode, NULL, length); | 274 | error = locks_verify_truncate(inode, NULL, length); |
| 275 | if (!error) | ||
| 276 | error = security_path_truncate(&path, length, 0); | ||
| 275 | if (!error) { | 277 | if (!error) { |
| 276 | DQUOT_INIT(inode); | 278 | DQUOT_INIT(inode); |
| 277 | error = do_truncate(path.dentry, length, 0, NULL); | 279 | error = do_truncate(path.dentry, length, 0, NULL); |
| @@ -329,6 +331,9 @@ static long do_sys_ftruncate(unsigned int fd, loff_t length, int small) | |||
| 329 | 331 | ||
| 330 | error = locks_verify_truncate(inode, file, length); | 332 | error = locks_verify_truncate(inode, file, length); |
| 331 | if (!error) | 333 | if (!error) |
| 334 | error = security_path_truncate(&file->f_path, length, | ||
| 335 | ATTR_MTIME|ATTR_CTIME); | ||
| 336 | if (!error) | ||
| 332 | error = do_truncate(dentry, length, ATTR_MTIME|ATTR_CTIME, file); | 337 | error = do_truncate(dentry, length, ATTR_MTIME|ATTR_CTIME, file); |
| 333 | out_putf: | 338 | out_putf: |
| 334 | fput(file); | 339 | fput(file); |
| @@ -407,7 +412,7 @@ asmlinkage long sys_fallocate(int fd, int mode, loff_t offset, loff_t len) | |||
| 407 | if (((offset + len) > inode->i_sb->s_maxbytes) || ((offset + len) < 0)) | 412 | if (((offset + len) > inode->i_sb->s_maxbytes) || ((offset + len) < 0)) |
| 408 | goto out_fput; | 413 | goto out_fput; |
| 409 | 414 | ||
| 410 | if (inode->i_op && inode->i_op->fallocate) | 415 | if (inode->i_op->fallocate) |
| 411 | ret = inode->i_op->fallocate(inode, mode, offset, len); | 416 | ret = inode->i_op->fallocate(inode, mode, offset, len); |
| 412 | else | 417 | else |
| 413 | ret = -EOPNOTSUPP; | 418 | ret = -EOPNOTSUPP; |
| @@ -425,39 +430,33 @@ out: | |||
| 425 | */ | 430 | */ |
| 426 | asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode) | 431 | asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode) |
| 427 | { | 432 | { |
| 433 | const struct cred *old_cred; | ||
| 434 | struct cred *override_cred; | ||
| 428 | struct path path; | 435 | struct path path; |
| 429 | struct inode *inode; | 436 | struct inode *inode; |
| 430 | int old_fsuid, old_fsgid; | ||
| 431 | kernel_cap_t uninitialized_var(old_cap); /* !SECURE_NO_SETUID_FIXUP */ | ||
| 432 | int res; | 437 | int res; |
| 433 | 438 | ||
| 434 | if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */ | 439 | if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */ |
| 435 | return -EINVAL; | 440 | return -EINVAL; |
| 436 | 441 | ||
| 437 | old_fsuid = current->fsuid; | 442 | override_cred = prepare_creds(); |
| 438 | old_fsgid = current->fsgid; | 443 | if (!override_cred) |
| 444 | return -ENOMEM; | ||
| 439 | 445 | ||
| 440 | current->fsuid = current->uid; | 446 | override_cred->fsuid = override_cred->uid; |
| 441 | current->fsgid = current->gid; | 447 | override_cred->fsgid = override_cred->gid; |
| 442 | 448 | ||
| 443 | if (!issecure(SECURE_NO_SETUID_FIXUP)) { | 449 | if (!issecure(SECURE_NO_SETUID_FIXUP)) { |
| 444 | /* | 450 | /* Clear the capabilities if we switch to a non-root user */ |
| 445 | * Clear the capabilities if we switch to a non-root user | 451 | if (override_cred->uid) |
| 446 | */ | 452 | 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 | 453 | else |
| 458 | old_cap = cap_set_effective(current->cap_permitted); | 454 | override_cred->cap_effective = |
| 455 | override_cred->cap_permitted; | ||
| 459 | } | 456 | } |
| 460 | 457 | ||
| 458 | old_cred = override_creds(override_cred); | ||
| 459 | |||
| 461 | res = user_path_at(dfd, filename, LOOKUP_FOLLOW, &path); | 460 | res = user_path_at(dfd, filename, LOOKUP_FOLLOW, &path); |
| 462 | if (res) | 461 | if (res) |
| 463 | goto out; | 462 | goto out; |
| @@ -494,12 +493,8 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode) | |||
| 494 | out_path_release: | 493 | out_path_release: |
| 495 | path_put(&path); | 494 | path_put(&path); |
| 496 | out: | 495 | out: |
| 497 | current->fsuid = old_fsuid; | 496 | revert_creds(old_cred); |
| 498 | current->fsgid = old_fsgid; | 497 | put_cred(override_cred); |
| 499 | |||
| 500 | if (!issecure(SECURE_NO_SETUID_FIXUP)) | ||
| 501 | cap_set_effective(old_cap); | ||
| 502 | |||
| 503 | return res; | 498 | return res; |
| 504 | } | 499 | } |
| 505 | 500 | ||
| @@ -792,7 +787,8 @@ static inline int __get_file_write_access(struct inode *inode, | |||
| 792 | 787 | ||
| 793 | static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, | 788 | static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, |
| 794 | int flags, struct file *f, | 789 | int flags, struct file *f, |
| 795 | int (*open)(struct inode *, struct file *)) | 790 | int (*open)(struct inode *, struct file *), |
| 791 | const struct cred *cred) | ||
| 796 | { | 792 | { |
| 797 | struct inode *inode; | 793 | struct inode *inode; |
| 798 | int error; | 794 | int error; |
| @@ -816,7 +812,7 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, | |||
| 816 | f->f_op = fops_get(inode->i_fop); | 812 | f->f_op = fops_get(inode->i_fop); |
| 817 | file_move(f, &inode->i_sb->s_files); | 813 | file_move(f, &inode->i_sb->s_files); |
| 818 | 814 | ||
| 819 | error = security_dentry_open(f); | 815 | error = security_dentry_open(f, cred); |
| 820 | if (error) | 816 | if (error) |
| 821 | goto cleanup_all; | 817 | goto cleanup_all; |
| 822 | 818 | ||
| @@ -891,6 +887,8 @@ cleanup_file: | |||
| 891 | struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry, | 887 | struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry, |
| 892 | int (*open)(struct inode *, struct file *)) | 888 | int (*open)(struct inode *, struct file *)) |
| 893 | { | 889 | { |
| 890 | const struct cred *cred = current_cred(); | ||
| 891 | |||
| 894 | if (IS_ERR(nd->intent.open.file)) | 892 | if (IS_ERR(nd->intent.open.file)) |
| 895 | goto out; | 893 | goto out; |
| 896 | if (IS_ERR(dentry)) | 894 | if (IS_ERR(dentry)) |
| @@ -898,7 +896,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), | 896 | nd->intent.open.file = __dentry_open(dget(dentry), mntget(nd->path.mnt), |
| 899 | nd->intent.open.flags - 1, | 897 | nd->intent.open.flags - 1, |
| 900 | nd->intent.open.file, | 898 | nd->intent.open.file, |
| 901 | open); | 899 | open, cred); |
| 902 | out: | 900 | out: |
| 903 | return nd->intent.open.file; | 901 | return nd->intent.open.file; |
| 904 | out_err: | 902 | out_err: |
| @@ -917,6 +915,7 @@ EXPORT_SYMBOL_GPL(lookup_instantiate_filp); | |||
| 917 | */ | 915 | */ |
| 918 | struct file *nameidata_to_filp(struct nameidata *nd, int flags) | 916 | struct file *nameidata_to_filp(struct nameidata *nd, int flags) |
| 919 | { | 917 | { |
| 918 | const struct cred *cred = current_cred(); | ||
| 920 | struct file *filp; | 919 | struct file *filp; |
| 921 | 920 | ||
| 922 | /* Pick up the filp from the open intent */ | 921 | /* Pick up the filp from the open intent */ |
| @@ -924,7 +923,7 @@ struct file *nameidata_to_filp(struct nameidata *nd, int flags) | |||
| 924 | /* Has the filesystem initialised the file for us? */ | 923 | /* Has the filesystem initialised the file for us? */ |
| 925 | if (filp->f_path.dentry == NULL) | 924 | if (filp->f_path.dentry == NULL) |
| 926 | filp = __dentry_open(nd->path.dentry, nd->path.mnt, flags, filp, | 925 | filp = __dentry_open(nd->path.dentry, nd->path.mnt, flags, filp, |
| 927 | NULL); | 926 | NULL, cred); |
| 928 | else | 927 | else |
| 929 | path_put(&nd->path); | 928 | path_put(&nd->path); |
| 930 | return filp; | 929 | return filp; |
| @@ -934,7 +933,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 | 933 | * dentry_open() will have done dput(dentry) and mntput(mnt) if it returns an |
| 935 | * error. | 934 | * error. |
| 936 | */ | 935 | */ |
| 937 | struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags) | 936 | struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags, |
| 937 | const struct cred *cred) | ||
| 938 | { | 938 | { |
| 939 | int error; | 939 | int error; |
| 940 | struct file *f; | 940 | struct file *f; |
| @@ -959,7 +959,7 @@ struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags) | |||
| 959 | return ERR_PTR(error); | 959 | return ERR_PTR(error); |
| 960 | } | 960 | } |
| 961 | 961 | ||
| 962 | return __dentry_open(dentry, mnt, flags, f, NULL); | 962 | return __dentry_open(dentry, mnt, flags, f, NULL, cred); |
| 963 | } | 963 | } |
| 964 | EXPORT_SYMBOL(dentry_open); | 964 | EXPORT_SYMBOL(dentry_open); |
| 965 | 965 | ||
