Skip to content

Commit cb08563

Browse files
committed
Merge tag 'mm-hotfixes-stable-2023-04-19-16-36' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm
Pull misc fixes from Andrew Morton: "22 hotfixes. 19 are cc:stable and the remainder address issues which were introduced during this merge cycle, or aren't considered suitable for -stable backporting. 19 are for MM and the remainder are for other subsystems" * tag 'mm-hotfixes-stable-2023-04-19-16-36' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm: (22 commits) nilfs2: initialize unused bytes in segment summary blocks mm: page_alloc: skip regions with hugetlbfs pages when allocating 1G pages mm/mmap: regression fix for unmapped_area{_topdown} maple_tree: fix mas_empty_area() search maple_tree: make maple state reusable after mas_empty_area_rev() mm: kmsan: handle alloc failures in kmsan_ioremap_page_range() mm: kmsan: handle alloc failures in kmsan_vmap_pages_range_noflush() tools/Makefile: do missed s/vm/mm/ mm: fix memory leak on mm_init error handling mm/page_alloc: fix potential deadlock on zonelist_update_seq seqlock kernel/sys.c: fix and improve control flow in __sys_setres[ug]id() Revert "userfaultfd: don't fail on unrecognized features" writeback, cgroup: fix null-ptr-deref write in bdi_split_work_to_wbs maple_tree: fix a potential memory leak, OOB access, or other unpredictable bug tools/mm/page_owner_sort.c: fix TGID output when cull=tg is used mailmap: update jtoppins' entry to reference correct email mm/mempolicy: fix use-after-free of VMA iterator mm/huge_memory.c: warn with pr_warn_ratelimited instead of VM_WARN_ON_ONCE_FOLIO mm/mprotect: fix do_mprotect_pkey() return on error mm/khugepaged: check again on anon uffd-wp during isolation ...
2 parents 23990b1 + ef83274 commit cb08563

File tree

21 files changed

+351
-187
lines changed

21 files changed

+351
-187
lines changed

.mailmap

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,8 @@ Johan Hovold <[email protected]> <[email protected]>
232232
233233
John Paul Adrian Glaubitz <[email protected]>
234234
John Stultz <[email protected]>
235+
236+
235237
236238
237239

fs/fs-writeback.c

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -978,6 +978,16 @@ static void bdi_split_work_to_wbs(struct backing_dev_info *bdi,
978978
continue;
979979
}
980980

981+
/*
982+
* If wb_tryget fails, the wb has been shutdown, skip it.
983+
*
984+
* Pin @wb so that it stays on @bdi->wb_list. This allows
985+
* continuing iteration from @wb after dropping and
986+
* regrabbing rcu read lock.
987+
*/
988+
if (!wb_tryget(wb))
989+
continue;
990+
981991
/* alloc failed, execute synchronously using on-stack fallback */
982992
work = &fallback_work;
983993
*work = *base_work;
@@ -986,13 +996,6 @@ static void bdi_split_work_to_wbs(struct backing_dev_info *bdi,
986996
work->done = &fallback_work_done;
987997

988998
wb_queue_work(wb, work);
989-
990-
/*
991-
* Pin @wb so that it stays on @bdi->wb_list. This allows
992-
* continuing iteration from @wb after dropping and
993-
* regrabbing rcu read lock.
994-
*/
995-
wb_get(wb);
996999
last_wb = wb;
9971000

9981001
rcu_read_unlock();

fs/nilfs2/segment.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,23 @@ static int nilfs_segctor_reset_segment_buffer(struct nilfs_sc_info *sci)
430430
return 0;
431431
}
432432

433+
/**
434+
* nilfs_segctor_zeropad_segsum - zero pad the rest of the segment summary area
435+
* @sci: segment constructor object
436+
*
437+
* nilfs_segctor_zeropad_segsum() zero-fills unallocated space at the end of
438+
* the current segment summary block.
439+
*/
440+
static void nilfs_segctor_zeropad_segsum(struct nilfs_sc_info *sci)
441+
{
442+
struct nilfs_segsum_pointer *ssp;
443+
444+
ssp = sci->sc_blk_cnt > 0 ? &sci->sc_binfo_ptr : &sci->sc_finfo_ptr;
445+
if (ssp->offset < ssp->bh->b_size)
446+
memset(ssp->bh->b_data + ssp->offset, 0,
447+
ssp->bh->b_size - ssp->offset);
448+
}
449+
433450
static int nilfs_segctor_feed_segment(struct nilfs_sc_info *sci)
434451
{
435452
sci->sc_nblk_this_inc += sci->sc_curseg->sb_sum.nblocks;
@@ -438,6 +455,7 @@ static int nilfs_segctor_feed_segment(struct nilfs_sc_info *sci)
438455
* The current segment is filled up
439456
* (internal code)
440457
*/
458+
nilfs_segctor_zeropad_segsum(sci);
441459
sci->sc_curseg = NILFS_NEXT_SEGBUF(sci->sc_curseg);
442460
return nilfs_segctor_reset_segment_buffer(sci);
443461
}
@@ -542,6 +560,7 @@ static int nilfs_segctor_add_file_block(struct nilfs_sc_info *sci,
542560
goto retry;
543561
}
544562
if (unlikely(required)) {
563+
nilfs_segctor_zeropad_segsum(sci);
545564
err = nilfs_segbuf_extend_segsum(segbuf);
546565
if (unlikely(err))
547566
goto failed;
@@ -1533,6 +1552,7 @@ static int nilfs_segctor_collect(struct nilfs_sc_info *sci,
15331552
nadd = min_t(int, nadd << 1, SC_MAX_SEGDELTA);
15341553
sci->sc_stage = prev_stage;
15351554
}
1555+
nilfs_segctor_zeropad_segsum(sci);
15361556
nilfs_segctor_truncate_segments(sci, sci->sc_curseg, nilfs->ns_sufile);
15371557
return 0;
15381558

fs/userfaultfd.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1955,8 +1955,10 @@ static int userfaultfd_api(struct userfaultfd_ctx *ctx,
19551955
ret = -EFAULT;
19561956
if (copy_from_user(&uffdio_api, buf, sizeof(uffdio_api)))
19571957
goto out;
1958-
/* Ignore unsupported features (userspace built against newer kernel) */
1959-
features = uffdio_api.features & UFFD_API_FEATURES;
1958+
features = uffdio_api.features;
1959+
ret = -EINVAL;
1960+
if (uffdio_api.api != UFFD_API || (features & ~UFFD_API_FEATURES))
1961+
goto err_out;
19601962
ret = -EPERM;
19611963
if ((features & UFFD_FEATURE_EVENT_FORK) && !capable(CAP_SYS_PTRACE))
19621964
goto err_out;

include/linux/kmsan.h

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -134,11 +134,12 @@ void kmsan_kfree_large(const void *ptr);
134134
* @page_shift: page_shift passed to vmap_range_noflush().
135135
*
136136
* KMSAN maps shadow and origin pages of @pages into contiguous ranges in
137-
* vmalloc metadata address range.
137+
* vmalloc metadata address range. Returns 0 on success, callers must check
138+
* for non-zero return value.
138139
*/
139-
void kmsan_vmap_pages_range_noflush(unsigned long start, unsigned long end,
140-
pgprot_t prot, struct page **pages,
141-
unsigned int page_shift);
140+
int kmsan_vmap_pages_range_noflush(unsigned long start, unsigned long end,
141+
pgprot_t prot, struct page **pages,
142+
unsigned int page_shift);
142143

143144
/**
144145
* kmsan_vunmap_kernel_range_noflush() - Notify KMSAN about a vunmap.
@@ -159,11 +160,12 @@ void kmsan_vunmap_range_noflush(unsigned long start, unsigned long end);
159160
* @page_shift: page_shift argument passed to vmap_range_noflush().
160161
*
161162
* KMSAN creates new metadata pages for the physical pages mapped into the
162-
* virtual memory.
163+
* virtual memory. Returns 0 on success, callers must check for non-zero return
164+
* value.
163165
*/
164-
void kmsan_ioremap_page_range(unsigned long addr, unsigned long end,
165-
phys_addr_t phys_addr, pgprot_t prot,
166-
unsigned int page_shift);
166+
int kmsan_ioremap_page_range(unsigned long addr, unsigned long end,
167+
phys_addr_t phys_addr, pgprot_t prot,
168+
unsigned int page_shift);
167169

168170
/**
169171
* kmsan_iounmap_page_range() - Notify KMSAN about a iounmap_page_range() call.
@@ -281,25 +283,26 @@ static inline void kmsan_kfree_large(const void *ptr)
281283
{
282284
}
283285

284-
static inline void kmsan_vmap_pages_range_noflush(unsigned long start,
285-
unsigned long end,
286-
pgprot_t prot,
287-
struct page **pages,
288-
unsigned int page_shift)
286+
static inline int kmsan_vmap_pages_range_noflush(unsigned long start,
287+
unsigned long end,
288+
pgprot_t prot,
289+
struct page **pages,
290+
unsigned int page_shift)
289291
{
292+
return 0;
290293
}
291294

292295
static inline void kmsan_vunmap_range_noflush(unsigned long start,
293296
unsigned long end)
294297
{
295298
}
296299

297-
static inline void kmsan_ioremap_page_range(unsigned long start,
298-
unsigned long end,
299-
phys_addr_t phys_addr,
300-
pgprot_t prot,
301-
unsigned int page_shift)
300+
static inline int kmsan_ioremap_page_range(unsigned long start,
301+
unsigned long end,
302+
phys_addr_t phys_addr, pgprot_t prot,
303+
unsigned int page_shift)
302304
{
305+
return 0;
303306
}
304307

305308
static inline void kmsan_iounmap_page_range(unsigned long start,

kernel/fork.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1174,6 +1174,7 @@ static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p,
11741174
fail_pcpu:
11751175
while (i > 0)
11761176
percpu_counter_destroy(&mm->rss_stat[--i]);
1177+
destroy_context(mm);
11771178
fail_nocontext:
11781179
mm_free_pgd(mm);
11791180
fail_nopgd:

kernel/sys.c

Lines changed: 40 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -664,6 +664,7 @@ long __sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)
664664
struct cred *new;
665665
int retval;
666666
kuid_t kruid, keuid, ksuid;
667+
bool ruid_new, euid_new, suid_new;
667668

668669
kruid = make_kuid(ns, ruid);
669670
keuid = make_kuid(ns, euid);
@@ -678,25 +679,29 @@ long __sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)
678679
if ((suid != (uid_t) -1) && !uid_valid(ksuid))
679680
return -EINVAL;
680681

682+
old = current_cred();
683+
684+
/* check for no-op */
685+
if ((ruid == (uid_t) -1 || uid_eq(kruid, old->uid)) &&
686+
(euid == (uid_t) -1 || (uid_eq(keuid, old->euid) &&
687+
uid_eq(keuid, old->fsuid))) &&
688+
(suid == (uid_t) -1 || uid_eq(ksuid, old->suid)))
689+
return 0;
690+
691+
ruid_new = ruid != (uid_t) -1 && !uid_eq(kruid, old->uid) &&
692+
!uid_eq(kruid, old->euid) && !uid_eq(kruid, old->suid);
693+
euid_new = euid != (uid_t) -1 && !uid_eq(keuid, old->uid) &&
694+
!uid_eq(keuid, old->euid) && !uid_eq(keuid, old->suid);
695+
suid_new = suid != (uid_t) -1 && !uid_eq(ksuid, old->uid) &&
696+
!uid_eq(ksuid, old->euid) && !uid_eq(ksuid, old->suid);
697+
if ((ruid_new || euid_new || suid_new) &&
698+
!ns_capable_setid(old->user_ns, CAP_SETUID))
699+
return -EPERM;
700+
681701
new = prepare_creds();
682702
if (!new)
683703
return -ENOMEM;
684704

685-
old = current_cred();
686-
687-
retval = -EPERM;
688-
if (!ns_capable_setid(old->user_ns, CAP_SETUID)) {
689-
if (ruid != (uid_t) -1 && !uid_eq(kruid, old->uid) &&
690-
!uid_eq(kruid, old->euid) && !uid_eq(kruid, old->suid))
691-
goto error;
692-
if (euid != (uid_t) -1 && !uid_eq(keuid, old->uid) &&
693-
!uid_eq(keuid, old->euid) && !uid_eq(keuid, old->suid))
694-
goto error;
695-
if (suid != (uid_t) -1 && !uid_eq(ksuid, old->uid) &&
696-
!uid_eq(ksuid, old->euid) && !uid_eq(ksuid, old->suid))
697-
goto error;
698-
}
699-
700705
if (ruid != (uid_t) -1) {
701706
new->uid = kruid;
702707
if (!uid_eq(kruid, old->uid)) {
@@ -761,6 +766,7 @@ long __sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
761766
struct cred *new;
762767
int retval;
763768
kgid_t krgid, kegid, ksgid;
769+
bool rgid_new, egid_new, sgid_new;
764770

765771
krgid = make_kgid(ns, rgid);
766772
kegid = make_kgid(ns, egid);
@@ -773,23 +779,28 @@ long __sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
773779
if ((sgid != (gid_t) -1) && !gid_valid(ksgid))
774780
return -EINVAL;
775781

782+
old = current_cred();
783+
784+
/* check for no-op */
785+
if ((rgid == (gid_t) -1 || gid_eq(krgid, old->gid)) &&
786+
(egid == (gid_t) -1 || (gid_eq(kegid, old->egid) &&
787+
gid_eq(kegid, old->fsgid))) &&
788+
(sgid == (gid_t) -1 || gid_eq(ksgid, old->sgid)))
789+
return 0;
790+
791+
rgid_new = rgid != (gid_t) -1 && !gid_eq(krgid, old->gid) &&
792+
!gid_eq(krgid, old->egid) && !gid_eq(krgid, old->sgid);
793+
egid_new = egid != (gid_t) -1 && !gid_eq(kegid, old->gid) &&
794+
!gid_eq(kegid, old->egid) && !gid_eq(kegid, old->sgid);
795+
sgid_new = sgid != (gid_t) -1 && !gid_eq(ksgid, old->gid) &&
796+
!gid_eq(ksgid, old->egid) && !gid_eq(ksgid, old->sgid);
797+
if ((rgid_new || egid_new || sgid_new) &&
798+
!ns_capable_setid(old->user_ns, CAP_SETGID))
799+
return -EPERM;
800+
776801
new = prepare_creds();
777802
if (!new)
778803
return -ENOMEM;
779-
old = current_cred();
780-
781-
retval = -EPERM;
782-
if (!ns_capable_setid(old->user_ns, CAP_SETGID)) {
783-
if (rgid != (gid_t) -1 && !gid_eq(krgid, old->gid) &&
784-
!gid_eq(krgid, old->egid) && !gid_eq(krgid, old->sgid))
785-
goto error;
786-
if (egid != (gid_t) -1 && !gid_eq(kegid, old->gid) &&
787-
!gid_eq(kegid, old->egid) && !gid_eq(kegid, old->sgid))
788-
goto error;
789-
if (sgid != (gid_t) -1 && !gid_eq(ksgid, old->gid) &&
790-
!gid_eq(ksgid, old->egid) && !gid_eq(ksgid, old->sgid))
791-
goto error;
792-
}
793804

794805
if (rgid != (gid_t) -1)
795806
new->gid = krgid;

0 commit comments

Comments
 (0)