diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-10-28 11:26:12 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-10-28 11:26:12 -0400 |
commit | 7a9787e1eba95a166265e6a260cf30af04ef0a99 (patch) | |
tree | e730a4565e0318140d2fbd2f0415d18a339d7336 /fs/open.c | |
parent | 41b9eb264c8407655db57b60b4457fe1b2ec9977 (diff) | |
parent | 0173a3265b228da319ceb9c1ec6a5682fd1b2d92 (diff) |
Merge commit 'v2.6.28-rc2' into x86/pci-ioapic-boot-irq-quirks
Diffstat (limited to 'fs/open.c')
-rw-r--r-- | fs/open.c | 243 |
1 files changed, 84 insertions, 159 deletions
@@ -64,7 +64,8 @@ static int vfs_statfs_native(struct dentry *dentry, struct statfs *buf) | |||
64 | memcpy(buf, &st, sizeof(st)); | 64 | memcpy(buf, &st, sizeof(st)); |
65 | else { | 65 | else { |
66 | if (sizeof buf->f_blocks == 4) { | 66 | if (sizeof buf->f_blocks == 4) { |
67 | if ((st.f_blocks | st.f_bfree | st.f_bavail) & | 67 | if ((st.f_blocks | st.f_bfree | st.f_bavail | |
68 | st.f_bsize | st.f_frsize) & | ||
68 | 0xffffffff00000000ULL) | 69 | 0xffffffff00000000ULL) |
69 | return -EOVERFLOW; | 70 | return -EOVERFLOW; |
70 | /* | 71 | /* |
@@ -121,37 +122,37 @@ static int vfs_statfs64(struct dentry *dentry, struct statfs64 *buf) | |||
121 | return 0; | 122 | return 0; |
122 | } | 123 | } |
123 | 124 | ||
124 | 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) |
125 | { | 126 | { |
126 | struct nameidata nd; | 127 | struct path path; |
127 | int error; | 128 | int error; |
128 | 129 | ||
129 | error = user_path_walk(path, &nd); | 130 | error = user_path(pathname, &path); |
130 | if (!error) { | 131 | if (!error) { |
131 | struct statfs tmp; | 132 | struct statfs tmp; |
132 | error = vfs_statfs_native(nd.path.dentry, &tmp); | 133 | error = vfs_statfs_native(path.dentry, &tmp); |
133 | if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) | 134 | if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) |
134 | error = -EFAULT; | 135 | error = -EFAULT; |
135 | path_put(&nd.path); | 136 | path_put(&path); |
136 | } | 137 | } |
137 | return error; | 138 | return error; |
138 | } | 139 | } |
139 | 140 | ||
140 | 141 | ||
141 | 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) |
142 | { | 143 | { |
143 | struct nameidata nd; | 144 | struct path path; |
144 | long error; | 145 | long error; |
145 | 146 | ||
146 | if (sz != sizeof(*buf)) | 147 | if (sz != sizeof(*buf)) |
147 | return -EINVAL; | 148 | return -EINVAL; |
148 | error = user_path_walk(path, &nd); | 149 | error = user_path(pathname, &path); |
149 | if (!error) { | 150 | if (!error) { |
150 | struct statfs64 tmp; | 151 | struct statfs64 tmp; |
151 | error = vfs_statfs64(nd.path.dentry, &tmp); | 152 | error = vfs_statfs64(path.dentry, &tmp); |
152 | if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) | 153 | if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) |
153 | error = -EFAULT; | 154 | error = -EFAULT; |
154 | path_put(&nd.path); | 155 | path_put(&path); |
155 | } | 156 | } |
156 | return error; | 157 | return error; |
157 | } | 158 | } |
@@ -222,20 +223,20 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs, | |||
222 | return err; | 223 | return err; |
223 | } | 224 | } |
224 | 225 | ||
225 | 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) |
226 | { | 227 | { |
227 | struct nameidata nd; | 228 | struct path path; |
228 | struct inode * inode; | 229 | struct inode *inode; |
229 | int error; | 230 | int error; |
230 | 231 | ||
231 | error = -EINVAL; | 232 | error = -EINVAL; |
232 | if (length < 0) /* sorry, but loff_t says... */ | 233 | if (length < 0) /* sorry, but loff_t says... */ |
233 | goto out; | 234 | goto out; |
234 | 235 | ||
235 | error = user_path_walk(path, &nd); | 236 | error = user_path(pathname, &path); |
236 | if (error) | 237 | if (error) |
237 | goto out; | 238 | goto out; |
238 | inode = nd.path.dentry->d_inode; | 239 | inode = path.dentry->d_inode; |
239 | 240 | ||
240 | /* For directories it's -EISDIR, for other non-regulars - -EINVAL */ | 241 | /* For directories it's -EISDIR, for other non-regulars - -EINVAL */ |
241 | error = -EISDIR; | 242 | error = -EISDIR; |
@@ -246,16 +247,16 @@ static long do_sys_truncate(const char __user * path, loff_t length) | |||
246 | if (!S_ISREG(inode->i_mode)) | 247 | if (!S_ISREG(inode->i_mode)) |
247 | goto dput_and_out; | 248 | goto dput_and_out; |
248 | 249 | ||
249 | error = mnt_want_write(nd.path.mnt); | 250 | error = mnt_want_write(path.mnt); |
250 | if (error) | 251 | if (error) |
251 | goto dput_and_out; | 252 | goto dput_and_out; |
252 | 253 | ||
253 | error = vfs_permission(&nd, MAY_WRITE); | 254 | error = inode_permission(inode, MAY_WRITE); |
254 | if (error) | 255 | if (error) |
255 | goto mnt_drop_write_and_out; | 256 | goto mnt_drop_write_and_out; |
256 | 257 | ||
257 | error = -EPERM; | 258 | error = -EPERM; |
258 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) | 259 | if (IS_APPEND(inode)) |
259 | goto mnt_drop_write_and_out; | 260 | goto mnt_drop_write_and_out; |
260 | 261 | ||
261 | error = get_write_access(inode); | 262 | error = get_write_access(inode); |
@@ -273,15 +274,15 @@ static long do_sys_truncate(const char __user * path, loff_t length) | |||
273 | error = locks_verify_truncate(inode, NULL, length); | 274 | error = locks_verify_truncate(inode, NULL, length); |
274 | if (!error) { | 275 | if (!error) { |
275 | DQUOT_INIT(inode); | 276 | DQUOT_INIT(inode); |
276 | error = do_truncate(nd.path.dentry, length, 0, NULL); | 277 | error = do_truncate(path.dentry, length, 0, NULL); |
277 | } | 278 | } |
278 | 279 | ||
279 | put_write_and_out: | 280 | put_write_and_out: |
280 | put_write_access(inode); | 281 | put_write_access(inode); |
281 | mnt_drop_write_and_out: | 282 | mnt_drop_write_and_out: |
282 | mnt_drop_write(nd.path.mnt); | 283 | mnt_drop_write(path.mnt); |
283 | dput_and_out: | 284 | dput_and_out: |
284 | path_put(&nd.path); | 285 | path_put(&path); |
285 | out: | 286 | out: |
286 | return error; | 287 | return error; |
287 | } | 288 | } |
@@ -424,7 +425,8 @@ out: | |||
424 | */ | 425 | */ |
425 | 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) |
426 | { | 427 | { |
427 | struct nameidata nd; | 428 | struct path path; |
429 | struct inode *inode; | ||
428 | int old_fsuid, old_fsgid; | 430 | int old_fsuid, old_fsgid; |
429 | kernel_cap_t uninitialized_var(old_cap); /* !SECURE_NO_SETUID_FIXUP */ | 431 | kernel_cap_t uninitialized_var(old_cap); /* !SECURE_NO_SETUID_FIXUP */ |
430 | int res; | 432 | int res; |
@@ -447,7 +449,7 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode) | |||
447 | * FIXME: There is a race here against sys_capset. The | 449 | * FIXME: There is a race here against sys_capset. The |
448 | * capabilities can change yet we will restore the old | 450 | * capabilities can change yet we will restore the old |
449 | * value below. We should hold task_capabilities_lock, | 451 | * value below. We should hold task_capabilities_lock, |
450 | * but we cannot because user_path_walk can sleep. | 452 | * but we cannot because user_path_at can sleep. |
451 | */ | 453 | */ |
452 | #endif /* ndef CONFIG_SECURITY_FILE_CAPABILITIES */ | 454 | #endif /* ndef CONFIG_SECURITY_FILE_CAPABILITIES */ |
453 | if (current->uid) | 455 | if (current->uid) |
@@ -456,14 +458,25 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode) | |||
456 | old_cap = cap_set_effective(current->cap_permitted); | 458 | old_cap = cap_set_effective(current->cap_permitted); |
457 | } | 459 | } |
458 | 460 | ||
459 | res = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd); | 461 | res = user_path_at(dfd, filename, LOOKUP_FOLLOW, &path); |
460 | if (res) | 462 | if (res) |
461 | goto out; | 463 | goto out; |
462 | 464 | ||
463 | 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); | ||
464 | /* SuS v2 requires we report a read only fs too */ | 478 | /* SuS v2 requires we report a read only fs too */ |
465 | if(res || !(mode & S_IWOTH) || | 479 | if (res || !(mode & S_IWOTH) || special_file(inode->i_mode)) |
466 | special_file(nd.path.dentry->d_inode->i_mode)) | ||
467 | goto out_path_release; | 480 | goto out_path_release; |
468 | /* | 481 | /* |
469 | * This is a rare case where using __mnt_is_readonly() | 482 | * This is a rare case where using __mnt_is_readonly() |
@@ -475,11 +488,11 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode) | |||
475 | * inherently racy and know that the fs may change | 488 | * inherently racy and know that the fs may change |
476 | * state before we even see this result. | 489 | * state before we even see this result. |
477 | */ | 490 | */ |
478 | if (__mnt_is_readonly(nd.path.mnt)) | 491 | if (__mnt_is_readonly(path.mnt)) |
479 | res = -EROFS; | 492 | res = -EROFS; |
480 | 493 | ||
481 | out_path_release: | 494 | out_path_release: |
482 | path_put(&nd.path); | 495 | path_put(&path); |
483 | out: | 496 | out: |
484 | current->fsuid = old_fsuid; | 497 | current->fsuid = old_fsuid; |
485 | current->fsgid = old_fsgid; | 498 | current->fsgid = old_fsgid; |
@@ -497,22 +510,21 @@ asmlinkage long sys_access(const char __user *filename, int mode) | |||
497 | 510 | ||
498 | asmlinkage long sys_chdir(const char __user * filename) | 511 | asmlinkage long sys_chdir(const char __user * filename) |
499 | { | 512 | { |
500 | struct nameidata nd; | 513 | struct path path; |
501 | int error; | 514 | int error; |
502 | 515 | ||
503 | error = __user_walk(filename, | 516 | error = user_path_dir(filename, &path); |
504 | LOOKUP_FOLLOW|LOOKUP_DIRECTORY|LOOKUP_CHDIR, &nd); | ||
505 | if (error) | 517 | if (error) |
506 | goto out; | 518 | goto out; |
507 | 519 | ||
508 | error = vfs_permission(&nd, MAY_EXEC); | 520 | error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_ACCESS); |
509 | if (error) | 521 | if (error) |
510 | goto dput_and_out; | 522 | goto dput_and_out; |
511 | 523 | ||
512 | set_fs_pwd(current->fs, &nd.path); | 524 | set_fs_pwd(current->fs, &path); |
513 | 525 | ||
514 | dput_and_out: | 526 | dput_and_out: |
515 | path_put(&nd.path); | 527 | path_put(&path); |
516 | out: | 528 | out: |
517 | return error; | 529 | return error; |
518 | } | 530 | } |
@@ -534,7 +546,7 @@ asmlinkage long sys_fchdir(unsigned int fd) | |||
534 | if (!S_ISDIR(inode->i_mode)) | 546 | if (!S_ISDIR(inode->i_mode)) |
535 | goto out_putf; | 547 | goto out_putf; |
536 | 548 | ||
537 | error = file_permission(file, MAY_EXEC); | 549 | error = inode_permission(inode, MAY_EXEC | MAY_ACCESS); |
538 | if (!error) | 550 | if (!error) |
539 | set_fs_pwd(current->fs, &file->f_path); | 551 | set_fs_pwd(current->fs, &file->f_path); |
540 | out_putf: | 552 | out_putf: |
@@ -545,14 +557,14 @@ out: | |||
545 | 557 | ||
546 | asmlinkage long sys_chroot(const char __user * filename) | 558 | asmlinkage long sys_chroot(const char __user * filename) |
547 | { | 559 | { |
548 | struct nameidata nd; | 560 | struct path path; |
549 | int error; | 561 | int error; |
550 | 562 | ||
551 | error = __user_walk(filename, LOOKUP_FOLLOW | LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd); | 563 | error = user_path_dir(filename, &path); |
552 | if (error) | 564 | if (error) |
553 | goto out; | 565 | goto out; |
554 | 566 | ||
555 | error = vfs_permission(&nd, MAY_EXEC); | 567 | error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_ACCESS); |
556 | if (error) | 568 | if (error) |
557 | goto dput_and_out; | 569 | goto dput_and_out; |
558 | 570 | ||
@@ -560,11 +572,10 @@ asmlinkage long sys_chroot(const char __user * filename) | |||
560 | if (!capable(CAP_SYS_CHROOT)) | 572 | if (!capable(CAP_SYS_CHROOT)) |
561 | goto dput_and_out; | 573 | goto dput_and_out; |
562 | 574 | ||
563 | set_fs_root(current->fs, &nd.path); | 575 | set_fs_root(current->fs, &path); |
564 | set_fs_altroot(); | ||
565 | error = 0; | 576 | error = 0; |
566 | dput_and_out: | 577 | dput_and_out: |
567 | path_put(&nd.path); | 578 | path_put(&path); |
568 | out: | 579 | out: |
569 | return error; | 580 | return error; |
570 | } | 581 | } |
@@ -589,9 +600,6 @@ asmlinkage long sys_fchmod(unsigned int fd, mode_t mode) | |||
589 | err = mnt_want_write(file->f_path.mnt); | 600 | err = mnt_want_write(file->f_path.mnt); |
590 | if (err) | 601 | if (err) |
591 | goto out_putf; | 602 | goto out_putf; |
592 | err = -EPERM; | ||
593 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) | ||
594 | goto out_drop_write; | ||
595 | mutex_lock(&inode->i_mutex); | 603 | mutex_lock(&inode->i_mutex); |
596 | if (mode == (mode_t) -1) | 604 | if (mode == (mode_t) -1) |
597 | mode = inode->i_mode; | 605 | mode = inode->i_mode; |
@@ -599,8 +607,6 @@ asmlinkage long sys_fchmod(unsigned int fd, mode_t mode) | |||
599 | newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; | 607 | newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; |
600 | err = notify_change(dentry, &newattrs); | 608 | err = notify_change(dentry, &newattrs); |
601 | mutex_unlock(&inode->i_mutex); | 609 | mutex_unlock(&inode->i_mutex); |
602 | |||
603 | out_drop_write: | ||
604 | mnt_drop_write(file->f_path.mnt); | 610 | mnt_drop_write(file->f_path.mnt); |
605 | out_putf: | 611 | out_putf: |
606 | fput(file); | 612 | fput(file); |
@@ -611,36 +617,29 @@ out: | |||
611 | asmlinkage long sys_fchmodat(int dfd, const char __user *filename, | 617 | asmlinkage long sys_fchmodat(int dfd, const char __user *filename, |
612 | mode_t mode) | 618 | mode_t mode) |
613 | { | 619 | { |
614 | struct nameidata nd; | 620 | struct path path; |
615 | struct inode * inode; | 621 | struct inode *inode; |
616 | int error; | 622 | int error; |
617 | struct iattr newattrs; | 623 | struct iattr newattrs; |
618 | 624 | ||
619 | error = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW, &nd); | 625 | error = user_path_at(dfd, filename, LOOKUP_FOLLOW, &path); |
620 | if (error) | 626 | if (error) |
621 | goto out; | 627 | goto out; |
622 | inode = nd.path.dentry->d_inode; | 628 | inode = path.dentry->d_inode; |
623 | 629 | ||
624 | error = mnt_want_write(nd.path.mnt); | 630 | error = mnt_want_write(path.mnt); |
625 | if (error) | 631 | if (error) |
626 | goto dput_and_out; | 632 | goto dput_and_out; |
627 | |||
628 | error = -EPERM; | ||
629 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) | ||
630 | goto out_drop_write; | ||
631 | |||
632 | mutex_lock(&inode->i_mutex); | 633 | mutex_lock(&inode->i_mutex); |
633 | if (mode == (mode_t) -1) | 634 | if (mode == (mode_t) -1) |
634 | mode = inode->i_mode; | 635 | mode = inode->i_mode; |
635 | newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); | 636 | newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); |
636 | newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; | 637 | newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; |
637 | error = notify_change(nd.path.dentry, &newattrs); | 638 | error = notify_change(path.dentry, &newattrs); |
638 | mutex_unlock(&inode->i_mutex); | 639 | mutex_unlock(&inode->i_mutex); |
639 | 640 | mnt_drop_write(path.mnt); | |
640 | out_drop_write: | ||
641 | mnt_drop_write(nd.path.mnt); | ||
642 | dput_and_out: | 641 | dput_and_out: |
643 | path_put(&nd.path); | 642 | path_put(&path); |
644 | out: | 643 | out: |
645 | return error; | 644 | return error; |
646 | } | 645 | } |
@@ -652,18 +651,10 @@ asmlinkage long sys_chmod(const char __user *filename, mode_t mode) | |||
652 | 651 | ||
653 | 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) |
654 | { | 653 | { |
655 | struct inode * inode; | 654 | struct inode *inode = dentry->d_inode; |
656 | int error; | 655 | int error; |
657 | struct iattr newattrs; | 656 | struct iattr newattrs; |
658 | 657 | ||
659 | error = -ENOENT; | ||
660 | if (!(inode = dentry->d_inode)) { | ||
661 | printk(KERN_ERR "chown_common: NULL inode\n"); | ||
662 | goto out; | ||
663 | } | ||
664 | error = -EPERM; | ||
665 | if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) | ||
666 | goto out; | ||
667 | newattrs.ia_valid = ATTR_CTIME; | 658 | newattrs.ia_valid = ATTR_CTIME; |
668 | if (user != (uid_t) -1) { | 659 | if (user != (uid_t) -1) { |
669 | newattrs.ia_valid |= ATTR_UID; | 660 | newattrs.ia_valid |= ATTR_UID; |
@@ -679,25 +670,25 @@ static int chown_common(struct dentry * dentry, uid_t user, gid_t group) | |||
679 | mutex_lock(&inode->i_mutex); | 670 | mutex_lock(&inode->i_mutex); |
680 | error = notify_change(dentry, &newattrs); | 671 | error = notify_change(dentry, &newattrs); |
681 | mutex_unlock(&inode->i_mutex); | 672 | mutex_unlock(&inode->i_mutex); |
682 | out: | 673 | |
683 | return error; | 674 | return error; |
684 | } | 675 | } |
685 | 676 | ||
686 | 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) |
687 | { | 678 | { |
688 | struct nameidata nd; | 679 | struct path path; |
689 | int error; | 680 | int error; |
690 | 681 | ||
691 | error = user_path_walk(filename, &nd); | 682 | error = user_path(filename, &path); |
692 | if (error) | 683 | if (error) |
693 | goto out; | 684 | goto out; |
694 | error = mnt_want_write(nd.path.mnt); | 685 | error = mnt_want_write(path.mnt); |
695 | if (error) | 686 | if (error) |
696 | goto out_release; | 687 | goto out_release; |
697 | error = chown_common(nd.path.dentry, user, group); | 688 | error = chown_common(path.dentry, user, group); |
698 | mnt_drop_write(nd.path.mnt); | 689 | mnt_drop_write(path.mnt); |
699 | out_release: | 690 | out_release: |
700 | path_put(&nd.path); | 691 | path_put(&path); |
701 | out: | 692 | out: |
702 | return error; | 693 | return error; |
703 | } | 694 | } |
@@ -705,7 +696,7 @@ out: | |||
705 | 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, |
706 | gid_t group, int flag) | 697 | gid_t group, int flag) |
707 | { | 698 | { |
708 | struct nameidata nd; | 699 | struct path path; |
709 | int error = -EINVAL; | 700 | int error = -EINVAL; |
710 | int follow; | 701 | int follow; |
711 | 702 | ||
@@ -713,35 +704,35 @@ asmlinkage long sys_fchownat(int dfd, const char __user *filename, uid_t user, | |||
713 | goto out; | 704 | goto out; |
714 | 705 | ||
715 | follow = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW; | 706 | follow = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW; |
716 | error = __user_walk_fd(dfd, filename, follow, &nd); | 707 | error = user_path_at(dfd, filename, follow, &path); |
717 | if (error) | 708 | if (error) |
718 | goto out; | 709 | goto out; |
719 | error = mnt_want_write(nd.path.mnt); | 710 | error = mnt_want_write(path.mnt); |
720 | if (error) | 711 | if (error) |
721 | goto out_release; | 712 | goto out_release; |
722 | error = chown_common(nd.path.dentry, user, group); | 713 | error = chown_common(path.dentry, user, group); |
723 | mnt_drop_write(nd.path.mnt); | 714 | mnt_drop_write(path.mnt); |
724 | out_release: | 715 | out_release: |
725 | path_put(&nd.path); | 716 | path_put(&path); |
726 | out: | 717 | out: |
727 | return error; | 718 | return error; |
728 | } | 719 | } |
729 | 720 | ||
730 | 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) |
731 | { | 722 | { |
732 | struct nameidata nd; | 723 | struct path path; |
733 | int error; | 724 | int error; |
734 | 725 | ||
735 | error = user_path_walk_link(filename, &nd); | 726 | error = user_lpath(filename, &path); |
736 | if (error) | 727 | if (error) |
737 | goto out; | 728 | goto out; |
738 | error = mnt_want_write(nd.path.mnt); | 729 | error = mnt_want_write(path.mnt); |
739 | if (error) | 730 | if (error) |
740 | goto out_release; | 731 | goto out_release; |
741 | error = chown_common(nd.path.dentry, user, group); | 732 | error = chown_common(path.dentry, user, group); |
742 | mnt_drop_write(nd.path.mnt); | 733 | mnt_drop_write(path.mnt); |
743 | out_release: | 734 | out_release: |
744 | path_put(&nd.path); | 735 | path_put(&path); |
745 | out: | 736 | out: |
746 | return error; | 737 | return error; |
747 | } | 738 | } |
@@ -807,7 +798,7 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, | |||
807 | int error; | 798 | int error; |
808 | 799 | ||
809 | f->f_flags = flags; | 800 | f->f_flags = flags; |
810 | f->f_mode = ((flags+1) & O_ACCMODE) | FMODE_LSEEK | | 801 | f->f_mode = (__force fmode_t)((flags+1) & O_ACCMODE) | FMODE_LSEEK | |
811 | FMODE_PREAD | FMODE_PWRITE; | 802 | FMODE_PREAD | FMODE_PWRITE; |
812 | inode = dentry->d_inode; | 803 | inode = dentry->d_inode; |
813 | if (f->f_mode & FMODE_WRITE) { | 804 | if (f->f_mode & FMODE_WRITE) { |
@@ -972,71 +963,6 @@ struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags) | |||
972 | } | 963 | } |
973 | EXPORT_SYMBOL(dentry_open); | 964 | EXPORT_SYMBOL(dentry_open); |
974 | 965 | ||
975 | /* | ||
976 | * Find an empty file descriptor entry, and mark it busy. | ||
977 | */ | ||
978 | int get_unused_fd_flags(int flags) | ||
979 | { | ||
980 | struct files_struct * files = current->files; | ||
981 | int fd, error; | ||
982 | struct fdtable *fdt; | ||
983 | |||
984 | error = -EMFILE; | ||
985 | spin_lock(&files->file_lock); | ||
986 | |||
987 | repeat: | ||
988 | fdt = files_fdtable(files); | ||
989 | fd = find_next_zero_bit(fdt->open_fds->fds_bits, fdt->max_fds, | ||
990 | files->next_fd); | ||
991 | |||
992 | /* | ||
993 | * N.B. For clone tasks sharing a files structure, this test | ||
994 | * will limit the total number of files that can be opened. | ||
995 | */ | ||
996 | if (fd >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur) | ||
997 | goto out; | ||
998 | |||
999 | /* Do we need to expand the fd array or fd set? */ | ||
1000 | error = expand_files(files, fd); | ||
1001 | if (error < 0) | ||
1002 | goto out; | ||
1003 | |||
1004 | if (error) { | ||
1005 | /* | ||
1006 | * If we needed to expand the fs array we | ||
1007 | * might have blocked - try again. | ||
1008 | */ | ||
1009 | error = -EMFILE; | ||
1010 | goto repeat; | ||
1011 | } | ||
1012 | |||
1013 | FD_SET(fd, fdt->open_fds); | ||
1014 | if (flags & O_CLOEXEC) | ||
1015 | FD_SET(fd, fdt->close_on_exec); | ||
1016 | else | ||
1017 | FD_CLR(fd, fdt->close_on_exec); | ||
1018 | files->next_fd = fd + 1; | ||
1019 | #if 1 | ||
1020 | /* Sanity check */ | ||
1021 | if (fdt->fd[fd] != NULL) { | ||
1022 | printk(KERN_WARNING "get_unused_fd: slot %d not NULL!\n", fd); | ||
1023 | fdt->fd[fd] = NULL; | ||
1024 | } | ||
1025 | #endif | ||
1026 | error = fd; | ||
1027 | |||
1028 | out: | ||
1029 | spin_unlock(&files->file_lock); | ||
1030 | return error; | ||
1031 | } | ||
1032 | |||
1033 | int get_unused_fd(void) | ||
1034 | { | ||
1035 | return get_unused_fd_flags(0); | ||
1036 | } | ||
1037 | |||
1038 | EXPORT_SYMBOL(get_unused_fd); | ||
1039 | |||
1040 | static void __put_unused_fd(struct files_struct *files, unsigned int fd) | 966 | static void __put_unused_fd(struct files_struct *files, unsigned int fd) |
1041 | { | 967 | { |
1042 | struct fdtable *fdt = files_fdtable(files); | 968 | struct fdtable *fdt = files_fdtable(files); |
@@ -1215,8 +1141,7 @@ EXPORT_SYMBOL(sys_close); | |||
1215 | asmlinkage long sys_vhangup(void) | 1141 | asmlinkage long sys_vhangup(void) |
1216 | { | 1142 | { |
1217 | if (capable(CAP_SYS_TTY_CONFIG)) { | 1143 | if (capable(CAP_SYS_TTY_CONFIG)) { |
1218 | /* XXX: this needs locking */ | 1144 | tty_vhangup_self(); |
1219 | tty_vhangup(current->signal->tty); | ||
1220 | return 0; | 1145 | return 0; |
1221 | } | 1146 | } |
1222 | return -EPERM; | 1147 | return -EPERM; |