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 ---