Skip to content

Commit d9abdee

Browse files
committed
Merge branch 'akpm' (patches from Andrew)
Merge misc fixes from Andrew Morton: "19 patches. Subsystems affected by this patch series: mm (userfaultfd, migration, memblock, mempolicy, slub, secretmem, and thp), ocfs2, binfmt, vfs, and misc" * emailed patches from Andrew Morton <akpm@linux-foundation.org>: mailmap: add Andrej Shadura mm/thp: decrease nr_thps in file's mapping on THP split mm/secretmem: fix NULL page->mapping dereference in page_is_secretmem() vfs: check fd has read access in kernel_read_file_from_fd() elfcore: correct reference to CONFIG_UML mm, slub: fix incorrect memcg slab count for bulk free mm, slub: fix potential use-after-free in slab_debugfs_fops mm, slub: fix potential memoryleak in kmem_cache_open() mm, slub: fix mismatch between reconstructed freelist depth and cnt mm, slub: fix two bugs in slab_debug_trace_open() mm/mempolicy: do not allow illegal MPOL_F_NUMA_BALANCING | MPOL_LOCAL in mbind() memblock: check memory total_size ocfs2: mount fails with buffer overflow in strlen ocfs2: fix data corruption after conversion from inline format mm/migrate: fix CPUHP state to update node demotion order mm/migrate: add CPU hotplug to demotion #ifdef mm/migrate: optimize hotplug-time demotion order updates userfaultfd: fix a race between writeprotect and exit_mmap() mm/userfaultfd: selftests: fix memory corruption with thp enabled
2 parents 519d819 + 362d5df commit d9abdee

17 files changed

Lines changed: 138 additions & 99 deletions

File tree

.mailmap

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ Al Viro <viro@zenIV.linux.org.uk>
3333
Andi Kleen <ak@linux.intel.com> <ak@suse.de>
3434
Andi Shyti <andi@etezian.org> <andi.shyti@samsung.com>
3535
Andreas Herrmann <aherrman@de.ibm.com>
36+
Andrej Shadura <andrew.shadura@collabora.co.uk>
37+
Andrej Shadura <andrew@shadura.me> <andrew@beldisplaytech.com>
3638
Andrew Morton <akpm@linux-foundation.org>
3739
Andrew Murray <amurray@thegoodpenguin.co.uk> <amurray@embedded-bits.co.uk>
3840
Andrew Murray <amurray@thegoodpenguin.co.uk> <andrew.murray@arm.com>

fs/kernel_read_file.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ int kernel_read_file_from_fd(int fd, loff_t offset, void **buf,
178178
struct fd f = fdget(fd);
179179
int ret = -EBADF;
180180

181-
if (!f.file)
181+
if (!f.file || !(f.file->f_mode & FMODE_READ))
182182
goto out;
183183

184184
ret = kernel_read_file(f.file, offset, buf, buf_size, file_size, id);

fs/ocfs2/alloc.c

Lines changed: 12 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -7045,7 +7045,7 @@ void ocfs2_set_inode_data_inline(struct inode *inode, struct ocfs2_dinode *di)
70457045
int ocfs2_convert_inline_data_to_extents(struct inode *inode,
70467046
struct buffer_head *di_bh)
70477047
{
7048-
int ret, i, has_data, num_pages = 0;
7048+
int ret, has_data, num_pages = 0;
70497049
int need_free = 0;
70507050
u32 bit_off, num;
70517051
handle_t *handle;
@@ -7054,26 +7054,17 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode,
70547054
struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
70557055
struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
70567056
struct ocfs2_alloc_context *data_ac = NULL;
7057-
struct page **pages = NULL;
7058-
loff_t end = osb->s_clustersize;
7057+
struct page *page = NULL;
70597058
struct ocfs2_extent_tree et;
70607059
int did_quota = 0;
70617060

70627061
has_data = i_size_read(inode) ? 1 : 0;
70637062

70647063
if (has_data) {
7065-
pages = kcalloc(ocfs2_pages_per_cluster(osb->sb),
7066-
sizeof(struct page *), GFP_NOFS);
7067-
if (pages == NULL) {
7068-
ret = -ENOMEM;
7069-
mlog_errno(ret);
7070-
return ret;
7071-
}
7072-
70737064
ret = ocfs2_reserve_clusters(osb, 1, &data_ac);
70747065
if (ret) {
70757066
mlog_errno(ret);
7076-
goto free_pages;
7067+
goto out;
70777068
}
70787069
}
70797070

@@ -7093,7 +7084,8 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode,
70937084
}
70947085

70957086
if (has_data) {
7096-
unsigned int page_end;
7087+
unsigned int page_end = min_t(unsigned, PAGE_SIZE,
7088+
osb->s_clustersize);
70977089
u64 phys;
70987090

70997091
ret = dquot_alloc_space_nodirty(inode,
@@ -7117,15 +7109,8 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode,
71177109
*/
71187110
block = phys = ocfs2_clusters_to_blocks(inode->i_sb, bit_off);
71197111

7120-
/*
7121-
* Non sparse file systems zero on extend, so no need
7122-
* to do that now.
7123-
*/
7124-
if (!ocfs2_sparse_alloc(osb) &&
7125-
PAGE_SIZE < osb->s_clustersize)
7126-
end = PAGE_SIZE;
7127-
7128-
ret = ocfs2_grab_eof_pages(inode, 0, end, pages, &num_pages);
7112+
ret = ocfs2_grab_eof_pages(inode, 0, page_end, &page,
7113+
&num_pages);
71297114
if (ret) {
71307115
mlog_errno(ret);
71317116
need_free = 1;
@@ -7136,20 +7121,15 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode,
71367121
* This should populate the 1st page for us and mark
71377122
* it up to date.
71387123
*/
7139-
ret = ocfs2_read_inline_data(inode, pages[0], di_bh);
7124+
ret = ocfs2_read_inline_data(inode, page, di_bh);
71407125
if (ret) {
71417126
mlog_errno(ret);
71427127
need_free = 1;
71437128
goto out_unlock;
71447129
}
71457130

7146-
page_end = PAGE_SIZE;
7147-
if (PAGE_SIZE > osb->s_clustersize)
7148-
page_end = osb->s_clustersize;
7149-
7150-
for (i = 0; i < num_pages; i++)
7151-
ocfs2_map_and_dirty_page(inode, handle, 0, page_end,
7152-
pages[i], i > 0, &phys);
7131+
ocfs2_map_and_dirty_page(inode, handle, 0, page_end, page, 0,
7132+
&phys);
71537133
}
71547134

71557135
spin_lock(&oi->ip_lock);
@@ -7180,8 +7160,8 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode,
71807160
}
71817161

71827162
out_unlock:
7183-
if (pages)
7184-
ocfs2_unlock_and_free_pages(pages, num_pages);
7163+
if (page)
7164+
ocfs2_unlock_and_free_pages(&page, num_pages);
71857165

71867166
out_commit:
71877167
if (ret < 0 && did_quota)
@@ -7205,8 +7185,6 @@ int ocfs2_convert_inline_data_to_extents(struct inode *inode,
72057185
out:
72067186
if (data_ac)
72077187
ocfs2_free_alloc_context(data_ac);
7208-
free_pages:
7209-
kfree(pages);
72107188
return ret;
72117189
}
72127190

fs/ocfs2/super.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2167,11 +2167,17 @@ static int ocfs2_initialize_super(struct super_block *sb,
21672167
}
21682168

21692169
if (ocfs2_clusterinfo_valid(osb)) {
2170+
/*
2171+
* ci_stack and ci_cluster in ocfs2_cluster_info may not be null
2172+
* terminated, so make sure no overflow happens here by using
2173+
* memcpy. Destination strings will always be null terminated
2174+
* because osb is allocated using kzalloc.
2175+
*/
21702176
osb->osb_stackflags =
21712177
OCFS2_RAW_SB(di)->s_cluster_info.ci_stackflags;
2172-
strlcpy(osb->osb_cluster_stack,
2178+
memcpy(osb->osb_cluster_stack,
21732179
OCFS2_RAW_SB(di)->s_cluster_info.ci_stack,
2174-
OCFS2_STACK_LABEL_LEN + 1);
2180+
OCFS2_STACK_LABEL_LEN);
21752181
if (strlen(osb->osb_cluster_stack) != OCFS2_STACK_LABEL_LEN) {
21762182
mlog(ML_ERROR,
21772183
"couldn't mount because of an invalid "
@@ -2180,9 +2186,9 @@ static int ocfs2_initialize_super(struct super_block *sb,
21802186
status = -EINVAL;
21812187
goto bail;
21822188
}
2183-
strlcpy(osb->osb_cluster_name,
2189+
memcpy(osb->osb_cluster_name,
21842190
OCFS2_RAW_SB(di)->s_cluster_info.ci_cluster,
2185-
OCFS2_CLUSTER_NAME_LEN + 1);
2191+
OCFS2_CLUSTER_NAME_LEN);
21862192
} else {
21872193
/* The empty string is identical with classic tools that
21882194
* don't know about s_cluster_info. */

fs/userfaultfd.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1827,9 +1827,15 @@ static int userfaultfd_writeprotect(struct userfaultfd_ctx *ctx,
18271827
if (mode_wp && mode_dontwake)
18281828
return -EINVAL;
18291829

1830-
ret = mwriteprotect_range(ctx->mm, uffdio_wp.range.start,
1831-
uffdio_wp.range.len, mode_wp,
1832-
&ctx->mmap_changing);
1830+
if (mmget_not_zero(ctx->mm)) {
1831+
ret = mwriteprotect_range(ctx->mm, uffdio_wp.range.start,
1832+
uffdio_wp.range.len, mode_wp,
1833+
&ctx->mmap_changing);
1834+
mmput(ctx->mm);
1835+
} else {
1836+
return -ESRCH;
1837+
}
1838+
18331839
if (ret)
18341840
return ret;
18351841

include/linux/cpuhotplug.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ enum cpuhp_state {
7272
CPUHP_SLUB_DEAD,
7373
CPUHP_DEBUG_OBJ_DEAD,
7474
CPUHP_MM_WRITEBACK_DEAD,
75+
/* Must be after CPUHP_MM_VMSTAT_DEAD */
76+
CPUHP_MM_DEMOTION_DEAD,
7577
CPUHP_MM_VMSTAT_DEAD,
7678
CPUHP_SOFTIRQ_DEAD,
7779
CPUHP_NET_MVNETA_DEAD,
@@ -240,6 +242,8 @@ enum cpuhp_state {
240242
CPUHP_AP_BASE_CACHEINFO_ONLINE,
241243
CPUHP_AP_ONLINE_DYN,
242244
CPUHP_AP_ONLINE_DYN_END = CPUHP_AP_ONLINE_DYN + 30,
245+
/* Must be after CPUHP_AP_ONLINE_DYN for node_states[N_CPU] update */
246+
CPUHP_AP_MM_DEMOTION_ONLINE,
243247
CPUHP_AP_X86_HPET_ONLINE,
244248
CPUHP_AP_X86_KVM_CLK_ONLINE,
245249
CPUHP_AP_DTPM_CPU_ONLINE,

include/linux/elfcore.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ static inline int elf_core_copy_task_fpregs(struct task_struct *t, struct pt_reg
109109
#endif
110110
}
111111

112-
#if defined(CONFIG_UM) || defined(CONFIG_IA64)
112+
#if (defined(CONFIG_UML) && defined(CONFIG_X86_32)) || defined(CONFIG_IA64)
113113
/*
114114
* These functions parameterize elf_core_dump in fs/binfmt_elf.c to write out
115115
* extra segments containing the gate DSO contents. Dumping its

include/linux/memory.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,10 @@ int walk_dynamic_memory_groups(int nid, walk_memory_groups_func_t func,
160160
#define register_hotmemory_notifier(nb) register_memory_notifier(nb)
161161
#define unregister_hotmemory_notifier(nb) unregister_memory_notifier(nb)
162162
#else
163-
#define hotplug_memory_notifier(fn, pri) ({ 0; })
163+
static inline int hotplug_memory_notifier(notifier_fn_t fn, int pri)
164+
{
165+
return 0;
166+
}
164167
/* These aren't inline functions due to a GCC bug. */
165168
#define register_hotmemory_notifier(nb) ({ (void)(nb); 0; })
166169
#define unregister_hotmemory_notifier(nb) ({ (void)(nb); })

include/linux/secretmem.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ static inline bool page_is_secretmem(struct page *page)
2323
mapping = (struct address_space *)
2424
((unsigned long)page->mapping & ~PAGE_MAPPING_FLAGS);
2525

26-
if (mapping != page->mapping)
26+
if (!mapping || mapping != page->mapping)
2727
return false;
2828

2929
return mapping->a_ops == &secretmem_aops;

mm/huge_memory.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2700,12 +2700,14 @@ int split_huge_page_to_list(struct page *page, struct list_head *list)
27002700
if (mapping) {
27012701
int nr = thp_nr_pages(head);
27022702

2703-
if (PageSwapBacked(head))
2703+
if (PageSwapBacked(head)) {
27042704
__mod_lruvec_page_state(head, NR_SHMEM_THPS,
27052705
-nr);
2706-
else
2706+
} else {
27072707
__mod_lruvec_page_state(head, NR_FILE_THPS,
27082708
-nr);
2709+
filemap_nr_thps_dec(mapping);
2710+
}
27092711
}
27102712

27112713
__split_huge_page(page, list, end);

0 commit comments

Comments
 (0)