aboutsummaryrefslogtreecommitdiffstats
path: root/fs/open.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2008-07-22 09:59:21 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2008-07-26 20:53:34 -0400
commit2d8f30380ab8c706f4e0a8f1aaa22b5886e9ac8a (patch)
treeb798097fd831eab39f35c8c2e5a8ccfd7a850ef5 /fs/open.c
parent256984a83880ff7ac78055cb87baea48137f0b77 (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.c124
1 files changed, 62 insertions, 62 deletions
diff --git a/fs/open.c b/fs/open.c
index e94266700eda..3fe1a6857c75 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -122,37 +122,37 @@ static int vfs_statfs64(struct dentry *dentry, struct statfs64 *buf)
122 return 0; 122 return 0;
123} 123}
124 124
125asmlinkage long sys_statfs(const char __user * path, struct statfs __user * buf) 125asmlinkage 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
142asmlinkage long sys_statfs64(const char __user *path, size_t sz, struct statfs64 __user *buf) 142asmlinkage 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
226static long do_sys_truncate(const char __user * path, loff_t length) 226static 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
280put_write_and_out: 280put_write_and_out:
281 put_write_access(inode); 281 put_write_access(inode);
282mnt_drop_write_and_out: 282mnt_drop_write_and_out:
283 mnt_drop_write(nd.path.mnt); 283 mnt_drop_write(path.mnt);
284dput_and_out: 284dput_and_out:
285 path_put(&nd.path); 285 path_put(&path);
286out: 286out:
287 return error; 287 return error;
288} 288}
@@ -425,7 +425,7 @@ 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 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
494out_path_release: 494out_path_release:
495 path_put(&nd.path); 495 path_put(&path);
496out: 496out:
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
511asmlinkage long sys_chdir(const char __user * filename) 511asmlinkage 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
526dput_and_out: 526dput_and_out:
527 path_put(&nd.path); 527 path_put(&path);
528out: 528out:
529 return error; 529 return error;
530} 530}
@@ -557,14 +557,14 @@ out:
557 557
558asmlinkage long sys_chroot(const char __user * filename) 558asmlinkage 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;
577dput_and_out: 577dput_and_out:
578 path_put(&nd.path); 578 path_put(&path);
579out: 579out:
580 return error; 580 return error;
581} 581}
@@ -617,17 +617,17 @@ out:
617asmlinkage long sys_fchmodat(int dfd, const char __user *filename, 617asmlinkage 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);
641dput_and_out: 641dput_and_out:
642 path_put(&nd.path); 642 path_put(&path);
643out: 643out:
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
677asmlinkage long sys_chown(const char __user * filename, uid_t user, gid_t group) 677asmlinkage 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);
690out_release: 690out_release:
691 path_put(&nd.path); 691 path_put(&path);
692out: 692out:
693 return error; 693 return error;
694} 694}
@@ -696,7 +696,7 @@ out:
696asmlinkage long sys_fchownat(int dfd, const char __user *filename, uid_t user, 696asmlinkage 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);
715out_release: 715out_release:
716 path_put(&nd.path); 716 path_put(&path);
717out: 717out:
718 return error; 718 return error;
719} 719}
720 720
721asmlinkage long sys_lchown(const char __user * filename, uid_t user, gid_t group) 721asmlinkage 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);
734out_release: 734out_release:
735 path_put(&nd.path); 735 path_put(&path);
736out: 736out:
737 return error; 737 return error;
738} 738}