diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2008-07-22 09:59:21 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2008-07-26 20:53:34 -0400 |
commit | 2d8f30380ab8c706f4e0a8f1aaa22b5886e9ac8a (patch) | |
tree | b798097fd831eab39f35c8c2e5a8ccfd7a850ef5 /fs/open.c | |
parent | 256984a83880ff7ac78055cb87baea48137f0b77 (diff) |
[PATCH] sanitize __user_walk_fd() et.al.
* do not pass nameidata; struct path is all the callers want.
* switch to new helpers:
user_path_at(dfd, pathname, flags, &path)
user_path(pathname, &path)
user_lpath(pathname, &path)
user_path_dir(pathname, &path) (fail if not a directory)
The last 3 are trivial macro wrappers for the first one.
* remove nameidata in callers.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/open.c')
-rw-r--r-- | fs/open.c | 124 |
1 files changed, 62 insertions, 62 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,7 +247,7 @@ 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 | ||
@@ -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,7 @@ 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 | struct inode *inode; |
430 | int old_fsuid, old_fsgid; | 430 | int old_fsuid, old_fsgid; |
431 | kernel_cap_t uninitialized_var(old_cap); /* !SECURE_NO_SETUID_FIXUP */ | 431 | kernel_cap_t uninitialized_var(old_cap); /* !SECURE_NO_SETUID_FIXUP */ |
@@ -449,7 +449,7 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode) | |||
449 | * FIXME: There is a race here against sys_capset. The | 449 | * FIXME: There is a race here against sys_capset. The |
450 | * capabilities can change yet we will restore the old | 450 | * capabilities can change yet we will restore the old |
451 | * value below. We should hold task_capabilities_lock, | 451 | * value below. We should hold task_capabilities_lock, |
452 | * but we cannot because user_path_walk can sleep. | 452 | * but we cannot because user_path_at can sleep. |
453 | */ | 453 | */ |
454 | #endif /* ndef CONFIG_SECURITY_FILE_CAPABILITIES */ | 454 | #endif /* ndef CONFIG_SECURITY_FILE_CAPABILITIES */ |
455 | if (current->uid) | 455 | if (current->uid) |
@@ -458,11 +458,11 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode) | |||
458 | old_cap = cap_set_effective(current->cap_permitted); | 458 | old_cap = cap_set_effective(current->cap_permitted); |
459 | } | 459 | } |
460 | 460 | ||
461 | res = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW, &nd); | 461 | res = user_path_at(dfd, filename, LOOKUP_FOLLOW, &path); |
462 | if (res) | 462 | if (res) |
463 | goto out; | 463 | goto out; |
464 | 464 | ||
465 | inode = nd.path.dentry->d_inode; | 465 | inode = path.dentry->d_inode; |
466 | 466 | ||
467 | if ((mode & MAY_EXEC) && S_ISREG(inode->i_mode)) { | 467 | if ((mode & MAY_EXEC) && S_ISREG(inode->i_mode)) { |
468 | /* | 468 | /* |
@@ -470,7 +470,7 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode) | |||
470 | * with the "noexec" flag. | 470 | * with the "noexec" flag. |
471 | */ | 471 | */ |
472 | res = -EACCES; | 472 | res = -EACCES; |
473 | if (nd.path.mnt->mnt_flags & MNT_NOEXEC) | 473 | if (path.mnt->mnt_flags & MNT_NOEXEC) |
474 | goto out_path_release; | 474 | goto out_path_release; |
475 | } | 475 | } |
476 | 476 | ||
@@ -488,11 +488,11 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode) | |||
488 | * inherently racy and know that the fs may change | 488 | * inherently racy and know that the fs may change |
489 | * state before we even see this result. | 489 | * state before we even see this result. |
490 | */ | 490 | */ |
491 | if (__mnt_is_readonly(nd.path.mnt)) | 491 | if (__mnt_is_readonly(path.mnt)) |
492 | res = -EROFS; | 492 | res = -EROFS; |
493 | 493 | ||
494 | out_path_release: | 494 | out_path_release: |
495 | path_put(&nd.path); | 495 | path_put(&path); |
496 | out: | 496 | out: |
497 | current->fsuid = old_fsuid; | 497 | current->fsuid = old_fsuid; |
498 | current->fsgid = old_fsgid; | 498 | current->fsgid = old_fsgid; |
@@ -510,21 +510,21 @@ asmlinkage long sys_access(const char __user *filename, int mode) | |||
510 | 510 | ||
511 | asmlinkage long sys_chdir(const char __user * filename) | 511 | asmlinkage long sys_chdir(const char __user * filename) |
512 | { | 512 | { |
513 | struct nameidata nd; | 513 | struct path path; |
514 | int error; | 514 | int error; |
515 | 515 | ||
516 | error = __user_walk(filename, LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &nd); | 516 | error = user_path_dir(filename, &path); |
517 | if (error) | 517 | if (error) |
518 | goto out; | 518 | goto out; |
519 | 519 | ||
520 | error = inode_permission(nd.path.dentry->d_inode, MAY_EXEC | MAY_ACCESS); | 520 | error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_ACCESS); |
521 | if (error) | 521 | if (error) |
522 | goto dput_and_out; | 522 | goto dput_and_out; |
523 | 523 | ||
524 | set_fs_pwd(current->fs, &nd.path); | 524 | set_fs_pwd(current->fs, &path); |
525 | 525 | ||
526 | dput_and_out: | 526 | dput_and_out: |
527 | path_put(&nd.path); | 527 | path_put(&path); |
528 | out: | 528 | out: |
529 | return error; | 529 | return error; |
530 | } | 530 | } |
@@ -557,14 +557,14 @@ out: | |||
557 | 557 | ||
558 | asmlinkage long sys_chroot(const char __user * filename) | 558 | asmlinkage long sys_chroot(const char __user * filename) |
559 | { | 559 | { |
560 | struct nameidata nd; | 560 | struct path path; |
561 | int error; | 561 | int error; |
562 | 562 | ||
563 | error = __user_walk(filename, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &nd); | 563 | error = user_path_dir(filename, &path); |
564 | if (error) | 564 | if (error) |
565 | goto out; | 565 | goto out; |
566 | 566 | ||
567 | error = inode_permission(nd.path.dentry->d_inode, MAY_EXEC | MAY_ACCESS); | 567 | error = inode_permission(path.dentry->d_inode, MAY_EXEC | MAY_ACCESS); |
568 | if (error) | 568 | if (error) |
569 | goto dput_and_out; | 569 | goto dput_and_out; |
570 | 570 | ||
@@ -572,10 +572,10 @@ asmlinkage long sys_chroot(const char __user * filename) | |||
572 | if (!capable(CAP_SYS_CHROOT)) | 572 | if (!capable(CAP_SYS_CHROOT)) |
573 | goto dput_and_out; | 573 | goto dput_and_out; |
574 | 574 | ||
575 | set_fs_root(current->fs, &nd.path); | 575 | set_fs_root(current->fs, &path); |
576 | error = 0; | 576 | error = 0; |
577 | dput_and_out: | 577 | dput_and_out: |
578 | path_put(&nd.path); | 578 | path_put(&path); |
579 | out: | 579 | out: |
580 | return error; | 580 | return error; |
581 | } | 581 | } |
@@ -617,17 +617,17 @@ out: | |||
617 | asmlinkage long sys_fchmodat(int dfd, const char __user *filename, | 617 | asmlinkage long sys_fchmodat(int dfd, const char __user *filename, |
618 | mode_t mode) | 618 | mode_t mode) |
619 | { | 619 | { |
620 | struct nameidata nd; | 620 | struct path path; |
621 | struct inode * inode; | 621 | struct inode *inode; |
622 | int error; | 622 | int error; |
623 | struct iattr newattrs; | 623 | struct iattr newattrs; |
624 | 624 | ||
625 | error = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW, &nd); | 625 | error = user_path_at(dfd, filename, LOOKUP_FOLLOW, &path); |
626 | if (error) | 626 | if (error) |
627 | goto out; | 627 | goto out; |
628 | inode = nd.path.dentry->d_inode; | 628 | inode = path.dentry->d_inode; |
629 | 629 | ||
630 | error = mnt_want_write(nd.path.mnt); | 630 | error = mnt_want_write(path.mnt); |
631 | if (error) | 631 | if (error) |
632 | goto dput_and_out; | 632 | goto dput_and_out; |
633 | mutex_lock(&inode->i_mutex); | 633 | mutex_lock(&inode->i_mutex); |
@@ -635,11 +635,11 @@ asmlinkage long sys_fchmodat(int dfd, const char __user *filename, | |||
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 | mnt_drop_write(nd.path.mnt); | 640 | mnt_drop_write(path.mnt); |
641 | dput_and_out: | 641 | dput_and_out: |
642 | path_put(&nd.path); | 642 | path_put(&path); |
643 | out: | 643 | out: |
644 | return error; | 644 | return error; |
645 | } | 645 | } |
@@ -676,19 +676,19 @@ static int chown_common(struct dentry * dentry, uid_t user, gid_t group) | |||
676 | 676 | ||
677 | 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) |
678 | { | 678 | { |
679 | struct nameidata nd; | 679 | struct path path; |
680 | int error; | 680 | int error; |
681 | 681 | ||
682 | error = user_path_walk(filename, &nd); | 682 | error = user_path(filename, &path); |
683 | if (error) | 683 | if (error) |
684 | goto out; | 684 | goto out; |
685 | error = mnt_want_write(nd.path.mnt); | 685 | error = mnt_want_write(path.mnt); |
686 | if (error) | 686 | if (error) |
687 | goto out_release; | 687 | goto out_release; |
688 | error = chown_common(nd.path.dentry, user, group); | 688 | error = chown_common(path.dentry, user, group); |
689 | mnt_drop_write(nd.path.mnt); | 689 | mnt_drop_write(path.mnt); |
690 | out_release: | 690 | out_release: |
691 | path_put(&nd.path); | 691 | path_put(&path); |
692 | out: | 692 | out: |
693 | return error; | 693 | return error; |
694 | } | 694 | } |
@@ -696,7 +696,7 @@ out: | |||
696 | 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, |
697 | gid_t group, int flag) | 697 | gid_t group, int flag) |
698 | { | 698 | { |
699 | struct nameidata nd; | 699 | struct path path; |
700 | int error = -EINVAL; | 700 | int error = -EINVAL; |
701 | int follow; | 701 | int follow; |
702 | 702 | ||
@@ -704,35 +704,35 @@ asmlinkage long sys_fchownat(int dfd, const char __user *filename, uid_t user, | |||
704 | goto out; | 704 | goto out; |
705 | 705 | ||
706 | follow = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW; | 706 | follow = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW; |
707 | error = __user_walk_fd(dfd, filename, follow, &nd); | 707 | error = user_path_at(dfd, filename, follow, &path); |
708 | if (error) | 708 | if (error) |
709 | goto out; | 709 | goto out; |
710 | error = mnt_want_write(nd.path.mnt); | 710 | error = mnt_want_write(path.mnt); |
711 | if (error) | 711 | if (error) |
712 | goto out_release; | 712 | goto out_release; |
713 | error = chown_common(nd.path.dentry, user, group); | 713 | error = chown_common(path.dentry, user, group); |
714 | mnt_drop_write(nd.path.mnt); | 714 | mnt_drop_write(path.mnt); |
715 | out_release: | 715 | out_release: |
716 | path_put(&nd.path); | 716 | path_put(&path); |
717 | out: | 717 | out: |
718 | return error; | 718 | return error; |
719 | } | 719 | } |
720 | 720 | ||
721 | 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) |
722 | { | 722 | { |
723 | struct nameidata nd; | 723 | struct path path; |
724 | int error; | 724 | int error; |
725 | 725 | ||
726 | error = user_path_walk_link(filename, &nd); | 726 | error = user_lpath(filename, &path); |
727 | if (error) | 727 | if (error) |
728 | goto out; | 728 | goto out; |
729 | error = mnt_want_write(nd.path.mnt); | 729 | error = mnt_want_write(path.mnt); |
730 | if (error) | 730 | if (error) |
731 | goto out_release; | 731 | goto out_release; |
732 | error = chown_common(nd.path.dentry, user, group); | 732 | error = chown_common(path.dentry, user, group); |
733 | mnt_drop_write(nd.path.mnt); | 733 | mnt_drop_write(path.mnt); |
734 | out_release: | 734 | out_release: |
735 | path_put(&nd.path); | 735 | path_put(&path); |
736 | out: | 736 | out: |
737 | return error; | 737 | return error; |
738 | } | 738 | } |