diff options
Diffstat (limited to 'fs/open.c')
| -rw-r--r-- | fs/open.c | 179 |
1 files changed, 80 insertions, 99 deletions
| @@ -122,37 +122,37 @@ static int vfs_statfs64(struct dentry *dentry, struct statfs64 *buf) | |||
| 122 | return 0; | 122 | return 0; |
| 123 | } | 123 | } |
| 124 | 124 | ||
| 125 | asmlinkage long sys_statfs(const char __user * path, struct statfs __user * buf) | 125 | asmlinkage long sys_statfs(const char __user *pathname, struct statfs __user * buf) |
| 126 | { | 126 | { |
| 127 | struct nameidata nd; | 127 | struct path path; |
| 128 | int error; | 128 | int error; |
| 129 | 129 | ||
| 130 | error = user_path_walk(path, &nd); | 130 | error = user_path(pathname, &path); |
| 131 | if (!error) { | 131 | if (!error) { |
| 132 | struct statfs tmp; | 132 | struct statfs tmp; |
| 133 | error = vfs_statfs_native(nd.path.dentry, &tmp); | 133 | error = vfs_statfs_native(path.dentry, &tmp); |
| 134 | if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) | 134 | if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) |
| 135 | error = -EFAULT; | 135 | error = -EFAULT; |
| 136 | path_put(&nd.path); | 136 | path_put(&path); |
| 137 | } | 137 | } |
| 138 | return error; | 138 | return error; |
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | 141 | ||
| 142 | asmlinkage long sys_statfs64(const char __user *path, size_t sz, struct statfs64 __user *buf) | 142 | asmlinkage long sys_statfs64(const char __user *pathname, size_t sz, struct statfs64 __user *buf) |
| 143 | { | 143 | { |
| 144 | struct nameidata nd; | 144 | struct path path; |
| 145 | long error; | 145 | long error; |
| 146 | 146 | ||
| 147 | if (sz != sizeof(*buf)) | 147 | if (sz != sizeof(*buf)) |
| 148 | return -EINVAL; | 148 | return -EINVAL; |
| 149 | error = user_path_walk(path, &nd); | 149 | error = user_path(pathname, &path); |
| 150 | if (!error) { | 150 | if (!error) { |
| 151 | struct statfs64 tmp; | 151 | struct statfs64 tmp; |
| 152 | error = vfs_statfs64(nd.path.dentry, &tmp); | 152 | error = vfs_statfs64(path.dentry, &tmp); |
| 153 | if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) | 153 | if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) |
| 154 | error = -EFAULT; | 154 | error = -EFAULT; |
| 155 | path_put(&nd.path); | 155 | path_put(&path); |
| 156 | } | 156 | } |
| 157 | return error; | 157 | return error; |
| 158 | } | 158 | } |
| @@ -223,20 +223,20 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs, | |||
| 223 | return err; | 223 | return err; |
| 224 | } | 224 | } |
| 225 | 225 | ||
| 226 | static long do_sys_truncate(const char __user * path, loff_t length) | 226 | static long do_sys_truncate(const char __user *pathname, loff_t length) |
| 227 | { | 227 | { |
| 228 | struct nameidata nd; | 228 | struct path path; |
| 229 | struct inode * inode; | 229 | struct inode *inode; |
| 230 | int error; | 230 | int error; |
| 231 | 231 | ||
| 232 | error = -EINVAL; | 232 | error = -EINVAL; |
| 233 | if (length < 0) /* sorry, but loff_t says... */ | 233 | if (length < 0) /* sorry, but loff_t says... */ |
| 234 | goto out; | 234 | goto out; |
| 235 | 235 | ||
| 236 | error = user_path_walk(path, &nd); | 236 | error = user_path(pathname, &path); |
| 237 | if (error) | 237 | if (error) |
| 238 | goto out; | 238 | goto out; |
| 239 | inode = nd.path.dentry->d_inode; | 239 | inode = path.dentry->d_inode; |
| 240 | 240 | ||
| 241 | /* For directories it's -EISDIR, for other non-regulars - -EINVAL */ | 241 | /* For directories it's -EISDIR, for other non-regulars - -EINVAL */ |
| 242 | error = -EISDIR; | 242 | error = -EISDIR; |
| @@ -247,16 +247,16 @@ static long do_sys_truncate(const char __user * path, loff_t length) | |||
| 247 | if (!S_ISREG(inode->i_mode)) | 247 | if (!S_ISREG(inode->i_mode)) |
| 248 | goto dput_and_out; | 248 | goto dput_and_out; |
| 249 | 249 | ||
| 250 | error = mnt_want_write(nd.path.mnt); | 250 | error = mnt_want_write(path.mnt); |
| 251 | if (error) | 251 | if (error) |
| 252 | goto dput_and_out; | 252 | goto dput_and_out; |
| 253 | 253 | ||
| 254 | error = vfs_permission(&nd, MAY_WRITE); | 254 | error = inode_permission(inode, MAY_WRITE); |
| 255 | if (error) | 255 | if (error) |
| 256 | goto mnt_drop_write_and_out; | 256 | goto mnt_drop_write_and_out; |
| 257 | 257 | ||
| 258 | error = -EPERM; | 258 | error = -EPERM; |
| 259 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) | 259 | if (IS_APPEND(inode)) |
| 260 | goto mnt_drop_write_and_out; | 260 | goto mnt_drop_write_and_out; |
| 261 | 261 | ||
| 262 | error = get_write_access(inode); | 262 | error = get_write_access(inode); |
| @@ -274,15 +274,15 @@ static long do_sys_truncate(const char __user * path, loff_t length) | |||
| 274 | error = locks_verify_truncate(inode, NULL, length); | 274 | error = locks_verify_truncate(inode, NULL, length); |
| 275 | if (!error) { | 275 | if (!error) { |
| 276 | DQUOT_INIT(inode); | 276 | DQUOT_INIT(inode); |
| 277 | error = do_truncate(nd.path.dentry, length, 0, NULL); | 277 | error = do_truncate(path.dentry, length, 0, NULL); |
| 278 | } | 278 | } |
| 279 | 279 | ||
| 280 | put_write_and_out: | 280 | put_write_and_out: |
| 281 | put_write_access(inode); | 281 | put_write_access(inode); |
| 282 | mnt_drop_write_and_out: | 282 | mnt_drop_write_and_out: |
| 283 | mnt_drop_write(nd.path.mnt); | 283 | mnt_drop_write(path.mnt); |
| 284 | dput_and_out: | 284 | dput_and_out: |
| 285 | path_put(&nd.path); | 285 | path_put(&path); |
| 286 | out: | 286 | out: |
| 287 | return error; | 287 | return error; |
| 288 | } | 288 | } |
| @@ -425,7 +425,8 @@ out: | |||
| 425 | */ | 425 | */ |
| 426 | asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode) | 426 | asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode) |
| 427 | { | 427 | { |
| 428 | struct nameidata nd; | 428 | struct path path; |
| 429 | struct inode *inode; | ||
| 429 | int old_fsuid, old_fsgid; | 430 | int old_fsuid, old_fsgid; |
| 430 | kernel_cap_t uninitialized_var(old_cap); /* !SECURE_NO_SETUID_FIXUP */ | 431 | kernel_cap_t uninitialized_var(old_cap); /* !SECURE_NO_SETUID_FIXUP */ |
| 431 | int res; | 432 | int res; |
| @@ -448,7 +449,7 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode) | |||
| 448 | * FIXME: There is a race here against sys_capset. The | 449 | * FIXME: There is a race here against sys_capset. The |
| 449 | * capabilities can change yet we will restore the old | 450 | * capabilities can change yet we will restore the old |
| 450 | * value below. We should hold task_capabilities_lock, | 451 | * value below. We should hold task_capabilities_lock, |
| 451 | * but we cannot because user_path_walk can sleep. | 452 | * but we cannot because user_path_at can sleep. |
| 452 | */ | 453 | */ |
| 453 | #endif /* ndef CONFIG_SECURITY_FILE_CAPABILITIES */ | 454 | #endif /* ndef CONFIG_SECURITY_FILE_CAPABILITIES */ |
| 454 | if (current->uid) | 455 | if (current->uid) |
| @@ -457,14 +458,25 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode) | |||
| 457 | old_cap = cap_set_effective(current->cap_permitted); | 458 | old_cap = cap_set_effective(current->cap_permitted); |
| 458 | } | 459 | } |
| 459 | 460 | ||
| 460 | res = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd); | 461 | res = user_path_at(dfd, filename, LOOKUP_FOLLOW, &path); |
| 461 | if (res) | 462 | if (res) |
| 462 | goto out; | 463 | goto out; |
| 463 | 464 | ||
| 464 | res = vfs_permission(&nd, mode); | 465 | inode = path.dentry->d_inode; |
| 466 | |||
| 467 | if ((mode & MAY_EXEC) && S_ISREG(inode->i_mode)) { | ||
| 468 | /* | ||
| 469 | * MAY_EXEC on regular files is denied if the fs is mounted | ||
| 470 | * with the "noexec" flag. | ||
| 471 | */ | ||
| 472 | res = -EACCES; | ||
| 473 | if (path.mnt->mnt_flags & MNT_NOEXEC) | ||
| 474 | goto out_path_release; | ||
| 475 | } | ||
| 476 | |||
| 477 | res = inode_permission(inode, mode | MAY_ACCESS); | ||
| 465 | /* SuS v2 requires we report a read only fs too */ | 478 | /* SuS v2 requires we report a read only fs too */ |
| 466 | if(res || !(mode & S_IWOTH) || | 479 | if (res || !(mode & S_IWOTH) || special_file(inode->i_mode)) |
| 467 | special_file(nd.path.dentry->d_inode->i_mode)) | ||
| 468 | goto out_path_release; | 480 | goto out_path_release; |
| 469 | /* | 481 | /* |
| 470 | * This is a rare case where using __mnt_is_readonly() | 482 | * This is a rare case where using __mnt_is_readonly() |
| @@ -476,11 +488,11 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode) | |||
| 476 | * inherently racy and know that the fs may change | 488 | * inherently racy and know that the fs may change |
| 477 | * state before we even see this result. | 489 | * state before we even see this result. |
| 478 | */ | 490 | */ |
| 479 | if (__mnt_is_readonly(nd.path.mnt)) | 491 | if (__mnt_is_readonly(path.mnt)) |
| 480 | res = -EROFS; | 492 | res = -EROFS; |
| 481 | 493 | ||
| 482 | out_path_release: | 494 | out_path_release: |
| 483 | path_put(&nd.path); | 495 | path_put(&path); |
| 484 | out: | 496 | out: |
| 485 | current->fsuid = old_fsuid; | 497 | current->fsuid = old_fsuid; |
| 486 | current->fsgid = old_fsgid; | 498 | current->fsgid = old_fsgid; |
| @@ -498,22 +510,21 @@ asmlinkage long sys_access(const char __user *filename, int mode) | |||
| 498 | 510 | ||
| 499 | asmlinkage long sys_chdir(const char __user * filename) | 511 | asmlinkage long sys_chdir(const char __user * filename) |
| 500 | { | 512 | { |
| 501 | struct nameidata nd; | 513 | struct path path; |
| 502 | int error; | 514 | int error; |
| 503 | 515 | ||
| 504 | error = __user_walk(filename, | 516 | error = user_path_dir(filename, &path); |
| 505 | LOOKUP_FOLLOW|LOOKUP_DIRECTORY|LOOKUP_CHDIR, &nd); | ||
| 506 | if (error) | 517 | if (error) |
| 507 | goto out; | 518 | goto out; |
| 508 | 519 | ||
| 509 | error = vfs_permission(&nd, MAY_EXEC); | 520 | error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_ACCESS); |
| 510 | if (error) | 521 | if (error) |
| 511 | goto dput_and_out; | 522 | goto dput_and_out; |
| 512 | 523 | ||
| 513 | set_fs_pwd(current->fs, &nd.path); | 524 | set_fs_pwd(current->fs, &path); |
| 514 | 525 | ||
| 515 | dput_and_out: | 526 | dput_and_out: |
| 516 | path_put(&nd.path); | 527 | path_put(&path); |
| 517 | out: | 528 | out: |
| 518 | return error; | 529 | return error; |
| 519 | } | 530 | } |
| @@ -535,7 +546,7 @@ asmlinkage long sys_fchdir(unsigned int fd) | |||
| 535 | if (!S_ISDIR(inode->i_mode)) | 546 | if (!S_ISDIR(inode->i_mode)) |
| 536 | goto out_putf; | 547 | goto out_putf; |
| 537 | 548 | ||
| 538 | error = file_permission(file, MAY_EXEC); | 549 | error = inode_permission(inode, MAY_EXEC | MAY_ACCESS); |
| 539 | if (!error) | 550 | if (!error) |
| 540 | set_fs_pwd(current->fs, &file->f_path); | 551 | set_fs_pwd(current->fs, &file->f_path); |
| 541 | out_putf: | 552 | out_putf: |
| @@ -546,14 +557,14 @@ out: | |||
| 546 | 557 | ||
| 547 | asmlinkage long sys_chroot(const char __user * filename) | 558 | asmlinkage long sys_chroot(const char __user * filename) |
| 548 | { | 559 | { |
| 549 | struct nameidata nd; | 560 | struct path path; |
| 550 | int error; | 561 | int error; |
| 551 | 562 | ||
| 552 | error = __user_walk(filename, LOOKUP_FOLLOW | LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd); | 563 | error = user_path_dir(filename, &path); |
| 553 | if (error) | 564 | if (error) |
| 554 | goto out; | 565 | goto out; |
| 555 | 566 | ||
| 556 | error = vfs_permission(&nd, MAY_EXEC); | 567 | error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_ACCESS); |
| 557 | if (error) | 568 | if (error) |
| 558 | goto dput_and_out; | 569 | goto dput_and_out; |
| 559 | 570 | ||
| @@ -561,11 +572,10 @@ asmlinkage long sys_chroot(const char __user * filename) | |||
| 561 | if (!capable(CAP_SYS_CHROOT)) | 572 | if (!capable(CAP_SYS_CHROOT)) |
| 562 | goto dput_and_out; | 573 | goto dput_and_out; |
| 563 | 574 | ||
| 564 | set_fs_root(current->fs, &nd.path); | 575 | set_fs_root(current->fs, &path); |
| 565 | set_fs_altroot(); | ||
| 566 | error = 0; | 576 | error = 0; |
| 567 | dput_and_out: | 577 | dput_and_out: |
| 568 | path_put(&nd.path); | 578 | path_put(&path); |
| 569 | out: | 579 | out: |
| 570 | return error; | 580 | return error; |
| 571 | } | 581 | } |
| @@ -590,9 +600,6 @@ asmlinkage long sys_fchmod(unsigned int fd, mode_t mode) | |||
| 590 | err = mnt_want_write(file->f_path.mnt); | 600 | err = mnt_want_write(file->f_path.mnt); |
| 591 | if (err) | 601 | if (err) |
| 592 | goto out_putf; | 602 | goto out_putf; |
| 593 | err = -EPERM; | ||
| 594 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) | ||
| 595 | goto out_drop_write; | ||
| 596 | mutex_lock(&inode->i_mutex); | 603 | mutex_lock(&inode->i_mutex); |
| 597 | if (mode == (mode_t) -1) | 604 | if (mode == (mode_t) -1) |
| 598 | mode = inode->i_mode; | 605 | mode = inode->i_mode; |
| @@ -600,8 +607,6 @@ asmlinkage long sys_fchmod(unsigned int fd, mode_t mode) | |||
| 600 | newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; | 607 | newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; |
| 601 | err = notify_change(dentry, &newattrs); | 608 | err = notify_change(dentry, &newattrs); |
| 602 | mutex_unlock(&inode->i_mutex); | 609 | mutex_unlock(&inode->i_mutex); |
| 603 | |||
| 604 | out_drop_write: | ||
| 605 | mnt_drop_write(file->f_path.mnt); | 610 | mnt_drop_write(file->f_path.mnt); |
| 606 | out_putf: | 611 | out_putf: |
| 607 | fput(file); | 612 | fput(file); |
| @@ -612,36 +617,29 @@ out: | |||
| 612 | asmlinkage long sys_fchmodat(int dfd, const char __user *filename, | 617 | asmlinkage long sys_fchmodat(int dfd, const char __user *filename, |
| 613 | mode_t mode) | 618 | mode_t mode) |
| 614 | { | 619 | { |
| 615 | struct nameidata nd; | 620 | struct path path; |
| 616 | struct inode * inode; | 621 | struct inode *inode; |
| 617 | int error; | 622 | int error; |
| 618 | struct iattr newattrs; | 623 | struct iattr newattrs; |
| 619 | 624 | ||
| 620 | error = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW, &nd); | 625 | error = user_path_at(dfd, filename, LOOKUP_FOLLOW, &path); |
| 621 | if (error) | 626 | if (error) |
| 622 | goto out; | 627 | goto out; |
| 623 | inode = nd.path.dentry->d_inode; | 628 | inode = path.dentry->d_inode; |
| 624 | 629 | ||
| 625 | error = mnt_want_write(nd.path.mnt); | 630 | error = mnt_want_write(path.mnt); |
| 626 | if (error) | 631 | if (error) |
| 627 | goto dput_and_out; | 632 | goto dput_and_out; |
| 628 | |||
| 629 | error = -EPERM; | ||
| 630 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) | ||
| 631 | goto out_drop_write; | ||
| 632 | |||
| 633 | mutex_lock(&inode->i_mutex); | 633 | mutex_lock(&inode->i_mutex); |
| 634 | if (mode == (mode_t) -1) | 634 | if (mode == (mode_t) -1) |
| 635 | mode = inode->i_mode; | 635 | mode = inode->i_mode; |
| 636 | newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); | 636 | newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); |
| 637 | newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; | 637 | newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; |
| 638 | error = notify_change(nd.path.dentry, &newattrs); | 638 | error = notify_change(path.dentry, &newattrs); |
| 639 | mutex_unlock(&inode->i_mutex); | 639 | mutex_unlock(&inode->i_mutex); |
| 640 | 640 | mnt_drop_write(path.mnt); | |
| 641 | out_drop_write: | ||
| 642 | mnt_drop_write(nd.path.mnt); | ||
| 643 | dput_and_out: | 641 | dput_and_out: |
| 644 | path_put(&nd.path); | 642 | path_put(&path); |
| 645 | out: | 643 | out: |
| 646 | return error; | 644 | return error; |
| 647 | } | 645 | } |
| @@ -653,18 +651,10 @@ asmlinkage long sys_chmod(const char __user *filename, mode_t mode) | |||
| 653 | 651 | ||
| 654 | static int chown_common(struct dentry * dentry, uid_t user, gid_t group) | 652 | static int chown_common(struct dentry * dentry, uid_t user, gid_t group) |
| 655 | { | 653 | { |
| 656 | struct inode * inode; | 654 | struct inode *inode = dentry->d_inode; |
| 657 | int error; | 655 | int error; |
| 658 | struct iattr newattrs; | 656 | struct iattr newattrs; |
| 659 | 657 | ||
| 660 | error = -ENOENT; | ||
| 661 | if (!(inode = dentry->d_inode)) { | ||
| 662 | printk(KERN_ERR "chown_common: NULL inode\n"); | ||
| 663 | goto out; | ||
| 664 | } | ||
| 665 | error = -EPERM; | ||
| 666 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) | ||
| 667 | goto out; | ||
| 668 | newattrs.ia_valid = ATTR_CTIME; | 658 | newattrs.ia_valid = ATTR_CTIME; |
| 669 | if (user != (uid_t) -1) { | 659 | if (user != (uid_t) -1) { |
| 670 | newattrs.ia_valid |= ATTR_UID; | 660 | newattrs.ia_valid |= ATTR_UID; |
| @@ -680,25 +670,25 @@ static int chown_common(struct dentry * dentry, uid_t user, gid_t group) | |||
| 680 | mutex_lock(&inode->i_mutex); | 670 | mutex_lock(&inode->i_mutex); |
| 681 | error = notify_change(dentry, &newattrs); | 671 | error = notify_change(dentry, &newattrs); |
| 682 | mutex_unlock(&inode->i_mutex); | 672 | mutex_unlock(&inode->i_mutex); |
| 683 | out: | 673 | |
| 684 | return error; | 674 | return error; |
| 685 | } | 675 | } |
| 686 | 676 | ||
| 687 | asmlinkage long sys_chown(const char __user * filename, uid_t user, gid_t group) | 677 | asmlinkage long sys_chown(const char __user * filename, uid_t user, gid_t group) |
| 688 | { | 678 | { |
| 689 | struct nameidata nd; | 679 | struct path path; |
| 690 | int error; | 680 | int error; |
| 691 | 681 | ||
| 692 | error = user_path_walk(filename, &nd); | 682 | error = user_path(filename, &path); |
| 693 | if (error) | 683 | if (error) |
| 694 | goto out; | 684 | goto out; |
| 695 | error = mnt_want_write(nd.path.mnt); | 685 | error = mnt_want_write(path.mnt); |
| 696 | if (error) | 686 | if (error) |
| 697 | goto out_release; | 687 | goto out_release; |
| 698 | error = chown_common(nd.path.dentry, user, group); | 688 | error = chown_common(path.dentry, user, group); |
| 699 | mnt_drop_write(nd.path.mnt); | 689 | mnt_drop_write(path.mnt); |
| 700 | out_release: | 690 | out_release: |
| 701 | path_put(&nd.path); | 691 | path_put(&path); |
| 702 | out: | 692 | out: |
| 703 | return error; | 693 | return error; |
| 704 | } | 694 | } |
| @@ -706,7 +696,7 @@ out: | |||
| 706 | asmlinkage long sys_fchownat(int dfd, const char __user *filename, uid_t user, | 696 | asmlinkage long sys_fchownat(int dfd, const char __user *filename, uid_t user, |
| 707 | gid_t group, int flag) | 697 | gid_t group, int flag) |
| 708 | { | 698 | { |
| 709 | struct nameidata nd; | 699 | struct path path; |
| 710 | int error = -EINVAL; | 700 | int error = -EINVAL; |
| 711 | int follow; | 701 | int follow; |
| 712 | 702 | ||
| @@ -714,35 +704,35 @@ asmlinkage long sys_fchownat(int dfd, const char __user *filename, uid_t user, | |||
| 714 | goto out; | 704 | goto out; |
| 715 | 705 | ||
| 716 | follow = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW; | 706 | follow = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW; |
| 717 | error = __user_walk_fd(dfd, filename, follow, &nd); | 707 | error = user_path_at(dfd, filename, follow, &path); |
| 718 | if (error) | 708 | if (error) |
| 719 | goto out; | 709 | goto out; |
| 720 | error = mnt_want_write(nd.path.mnt); | 710 | error = mnt_want_write(path.mnt); |
| 721 | if (error) | 711 | if (error) |
| 722 | goto out_release; | 712 | goto out_release; |
| 723 | error = chown_common(nd.path.dentry, user, group); | 713 | error = chown_common(path.dentry, user, group); |
| 724 | mnt_drop_write(nd.path.mnt); | 714 | mnt_drop_write(path.mnt); |
| 725 | out_release: | 715 | out_release: |
| 726 | path_put(&nd.path); | 716 | path_put(&path); |
| 727 | out: | 717 | out: |
| 728 | return error; | 718 | return error; |
| 729 | } | 719 | } |
| 730 | 720 | ||
| 731 | asmlinkage long sys_lchown(const char __user * filename, uid_t user, gid_t group) | 721 | asmlinkage long sys_lchown(const char __user * filename, uid_t user, gid_t group) |
| 732 | { | 722 | { |
| 733 | struct nameidata nd; | 723 | struct path path; |
| 734 | int error; | 724 | int error; |
| 735 | 725 | ||
| 736 | error = user_path_walk_link(filename, &nd); | 726 | error = user_lpath(filename, &path); |
| 737 | if (error) | 727 | if (error) |
| 738 | goto out; | 728 | goto out; |
| 739 | error = mnt_want_write(nd.path.mnt); | 729 | error = mnt_want_write(path.mnt); |
| 740 | if (error) | 730 | if (error) |
| 741 | goto out_release; | 731 | goto out_release; |
| 742 | error = chown_common(nd.path.dentry, user, group); | 732 | error = chown_common(path.dentry, user, group); |
| 743 | mnt_drop_write(nd.path.mnt); | 733 | mnt_drop_write(path.mnt); |
| 744 | out_release: | 734 | out_release: |
| 745 | path_put(&nd.path); | 735 | path_put(&path); |
| 746 | out: | 736 | out: |
| 747 | return error; | 737 | return error; |
| 748 | } | 738 | } |
| @@ -982,7 +972,6 @@ int get_unused_fd_flags(int flags) | |||
| 982 | int fd, error; | 972 | int fd, error; |
| 983 | struct fdtable *fdt; | 973 | struct fdtable *fdt; |
| 984 | 974 | ||
| 985 | error = -EMFILE; | ||
| 986 | spin_lock(&files->file_lock); | 975 | spin_lock(&files->file_lock); |
| 987 | 976 | ||
| 988 | repeat: | 977 | repeat: |
| @@ -990,13 +979,6 @@ repeat: | |||
| 990 | fd = find_next_zero_bit(fdt->open_fds->fds_bits, fdt->max_fds, | 979 | fd = find_next_zero_bit(fdt->open_fds->fds_bits, fdt->max_fds, |
| 991 | files->next_fd); | 980 | files->next_fd); |
| 992 | 981 | ||
| 993 | /* | ||
| 994 | * N.B. For clone tasks sharing a files structure, this test | ||
| 995 | * will limit the total number of files that can be opened. | ||
| 996 | */ | ||
| 997 | if (fd >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur) | ||
| 998 | goto out; | ||
| 999 | |||
| 1000 | /* Do we need to expand the fd array or fd set? */ | 982 | /* Do we need to expand the fd array or fd set? */ |
| 1001 | error = expand_files(files, fd); | 983 | error = expand_files(files, fd); |
| 1002 | if (error < 0) | 984 | if (error < 0) |
| @@ -1007,7 +989,6 @@ repeat: | |||
| 1007 | * If we needed to expand the fs array we | 989 | * If we needed to expand the fs array we |
| 1008 | * might have blocked - try again. | 990 | * might have blocked - try again. |
| 1009 | */ | 991 | */ |
| 1010 | error = -EMFILE; | ||
| 1011 | goto repeat; | 992 | goto repeat; |
| 1012 | } | 993 | } |
| 1013 | 994 | ||
