1515#include <linux/posix_acl.h>
1616#include <linux/posix_acl_xattr.h>
1717#include <linux/atomic.h>
18+ #include <linux/ratelimit.h>
1819#include "overlayfs.h"
1920
2021void ovl_cleanup (struct inode * wdir , struct dentry * wdentry )
@@ -757,6 +758,104 @@ static bool ovl_type_merge_or_lower(struct dentry *dentry)
757758 return OVL_TYPE_MERGE (type ) || !OVL_TYPE_UPPER (type );
758759}
759760
761+ static bool ovl_can_move (struct dentry * dentry )
762+ {
763+ return ovl_redirect_dir (dentry -> d_sb ) ||
764+ !d_is_dir (dentry ) || !ovl_type_merge_or_lower (dentry );
765+ }
766+
767+ #define OVL_REDIRECT_MAX 256
768+
769+ static char * ovl_get_redirect (struct dentry * dentry , bool samedir )
770+ {
771+ char * buf , * ret ;
772+ struct dentry * d , * tmp ;
773+ int buflen = OVL_REDIRECT_MAX + 1 ;
774+
775+ if (samedir ) {
776+ ret = kstrndup (dentry -> d_name .name , dentry -> d_name .len ,
777+ GFP_KERNEL );
778+ goto out ;
779+ }
780+
781+ buf = ret = kmalloc (buflen , GFP_TEMPORARY );
782+ if (!buf )
783+ goto out ;
784+
785+ buflen -- ;
786+ buf [buflen ] = '\0' ;
787+ for (d = dget (dentry ); !IS_ROOT (d );) {
788+ const char * name ;
789+ int thislen ;
790+
791+ spin_lock (& d -> d_lock );
792+ name = ovl_dentry_get_redirect (d );
793+ if (name ) {
794+ thislen = strlen (name );
795+ } else {
796+ name = d -> d_name .name ;
797+ thislen = d -> d_name .len ;
798+ }
799+
800+ /* If path is too long, fall back to userspace move */
801+ if (thislen + (name [0 ] != '/' ) > buflen ) {
802+ ret = ERR_PTR (- EXDEV );
803+ spin_unlock (& d -> d_lock );
804+ goto out_put ;
805+ }
806+
807+ buflen -= thislen ;
808+ memcpy (& buf [buflen ], name , thislen );
809+ tmp = dget_dlock (d -> d_parent );
810+ spin_unlock (& d -> d_lock );
811+
812+ dput (d );
813+ d = tmp ;
814+
815+ /* Absolute redirect: finished */
816+ if (buf [buflen ] == '/' )
817+ break ;
818+ buflen -- ;
819+ buf [buflen ] = '/' ;
820+ }
821+ ret = kstrdup (& buf [buflen ], GFP_KERNEL );
822+ out_put :
823+ dput (d );
824+ kfree (buf );
825+ out :
826+ return ret ? ret : ERR_PTR (- ENOMEM );
827+ }
828+
829+ static int ovl_set_redirect (struct dentry * dentry , bool samedir )
830+ {
831+ int err ;
832+ const char * redirect = ovl_dentry_get_redirect (dentry );
833+
834+ if (redirect && (samedir || redirect [0 ] == '/' ))
835+ return 0 ;
836+
837+ redirect = ovl_get_redirect (dentry , samedir );
838+ if (IS_ERR (redirect ))
839+ return PTR_ERR (redirect );
840+
841+ err = ovl_do_setxattr (ovl_dentry_upper (dentry ), OVL_XATTR_REDIRECT ,
842+ redirect , strlen (redirect ), 0 );
843+ if (!err ) {
844+ spin_lock (& dentry -> d_lock );
845+ ovl_dentry_set_redirect (dentry , redirect );
846+ spin_unlock (& dentry -> d_lock );
847+ } else {
848+ kfree (redirect );
849+ if (err == - EOPNOTSUPP )
850+ ovl_clear_redirect_dir (dentry -> d_sb );
851+ else
852+ pr_warn_ratelimited ("overlay: failed to set redirect (%i)\n" , err );
853+ /* Fall back to userspace copy-up */
854+ err = - EXDEV ;
855+ }
856+ return err ;
857+ }
858+
760859static int ovl_rename (struct inode * olddir , struct dentry * old ,
761860 struct inode * newdir , struct dentry * new ,
762861 unsigned int flags )
@@ -773,6 +872,7 @@ static int ovl_rename(struct inode *olddir, struct dentry *old,
773872 bool overwrite = !(flags & RENAME_EXCHANGE );
774873 bool is_dir = d_is_dir (old );
775874 bool new_is_dir = d_is_dir (new );
875+ bool samedir = olddir == newdir ;
776876 struct dentry * opaquedir = NULL ;
777877 const struct cred * old_cred = NULL ;
778878
@@ -784,9 +884,9 @@ static int ovl_rename(struct inode *olddir, struct dentry *old,
784884
785885 /* Don't copy up directory trees */
786886 err = - EXDEV ;
787- if (is_dir && ovl_type_merge_or_lower (old ))
887+ if (! ovl_can_move (old ))
788888 goto out ;
789- if (!overwrite && new_is_dir && ovl_type_merge_or_lower (new ))
889+ if (!overwrite && ! ovl_can_move (new ))
790890 goto out ;
791891
792892 err = ovl_want_write (old );
@@ -837,7 +937,6 @@ static int ovl_rename(struct inode *olddir, struct dentry *old,
837937
838938 trap = lock_rename (new_upperdir , old_upperdir );
839939
840-
841940 olddentry = lookup_one_len (old -> d_name .name , old_upperdir ,
842941 old -> d_name .len );
843942 err = PTR_ERR (olddentry );
@@ -880,18 +979,29 @@ static int ovl_rename(struct inode *olddir, struct dentry *old,
880979 if (WARN_ON (olddentry -> d_inode == newdentry -> d_inode ))
881980 goto out_dput ;
882981
883- if (is_dir && !old_opaque && ovl_lower_positive (new )) {
884- err = ovl_set_opaque (olddentry );
885- if (err )
886- goto out_dput ;
887- ovl_dentry_set_opaque (old , true);
982+ if (is_dir ) {
983+ if (ovl_type_merge_or_lower (old )) {
984+ err = ovl_set_redirect (old , samedir );
985+ if (err )
986+ goto out_dput ;
987+ } else if (!old_opaque && ovl_lower_positive (new )) {
988+ err = ovl_set_opaque (olddentry );
989+ if (err )
990+ goto out_dput ;
991+ ovl_dentry_set_opaque (old , true);
992+ }
888993 }
889- if (!overwrite &&
890- new_is_dir && !new_opaque && ovl_lower_positive (old )) {
891- err = ovl_set_opaque (newdentry );
892- if (err )
893- goto out_dput ;
894- ovl_dentry_set_opaque (new , true);
994+ if (!overwrite && new_is_dir ) {
995+ if (ovl_type_merge_or_lower (new )) {
996+ err = ovl_set_redirect (new , samedir );
997+ if (err )
998+ goto out_dput ;
999+ } else if (!new_opaque && ovl_lower_positive (old )) {
1000+ err = ovl_set_opaque (newdentry );
1001+ if (err )
1002+ goto out_dput ;
1003+ ovl_dentry_set_opaque (new , true);
1004+ }
8951005 }
8961006
8971007 err = ovl_do_rename (old_upperdir -> d_inode , olddentry ,
0 commit comments