open.c (256984a83880ff7ac78055cb87baea48137f0b77) | open.c (2d8f30380ab8c706f4e0a8f1aaa22b5886e9ac8a) |
---|---|
1/* 2 * linux/fs/open.c 3 * 4 * Copyright (C) 1991, 1992 Linus Torvalds 5 */ 6 7#include <linux/string.h> 8#include <linux/mm.h> --- 108 unchanged lines hidden (view full) --- 117 buf->f_fsid = st.f_fsid; 118 buf->f_namelen = st.f_namelen; 119 buf->f_frsize = st.f_frsize; 120 memset(buf->f_spare, 0, sizeof(buf->f_spare)); 121 } 122 return 0; 123} 124 | 1/* 2 * linux/fs/open.c 3 * 4 * Copyright (C) 1991, 1992 Linus Torvalds 5 */ 6 7#include <linux/string.h> 8#include <linux/mm.h> --- 108 unchanged lines hidden (view full) --- 117 buf->f_fsid = st.f_fsid; 118 buf->f_namelen = st.f_namelen; 119 buf->f_frsize = st.f_frsize; 120 memset(buf->f_spare, 0, sizeof(buf->f_spare)); 121 } 122 return 0; 123} 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; 129 | 128 int error; 129 |
130 error = user_path_walk(path, &nd); | 130 error = user_path(pathname, &path); |
131 if (!error) { 132 struct statfs tmp; | 131 if (!error) { 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))) 135 error = -EFAULT; | 134 if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) 135 error = -EFAULT; |
136 path_put(&nd.path); | 136 path_put(&path); |
137 } 138 return error; 139} 140 141 | 137 } 138 return error; 139} 140 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; 146 147 if (sz != sizeof(*buf)) 148 return -EINVAL; | 145 long error; 146 147 if (sz != sizeof(*buf)) 148 return -EINVAL; |
149 error = user_path_walk(path, &nd); | 149 error = user_path(pathname, &path); |
150 if (!error) { 151 struct statfs64 tmp; | 150 if (!error) { 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))) 154 error = -EFAULT; | 153 if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) 154 error = -EFAULT; |
155 path_put(&nd.path); | 155 path_put(&path); |
156 } 157 return error; 158} 159 160 161asmlinkage long sys_fstatfs(unsigned int fd, struct statfs __user * buf) 162{ 163 struct file * file; --- 54 unchanged lines hidden (view full) --- 218 newattrs.ia_valid |= should_remove_suid(dentry); 219 220 mutex_lock(&dentry->d_inode->i_mutex); 221 err = notify_change(dentry, &newattrs); 222 mutex_unlock(&dentry->d_inode->i_mutex); 223 return err; 224} 225 | 156 } 157 return error; 158} 159 160 161asmlinkage long sys_fstatfs(unsigned int fd, struct statfs __user * buf) 162{ 163 struct file * file; --- 54 unchanged lines hidden (view full) --- 218 newattrs.ia_valid |= should_remove_suid(dentry); 219 220 mutex_lock(&dentry->d_inode->i_mutex); 221 err = notify_change(dentry, &newattrs); 222 mutex_unlock(&dentry->d_inode->i_mutex); 223 return err; 224} 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; 229 struct inode * inode; | 228 struct path path; 229 struct inode *inode; |
230 int error; 231 232 error = -EINVAL; 233 if (length < 0) /* sorry, but loff_t says... */ 234 goto out; 235 | 230 int error; 231 232 error = -EINVAL; 233 if (length < 0) /* sorry, but loff_t says... */ 234 goto out; 235 |
236 error = user_path_walk(path, &nd); | 236 error = user_path(pathname, &path); |
237 if (error) 238 goto out; | 237 if (error) 238 goto out; |
239 inode = nd.path.dentry->d_inode; | 239 inode = path.dentry->d_inode; |
240 241 /* For directories it's -EISDIR, for other non-regulars - -EINVAL */ 242 error = -EISDIR; 243 if (S_ISDIR(inode->i_mode)) 244 goto dput_and_out; 245 246 error = -EINVAL; 247 if (!S_ISREG(inode->i_mode)) 248 goto dput_and_out; 249 | 240 241 /* For directories it's -EISDIR, for other non-regulars - -EINVAL */ 242 error = -EISDIR; 243 if (S_ISDIR(inode->i_mode)) 244 goto dput_and_out; 245 246 error = -EINVAL; 247 if (!S_ISREG(inode->i_mode)) 248 goto dput_and_out; 249 |
250 error = mnt_want_write(nd.path.mnt); | 250 error = mnt_want_write(path.mnt); |
251 if (error) 252 goto dput_and_out; 253 254 error = inode_permission(inode, MAY_WRITE); 255 if (error) 256 goto mnt_drop_write_and_out; 257 258 error = -EPERM; --- 10 unchanged lines hidden (view full) --- 269 */ 270 error = break_lease(inode, FMODE_WRITE); 271 if (error) 272 goto put_write_and_out; 273 274 error = locks_verify_truncate(inode, NULL, length); 275 if (!error) { 276 DQUOT_INIT(inode); | 251 if (error) 252 goto dput_and_out; 253 254 error = inode_permission(inode, MAY_WRITE); 255 if (error) 256 goto mnt_drop_write_and_out; 257 258 error = -EPERM; --- 10 unchanged lines hidden (view full) --- 269 */ 270 error = break_lease(inode, FMODE_WRITE); 271 if (error) 272 goto put_write_and_out; 273 274 error = locks_verify_truncate(inode, NULL, length); 275 if (!error) { 276 DQUOT_INIT(inode); |
277 error = do_truncate(nd.path.dentry, length, 0, NULL); | 277 error = do_truncate(path.dentry, length, 0, NULL); |
278 } 279 280put_write_and_out: 281 put_write_access(inode); 282mnt_drop_write_and_out: | 278 } 279 280put_write_and_out: 281 put_write_access(inode); 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: 287 return error; 288} 289 290asmlinkage long sys_truncate(const char __user * path, unsigned long length) 291{ 292 /* on 32-bit boxen it will cut the range 2^31--2^32-1 off */ 293 return do_sys_truncate(path, (long)length); --- 126 unchanged lines hidden (view full) --- 420 421/* 422 * access() needs to use the real uid/gid, not the effective uid/gid. 423 * We do this by temporarily clearing all FS-related capabilities and 424 * switching the fsuid/fsgid around to the real ones. 425 */ 426asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode) 427{ | 286out: 287 return error; 288} 289 290asmlinkage long sys_truncate(const char __user * path, unsigned long length) 291{ 292 /* on 32-bit boxen it will cut the range 2^31--2^32-1 off */ 293 return do_sys_truncate(path, (long)length); --- 126 unchanged lines hidden (view full) --- 420 421/* 422 * access() needs to use the real uid/gid, not the effective uid/gid. 423 * We do this by temporarily clearing all FS-related capabilities and 424 * switching the fsuid/fsgid around to the real ones. 425 */ 426asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode) 427{ |
428 struct nameidata nd; | 428 struct path path; |
429 struct inode *inode; 430 int old_fsuid, old_fsgid; 431 kernel_cap_t uninitialized_var(old_cap); /* !SECURE_NO_SETUID_FIXUP */ 432 int res; 433 434 if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */ 435 return -EINVAL; 436 --- 7 unchanged lines hidden (view full) --- 444 /* 445 * Clear the capabilities if we switch to a non-root user 446 */ 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, | 429 struct inode *inode; 430 int old_fsuid, old_fsgid; 431 kernel_cap_t uninitialized_var(old_cap); /* !SECURE_NO_SETUID_FIXUP */ 432 int res; 433 434 if (mode & ~S_IRWXO) /* where's F_OK, X_OK, W_OK, R_OK? */ 435 return -EINVAL; 436 --- 7 unchanged lines hidden (view full) --- 444 /* 445 * Clear the capabilities if we switch to a non-root user 446 */ 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_walk can sleep. | 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 458 old_cap = cap_set_effective(current->cap_permitted); 459 } 460 | 453 */ 454#endif /* ndef CONFIG_SECURITY_FILE_CAPABILITIES */ 455 if (current->uid) 456 old_cap = cap_set_effective(__cap_empty_set); 457 else 458 old_cap = cap_set_effective(current->cap_permitted); 459 } 460 |
461 res = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW, &nd); | 461 res = user_path_at(dfd, filename, LOOKUP_FOLLOW, &path); |
462 if (res) 463 goto out; 464 | 462 if (res) 463 goto out; 464 |
465 inode = nd.path.dentry->d_inode; | 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; | 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 (nd.path.mnt->mnt_flags & MNT_NOEXEC) | 473 if (path.mnt->mnt_flags & MNT_NOEXEC) |
474 goto out_path_release; 475 } 476 477 res = inode_permission(inode, mode | MAY_ACCESS); 478 /* SuS v2 requires we report a read only fs too */ 479 if (res || !(mode & S_IWOTH) || special_file(inode->i_mode)) 480 goto out_path_release; 481 /* 482 * This is a rare case where using __mnt_is_readonly() 483 * is OK without a mnt_want/drop_write() pair. Since 484 * no actual write to the fs is performed here, we do 485 * not need to telegraph to that to anyone. 486 * 487 * By doing this, we accept that this access is 488 * inherently racy and know that the fs may change 489 * state before we even see this result. 490 */ | 474 goto out_path_release; 475 } 476 477 res = inode_permission(inode, mode | MAY_ACCESS); 478 /* SuS v2 requires we report a read only fs too */ 479 if (res || !(mode & S_IWOTH) || special_file(inode->i_mode)) 480 goto out_path_release; 481 /* 482 * This is a rare case where using __mnt_is_readonly() 483 * is OK without a mnt_want/drop_write() pair. Since 484 * no actual write to the fs is performed here, we do 485 * not need to telegraph to that to anyone. 486 * 487 * By doing this, we accept that this access is 488 * inherently racy and know that the fs may change 489 * state before we even see this result. 490 */ |
491 if (__mnt_is_readonly(nd.path.mnt)) | 491 if (__mnt_is_readonly(path.mnt)) |
492 res = -EROFS; 493 494out_path_release: | 492 res = -EROFS; 493 494out_path_release: |
495 path_put(&nd.path); | 495 path_put(&path); |
496out: 497 current->fsuid = old_fsuid; 498 current->fsgid = old_fsgid; 499 500 if (!issecure(SECURE_NO_SETUID_FIXUP)) 501 cap_set_effective(old_cap); 502 503 return res; 504} 505 506asmlinkage long sys_access(const char __user *filename, int mode) 507{ 508 return sys_faccessat(AT_FDCWD, filename, mode); 509} 510 511asmlinkage long sys_chdir(const char __user * filename) 512{ | 496out: 497 current->fsuid = old_fsuid; 498 current->fsgid = old_fsgid; 499 500 if (!issecure(SECURE_NO_SETUID_FIXUP)) 501 cap_set_effective(old_cap); 502 503 return res; 504} 505 506asmlinkage long sys_access(const char __user *filename, int mode) 507{ 508 return sys_faccessat(AT_FDCWD, filename, mode); 509} 510 511asmlinkage long sys_chdir(const char __user * filename) 512{ |
513 struct nameidata nd; | 513 struct path path; |
514 int error; 515 | 514 int error; 515 |
516 error = __user_walk(filename, LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &nd); | 516 error = user_path_dir(filename, &path); |
517 if (error) 518 goto out; 519 | 517 if (error) 518 goto out; 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) 522 goto dput_and_out; 523 | 521 if (error) 522 goto dput_and_out; 523 |
524 set_fs_pwd(current->fs, &nd.path); | 524 set_fs_pwd(current->fs, &path); |
525 526dput_and_out: | 525 526dput_and_out: |
527 path_put(&nd.path); | 527 path_put(&path); |
528out: 529 return error; 530} 531 532asmlinkage long sys_fchdir(unsigned int fd) 533{ 534 struct file *file; 535 struct inode *inode; --- 16 unchanged lines hidden (view full) --- 552out_putf: 553 fput(file); 554out: 555 return error; 556} 557 558asmlinkage long sys_chroot(const char __user * filename) 559{ | 528out: 529 return error; 530} 531 532asmlinkage long sys_fchdir(unsigned int fd) 533{ 534 struct file *file; 535 struct inode *inode; --- 16 unchanged lines hidden (view full) --- 552out_putf: 553 fput(file); 554out: 555 return error; 556} 557 558asmlinkage long sys_chroot(const char __user * filename) 559{ |
560 struct nameidata nd; | 560 struct path path; |
561 int error; 562 | 561 int error; 562 |
563 error = __user_walk(filename, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &nd); | 563 error = user_path_dir(filename, &path); |
564 if (error) 565 goto out; 566 | 564 if (error) 565 goto out; 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) 569 goto dput_and_out; 570 571 error = -EPERM; 572 if (!capable(CAP_SYS_CHROOT)) 573 goto dput_and_out; 574 | 568 if (error) 569 goto dput_and_out; 570 571 error = -EPERM; 572 if (!capable(CAP_SYS_CHROOT)) 573 goto dput_and_out; 574 |
575 set_fs_root(current->fs, &nd.path); | 575 set_fs_root(current->fs, &path); |
576 error = 0; 577dput_and_out: | 576 error = 0; 577dput_and_out: |
578 path_put(&nd.path); | 578 path_put(&path); |
579out: 580 return error; 581} 582 583asmlinkage long sys_fchmod(unsigned int fd, mode_t mode) 584{ 585 struct inode * inode; 586 struct dentry * dentry; --- 25 unchanged lines hidden (view full) --- 612 fput(file); 613out: 614 return err; 615} 616 617asmlinkage long sys_fchmodat(int dfd, const char __user *filename, 618 mode_t mode) 619{ | 579out: 580 return error; 581} 582 583asmlinkage long sys_fchmod(unsigned int fd, mode_t mode) 584{ 585 struct inode * inode; 586 struct dentry * dentry; --- 25 unchanged lines hidden (view full) --- 612 fput(file); 613out: 614 return err; 615} 616 617asmlinkage long sys_fchmodat(int dfd, const char __user *filename, 618 mode_t mode) 619{ |
620 struct nameidata nd; 621 struct inode * inode; | 620 struct path path; 621 struct inode *inode; |
622 int error; 623 struct iattr newattrs; 624 | 622 int error; 623 struct iattr newattrs; 624 |
625 error = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW, &nd); | 625 error = user_path_at(dfd, filename, LOOKUP_FOLLOW, &path); |
626 if (error) 627 goto out; | 626 if (error) 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) 632 goto dput_and_out; 633 mutex_lock(&inode->i_mutex); 634 if (mode == (mode_t) -1) 635 mode = inode->i_mode; 636 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); 637 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; | 631 if (error) 632 goto dput_and_out; 633 mutex_lock(&inode->i_mutex); 634 if (mode == (mode_t) -1) 635 mode = inode->i_mode; 636 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); 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: 644 return error; 645} 646 647asmlinkage long sys_chmod(const char __user *filename, mode_t mode) 648{ 649 return sys_fchmodat(AT_FDCWD, filename, mode); 650} --- 20 unchanged lines hidden (view full) --- 671 error = notify_change(dentry, &newattrs); 672 mutex_unlock(&inode->i_mutex); 673 674 return error; 675} 676 677asmlinkage long sys_chown(const char __user * filename, uid_t user, gid_t group) 678{ | 643out: 644 return error; 645} 646 647asmlinkage long sys_chmod(const char __user *filename, mode_t mode) 648{ 649 return sys_fchmodat(AT_FDCWD, filename, mode); 650} --- 20 unchanged lines hidden (view full) --- 671 error = notify_change(dentry, &newattrs); 672 mutex_unlock(&inode->i_mutex); 673 674 return error; 675} 676 677asmlinkage long sys_chown(const char __user * filename, uid_t user, gid_t group) 678{ |
679 struct nameidata nd; | 679 struct path path; |
680 int error; 681 | 680 int error; 681 |
682 error = user_path_walk(filename, &nd); | 682 error = user_path(filename, &path); |
683 if (error) 684 goto out; | 683 if (error) 684 goto out; |
685 error = mnt_want_write(nd.path.mnt); | 685 error = mnt_want_write(path.mnt); |
686 if (error) 687 goto out_release; | 686 if (error) 687 goto out_release; |
688 error = chown_common(nd.path.dentry, user, group); 689 mnt_drop_write(nd.path.mnt); | 688 error = chown_common(path.dentry, user, group); 689 mnt_drop_write(path.mnt); |
690out_release: | 690out_release: |
691 path_put(&nd.path); | 691 path_put(&path); |
692out: 693 return error; 694} 695 696asmlinkage long sys_fchownat(int dfd, const char __user *filename, uid_t user, 697 gid_t group, int flag) 698{ | 692out: 693 return error; 694} 695 696asmlinkage long sys_fchownat(int dfd, const char __user *filename, uid_t user, 697 gid_t group, int flag) 698{ |
699 struct nameidata nd; | 699 struct path path; |
700 int error = -EINVAL; 701 int follow; 702 703 if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0) 704 goto out; 705 706 follow = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW; | 700 int error = -EINVAL; 701 int follow; 702 703 if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0) 704 goto out; 705 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) 709 goto out; | 708 if (error) 709 goto out; |
710 error = mnt_want_write(nd.path.mnt); | 710 error = mnt_want_write(path.mnt); |
711 if (error) 712 goto out_release; | 711 if (error) 712 goto out_release; |
713 error = chown_common(nd.path.dentry, user, group); 714 mnt_drop_write(nd.path.mnt); | 713 error = chown_common(path.dentry, user, group); 714 mnt_drop_write(path.mnt); |
715out_release: | 715out_release: |
716 path_put(&nd.path); | 716 path_put(&path); |
717out: 718 return error; 719} 720 721asmlinkage long sys_lchown(const char __user * filename, uid_t user, gid_t group) 722{ | 717out: 718 return error; 719} 720 721asmlinkage long sys_lchown(const char __user * filename, uid_t user, gid_t group) 722{ |
723 struct nameidata nd; | 723 struct path path; |
724 int error; 725 | 724 int error; 725 |
726 error = user_path_walk_link(filename, &nd); | 726 error = user_lpath(filename, &path); |
727 if (error) 728 goto out; | 727 if (error) 728 goto out; |
729 error = mnt_want_write(nd.path.mnt); | 729 error = mnt_want_write(path.mnt); |
730 if (error) 731 goto out_release; | 730 if (error) 731 goto out_release; |
732 error = chown_common(nd.path.dentry, user, group); 733 mnt_drop_write(nd.path.mnt); | 732 error = chown_common(path.dentry, user, group); 733 mnt_drop_write(path.mnt); |
734out_release: | 734out_release: |
735 path_put(&nd.path); | 735 path_put(&path); |
736out: 737 return error; 738} 739 740 741asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group) 742{ 743 struct file * file; --- 498 unchanged lines hidden --- | 736out: 737 return error; 738} 739 740 741asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group) 742{ 743 struct file * file; --- 498 unchanged lines hidden --- |