@@ -617,6 +617,29 @@ static inline void vma_complete(struct vma_prepare *vp,
617617 uprobe_mmap (vp -> insert );
618618}
619619
620+ /*
621+ * dup_anon_vma() - Helper function to duplicate anon_vma
622+ * @dst: The destination VMA
623+ * @src: The source VMA
624+ *
625+ * Returns: 0 on success.
626+ */
627+ static inline int dup_anon_vma (struct vm_area_struct * dst ,
628+ struct vm_area_struct * src )
629+ {
630+ /*
631+ * Easily overlooked: when mprotect shifts the boundary, make sure the
632+ * expanding vma has anon_vma set if the shrinking vma had, to cover any
633+ * anon pages imported.
634+ */
635+ if (src -> anon_vma && !dst -> anon_vma ) {
636+ dst -> anon_vma = src -> anon_vma ;
637+ return anon_vma_clone (dst , src );
638+ }
639+
640+ return 0 ;
641+ }
642+
620643/*
621644 * vma_expand - Expand an existing VMA
622645 *
@@ -642,15 +665,12 @@ int vma_expand(struct vma_iterator *vmi, struct vm_area_struct *vma,
642665 struct vma_prepare vp ;
643666
644667 if (next && (vma != next ) && (end == next -> vm_end )) {
645- remove_next = true;
646- if (next -> anon_vma && !vma -> anon_vma ) {
647- int error ;
668+ int ret ;
648669
649- vma -> anon_vma = next -> anon_vma ;
650- error = anon_vma_clone (vma , next );
651- if (error )
652- return error ;
653- }
670+ remove_next = true;
671+ ret = dup_anon_vma (vma , next );
672+ if (ret )
673+ return ret ;
654674 }
655675
656676 init_multi_vma_prep (& vp , vma , NULL , remove_next ? next : NULL , NULL );
@@ -739,10 +759,11 @@ int __vma_adjust(struct vma_iterator *vmi, struct vm_area_struct *vma,
739759 struct file * file = vma -> vm_file ;
740760 bool vma_changed = false;
741761 long adjust_next = 0 ;
742- struct vm_area_struct * exporter = NULL , * importer = NULL ;
743762 struct vma_prepare vma_prep ;
744763
745764 if (next ) {
765+ int error = 0 ;
766+
746767 if (end >= next -> vm_end ) {
747768 /*
748769 * vma expands, overlapping all the next, and
@@ -777,50 +798,35 @@ int __vma_adjust(struct vma_iterator *vmi, struct vm_area_struct *vma,
777798 end != remove2 -> vm_end );
778799 }
779800
780- exporter = next ;
781- importer = vma ;
782-
783801 /*
784802 * If next doesn't have anon_vma, import from vma after
785803 * next, if the vma overlaps with it.
786804 */
787- if (remove2 != NULL && !next -> anon_vma )
788- exporter = remove2 ;
805+ if (remove != NULL && !next -> anon_vma )
806+ error = dup_anon_vma (vma , remove2 );
807+ else
808+ error = dup_anon_vma (vma , remove );
789809
790810 } else if (end > next -> vm_start ) {
791811 /*
792812 * vma expands, overlapping part of the next:
793813 * mprotect case 5 shifting the boundary up.
794814 */
795815 adjust_next = (end - next -> vm_start );
796- exporter = next ;
797- importer = vma ;
798- VM_WARN_ON (expand != importer );
816+ VM_WARN_ON (expand != vma );
817+ error = dup_anon_vma (vma , next );
799818 } else if (end < vma -> vm_end ) {
800819 /*
801820 * vma shrinks, and !insert tells it's not
802821 * split_vma inserting another: so it must be
803822 * mprotect case 4 shifting the boundary down.
804823 */
805824 adjust_next = - (vma -> vm_end - end );
806- exporter = vma ;
807- importer = next ;
808- VM_WARN_ON (expand != importer );
809- }
810-
811- /*
812- * Easily overlooked: when mprotect shifts the boundary,
813- * make sure the expanding vma has anon_vma set if the
814- * shrinking vma had, to cover any anon pages imported.
815- */
816- if (exporter && exporter -> anon_vma && !importer -> anon_vma ) {
817- int error ;
818-
819- importer -> anon_vma = exporter -> anon_vma ;
820- error = anon_vma_clone (importer , exporter );
821- if (error )
822- return error ;
825+ VM_WARN_ON (expand != next );
826+ error = dup_anon_vma (next , vma );
823827 }
828+ if (error )
829+ return error ;
824830 }
825831
826832 if (vma_iter_prealloc (vmi ))
0 commit comments