aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/namei.c122
1 files changed, 122 insertions, 0 deletions
diff --git a/fs/namei.c b/fs/namei.c
index afa087649ddb..3861d85f8488 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -650,6 +650,119 @@ static inline void put_link(struct nameidata *nd, struct path *link, void *cooki
650 path_put(link); 650 path_put(link);
651} 651}
652 652
653int sysctl_protected_symlinks __read_mostly = 1;
654int sysctl_protected_hardlinks __read_mostly = 1;
655
656/**
657 * may_follow_link - Check symlink following for unsafe situations
658 * @link: The path of the symlink
659 *
660 * In the case of the sysctl_protected_symlinks sysctl being enabled,
661 * CAP_DAC_OVERRIDE needs to be specifically ignored if the symlink is
662 * in a sticky world-writable directory. This is to protect privileged
663 * processes from failing races against path names that may change out
664 * from under them by way of other users creating malicious symlinks.
665 * It will permit symlinks to be followed only when outside a sticky
666 * world-writable directory, or when the uid of the symlink and follower
667 * match, or when the directory owner matches the symlink's owner.
668 *
669 * Returns 0 if following the symlink is allowed, -ve on error.
670 */
671static inline int may_follow_link(struct path *link, struct nameidata *nd)
672{
673 const struct inode *inode;
674 const struct inode *parent;
675
676 if (!sysctl_protected_symlinks)
677 return 0;
678
679 /* Allowed if owner and follower match. */
680 inode = link->dentry->d_inode;
681 if (current_cred()->fsuid == inode->i_uid)
682 return 0;
683
684 /* Allowed if parent directory not sticky and world-writable. */
685 parent = nd->path.dentry->d_inode;
686 if ((parent->i_mode & (S_ISVTX|S_IWOTH)) != (S_ISVTX|S_IWOTH))
687 return 0;
688
689 /* Allowed if parent directory and link owner match. */
690 if (parent->i_uid == inode->i_uid)
691 return 0;
692
693 path_put_conditional(link, nd);
694 path_put(&nd->path);
695 return -EACCES;
696}
697
698/**
699 * safe_hardlink_source - Check for safe hardlink conditions
700 * @inode: the source inode to hardlink from
701 *
702 * Return false if at least one of the following conditions:
703 * - inode is not a regular file
704 * - inode is setuid
705 * - inode is setgid and group-exec
706 * - access failure for read and write
707 *
708 * Otherwise returns true.
709 */
710static bool safe_hardlink_source(struct inode *inode)
711{
712 umode_t mode = inode->i_mode;
713
714 /* Special files should not get pinned to the filesystem. */
715 if (!S_ISREG(mode))
716 return false;
717
718 /* Setuid files should not get pinned to the filesystem. */
719 if (mode & S_ISUID)
720 return false;
721
722 /* Executable setgid files should not get pinned to the filesystem. */
723 if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP))
724 return false;
725
726 /* Hardlinking to unreadable or unwritable sources is dangerous. */
727 if (inode_permission(inode, MAY_READ | MAY_WRITE))
728 return false;
729
730 return true;
731}
732
733/**
734 * may_linkat - Check permissions for creating a hardlink
735 * @link: the source to hardlink from
736 *
737 * Block hardlink when all of:
738 * - sysctl_protected_hardlinks enabled
739 * - fsuid does not match inode
740 * - hardlink source is unsafe (see safe_hardlink_source() above)
741 * - not CAP_FOWNER
742 *
743 * Returns 0 if successful, -ve on error.
744 */
745static int may_linkat(struct path *link)
746{
747 const struct cred *cred;
748 struct inode *inode;
749
750 if (!sysctl_protected_hardlinks)
751 return 0;
752
753 cred = current_cred();
754 inode = link->dentry->d_inode;
755
756 /* Source inode owner (or CAP_FOWNER) can hardlink all they like,
757 * otherwise, it must be a safe source.
758 */
759 if (cred->fsuid == inode->i_uid || safe_hardlink_source(inode) ||
760 capable(CAP_FOWNER))
761 return 0;
762
763 return -EPERM;
764}
765
653static __always_inline int 766static __always_inline int
654follow_link(struct path *link, struct nameidata *nd, void **p) 767follow_link(struct path *link, struct nameidata *nd, void **p)
655{ 768{
@@ -1818,6 +1931,9 @@ static int path_lookupat(int dfd, const char *name,
1818 while (err > 0) { 1931 while (err > 0) {
1819 void *cookie; 1932 void *cookie;
1820 struct path link = path; 1933 struct path link = path;
1934 err = may_follow_link(&link, nd);
1935 if (unlikely(err))
1936 break;
1821 nd->flags |= LOOKUP_PARENT; 1937 nd->flags |= LOOKUP_PARENT;
1822 err = follow_link(&link, nd, &cookie); 1938 err = follow_link(&link, nd, &cookie);
1823 if (err) 1939 if (err)
@@ -2778,6 +2894,9 @@ static struct file *path_openat(int dfd, const char *pathname,
2778 error = -ELOOP; 2894 error = -ELOOP;
2779 break; 2895 break;
2780 } 2896 }
2897 error = may_follow_link(&link, nd);
2898 if (unlikely(error))
2899 break;
2781 nd->flags |= LOOKUP_PARENT; 2900 nd->flags |= LOOKUP_PARENT;
2782 nd->flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL); 2901 nd->flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL);
2783 error = follow_link(&link, nd, &cookie); 2902 error = follow_link(&link, nd, &cookie);
@@ -3421,6 +3540,9 @@ SYSCALL_DEFINE5(linkat, int, olddfd, const char __user *, oldname,
3421 error = -EXDEV; 3540 error = -EXDEV;
3422 if (old_path.mnt != new_path.mnt) 3541 if (old_path.mnt != new_path.mnt)
3423 goto out_dput; 3542 goto out_dput;
3543 error = may_linkat(&old_path);
3544 if (unlikely(error))
3545 goto out_dput;
3424 error = security_path_link(old_path.dentry, &new_path, new_dentry); 3546 error = security_path_link(old_path.dentry, &new_path, new_dentry);
3425 if (error) 3547 if (error)
3426 goto out_dput; 3548 goto out_dput;