diff options
Diffstat (limited to 'fs/proc')
| -rw-r--r-- | fs/proc/array.c | 8 | ||||
| -rw-r--r-- | fs/proc/base.c | 70 | ||||
| -rw-r--r-- | fs/proc/consoles.c | 3 | ||||
| -rw-r--r-- | fs/proc/fd.c | 2 | ||||
| -rw-r--r-- | fs/proc/generic.c | 18 | ||||
| -rw-r--r-- | fs/proc/inode.c | 17 | ||||
| -rw-r--r-- | fs/proc/internal.h | 29 | ||||
| -rw-r--r-- | fs/proc/kcore.c | 22 | ||||
| -rw-r--r-- | fs/proc/kmsg.c | 4 | ||||
| -rw-r--r-- | fs/proc/proc_net.c | 4 | ||||
| -rw-r--r-- | fs/proc/proc_sysctl.c | 8 | ||||
| -rw-r--r-- | fs/proc/self.c | 9 | ||||
| -rw-r--r-- | fs/proc/task_mmu.c | 19 | ||||
| -rw-r--r-- | fs/proc/thread_self.c | 8 | ||||
| -rw-r--r-- | fs/proc/vmcore.c | 6 | 
15 files changed, 127 insertions, 100 deletions
| diff --git a/fs/proc/array.c b/fs/proc/array.c index d67a72dcb92c..598803576e4c 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -736,16 +736,10 @@ static int children_seq_open(struct inode *inode, struct file *file)  	return ret;  } -int children_seq_release(struct inode *inode, struct file *file) -{ -	seq_release(inode, file); -	return 0; -} -  const struct file_operations proc_tid_children_operations = {  	.open    = children_seq_open,  	.read    = seq_read,  	.llseek  = seq_lseek, -	.release = children_seq_release, +	.release = seq_release,  };  #endif /* CONFIG_PROC_CHILDREN */ diff --git a/fs/proc/base.c b/fs/proc/base.c index 60316b52d659..9298324325ed 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -75,6 +75,7 @@  #include <linux/ptrace.h>  #include <linux/tracehook.h>  #include <linux/printk.h> +#include <linux/cache.h>  #include <linux/cgroup.h>  #include <linux/cpuset.h>  #include <linux/audit.h> @@ -100,6 +101,8 @@  #include "internal.h"  #include "fd.h" +#include "../../lib/kstrtox.h" +  /* NOTE:   *	Implementing inode permission operations in /proc is almost   *	certainly an error.  Permission checks need to happen during @@ -110,8 +113,8 @@   *	in /proc for a task before it execs a suid executable.   */ -static u8 nlink_tid; -static u8 nlink_tgid; +static u8 nlink_tid __ro_after_init; +static u8 nlink_tgid __ro_after_init;  struct pid_entry {  	const char *name; @@ -1370,7 +1373,7 @@ static ssize_t proc_fail_nth_write(struct file *file, const char __user *buf,  	task = get_proc_task(file_inode(file));  	if (!task)  		return -ESRCH; -	WRITE_ONCE(task->fail_nth, n); +	task->fail_nth = n;  	put_task_struct(task);  	return count; @@ -1386,8 +1389,7 @@ static ssize_t proc_fail_nth_read(struct file *file, char __user *buf,  	task = get_proc_task(file_inode(file));  	if (!task)  		return -ESRCH; -	len = snprintf(numbuf, sizeof(numbuf), "%u\n", -			READ_ONCE(task->fail_nth)); +	len = snprintf(numbuf, sizeof(numbuf), "%u\n", task->fail_nth);  	len = simple_read_from_buffer(buf, count, ppos, numbuf, len);  	put_task_struct(task); @@ -1907,8 +1909,33 @@ end_instantiate:  static int dname_to_vma_addr(struct dentry *dentry,  			     unsigned long *start, unsigned long *end)  { -	if (sscanf(dentry->d_name.name, "%lx-%lx", start, end) != 2) +	const char *str = dentry->d_name.name; +	unsigned long long sval, eval; +	unsigned int len; + +	len = _parse_integer(str, 16, &sval); +	if (len & KSTRTOX_OVERFLOW) +		return -EINVAL; +	if (sval != (unsigned long)sval)  		return -EINVAL; +	str += len; + +	if (*str != '-') +		return -EINVAL; +	str++; + +	len = _parse_integer(str, 16, &eval); +	if (len & KSTRTOX_OVERFLOW) +		return -EINVAL; +	if (eval != (unsigned long)eval) +		return -EINVAL; +	str += len; + +	if (*str != '\0') +		return -EINVAL; + +	*start = sval; +	*end = eval;  	return 0;  } @@ -2000,9 +2027,9 @@ out:  }  struct map_files_info { +	unsigned long	start; +	unsigned long	end;  	fmode_t		mode; -	unsigned int	len; -	unsigned char	name[4*sizeof(long)+2]; /* max: %lx-%lx\0 */  };  /* @@ -2172,10 +2199,9 @@ proc_map_files_readdir(struct file *file, struct dir_context *ctx)  			if (++pos <= ctx->pos)  				continue; +			info.start = vma->vm_start; +			info.end = vma->vm_end;  			info.mode = vma->vm_file->f_mode; -			info.len = snprintf(info.name, -					sizeof(info.name), "%lx-%lx", -					vma->vm_start, vma->vm_end);  			if (flex_array_put(fa, i++, &info, GFP_KERNEL))  				BUG();  		} @@ -2183,9 +2209,13 @@ proc_map_files_readdir(struct file *file, struct dir_context *ctx)  	up_read(&mm->mmap_sem);  	for (i = 0; i < nr_files; i++) { +		char buf[4 * sizeof(long) + 2];	/* max: %lx-%lx\0 */ +		unsigned int len; +  		p = flex_array_get(fa, i); +		len = snprintf(buf, sizeof(buf), "%lx-%lx", p->start, p->end);  		if (!proc_fill_cache(file, ctx, -				      p->name, p->len, +				      buf, len,  				      proc_map_files_instantiate,  				      task,  				      (void *)(unsigned long)p->mode)) @@ -3018,11 +3048,11 @@ static const struct inode_operations proc_tgid_base_inode_operations = {  static void proc_flush_task_mnt(struct vfsmount *mnt, pid_t pid, pid_t tgid)  {  	struct dentry *dentry, *leader, *dir; -	char buf[PROC_NUMBUF]; +	char buf[10 + 1];  	struct qstr name;  	name.name = buf; -	name.len = snprintf(buf, sizeof(buf), "%d", pid); +	name.len = snprintf(buf, sizeof(buf), "%u", pid);  	/* no ->d_hash() rejects on procfs */  	dentry = d_hash_and_lookup(mnt->mnt_root, &name);  	if (dentry) { @@ -3034,7 +3064,7 @@ static void proc_flush_task_mnt(struct vfsmount *mnt, pid_t pid, pid_t tgid)  		return;  	name.name = buf; -	name.len = snprintf(buf, sizeof(buf), "%d", tgid); +	name.len = snprintf(buf, sizeof(buf), "%u", tgid);  	leader = d_hash_and_lookup(mnt->mnt_root, &name);  	if (!leader)  		goto out; @@ -3046,7 +3076,7 @@ static void proc_flush_task_mnt(struct vfsmount *mnt, pid_t pid, pid_t tgid)  		goto out_put_leader;  	name.name = buf; -	name.len = snprintf(buf, sizeof(buf), "%d", pid); +	name.len = snprintf(buf, sizeof(buf), "%u", pid);  	dentry = d_hash_and_lookup(dir, &name);  	if (dentry) {  		d_invalidate(dentry); @@ -3225,14 +3255,14 @@ int proc_pid_readdir(struct file *file, struct dir_context *ctx)  	for (iter = next_tgid(ns, iter);  	     iter.task;  	     iter.tgid += 1, iter = next_tgid(ns, iter)) { -		char name[PROC_NUMBUF]; +		char name[10 + 1];  		int len;  		cond_resched();  		if (!has_pid_permissions(ns, iter.task, HIDEPID_INVISIBLE))  			continue; -		len = snprintf(name, sizeof(name), "%d", iter.tgid); +		len = snprintf(name, sizeof(name), "%u", iter.tgid);  		ctx->pos = iter.tgid + TGID_OFFSET;  		if (!proc_fill_cache(file, ctx, name, len,  				     proc_pid_instantiate, iter.task, NULL)) { @@ -3560,10 +3590,10 @@ static int proc_task_readdir(struct file *file, struct dir_context *ctx)  	for (task = first_tid(proc_pid(inode), tid, ctx->pos - 2, ns);  	     task;  	     task = next_tid(task), ctx->pos++) { -		char name[PROC_NUMBUF]; +		char name[10 + 1];  		int len;  		tid = task_pid_nr_ns(task, ns); -		len = snprintf(name, sizeof(name), "%d", tid); +		len = snprintf(name, sizeof(name), "%u", tid);  		if (!proc_fill_cache(file, ctx, name, len,  				proc_task_instantiate, task, NULL)) {  			/* returning this tgid failed, save it as the first diff --git a/fs/proc/consoles.c b/fs/proc/consoles.c index 290ba85cb900..a8ac48aebd59 100644 --- a/fs/proc/consoles.c +++ b/fs/proc/consoles.c @@ -55,8 +55,7 @@ static int show_console_dev(struct seq_file *m, void *v)  	if (dev)  		seq_printf(m, " %4d:%d", MAJOR(dev), MINOR(dev)); -	seq_printf(m, "\n"); - +	seq_putc(m, '\n');  	return 0;  } diff --git a/fs/proc/fd.c b/fs/proc/fd.c index 96fc70225e54..6b80cd1e419a 100644 --- a/fs/proc/fd.c +++ b/fs/proc/fd.c @@ -236,7 +236,7 @@ static int proc_readfd_common(struct file *file, struct dir_context *ctx,  	for (fd = ctx->pos - 2;  	     fd < files_fdtable(files)->max_fds;  	     fd++, ctx->pos++) { -		char name[PROC_NUMBUF]; +		char name[10 + 1];  		int len;  		if (!fcheck_files(files, fd)) diff --git a/fs/proc/generic.c b/fs/proc/generic.c index 793a67574668..5d709fa8f3a2 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c @@ -28,7 +28,7 @@  static DEFINE_RWLOCK(proc_subdir_lock); -static int proc_match(unsigned int len, const char *name, struct proc_dir_entry *de) +static int proc_match(const char *name, struct proc_dir_entry *de, unsigned int len)  {  	if (len < de->namelen)  		return -1; @@ -60,7 +60,7 @@ static struct proc_dir_entry *pde_subdir_find(struct proc_dir_entry *dir,  		struct proc_dir_entry *de = rb_entry(node,  						     struct proc_dir_entry,  						     subdir_node); -		int result = proc_match(len, name, de); +		int result = proc_match(name, de, len);  		if (result < 0)  			node = node->rb_left; @@ -84,7 +84,7 @@ static bool pde_subdir_insert(struct proc_dir_entry *dir,  		struct proc_dir_entry *this = rb_entry(*new,  						       struct proc_dir_entry,  						       subdir_node); -		int result = proc_match(de->namelen, de->name, this); +		int result = proc_match(de->name, this, de->namelen);  		parent = *new;  		if (result < 0) @@ -211,8 +211,8 @@ void proc_free_inum(unsigned int inum)   * Don't create negative dentries here, return -ENOENT by hand   * instead.   */ -struct dentry *proc_lookup_de(struct proc_dir_entry *de, struct inode *dir, -		struct dentry *dentry) +struct dentry *proc_lookup_de(struct inode *dir, struct dentry *dentry, +			      struct proc_dir_entry *de)  {  	struct inode *inode; @@ -235,7 +235,7 @@ struct dentry *proc_lookup_de(struct proc_dir_entry *de, struct inode *dir,  struct dentry *proc_lookup(struct inode *dir, struct dentry *dentry,  		unsigned int flags)  { -	return proc_lookup_de(PDE(dir), dir, dentry); +	return proc_lookup_de(dir, dentry, PDE(dir));  }  /* @@ -247,8 +247,8 @@ struct dentry *proc_lookup(struct inode *dir, struct dentry *dentry,   * value of the readdir() call, as long as it's non-negative   * for success..   */ -int proc_readdir_de(struct proc_dir_entry *de, struct file *file, -		    struct dir_context *ctx) +int proc_readdir_de(struct file *file, struct dir_context *ctx, +		    struct proc_dir_entry *de)  {  	int i; @@ -292,7 +292,7 @@ int proc_readdir(struct file *file, struct dir_context *ctx)  {  	struct inode *inode = file_inode(file); -	return proc_readdir_de(PDE(inode), file, ctx); +	return proc_readdir_de(file, ctx, PDE(inode));  }  /* diff --git a/fs/proc/inode.c b/fs/proc/inode.c index dd0f82622427..6e8724958116 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c @@ -5,6 +5,7 @@   *  Copyright (C) 1991, 1992  Linus Torvalds   */ +#include <linux/cache.h>  #include <linux/time.h>  #include <linux/proc_fs.h>  #include <linux/kernel.h> @@ -52,7 +53,7 @@ static void proc_evict_inode(struct inode *inode)  	}  } -static struct kmem_cache * proc_inode_cachep; +static struct kmem_cache *proc_inode_cachep __ro_after_init;  static struct inode *proc_alloc_inode(struct super_block *sb)  { @@ -128,12 +129,12 @@ enum {BIAS = -1U<<31};  static inline int use_pde(struct proc_dir_entry *pde)  { -	return atomic_inc_unless_negative(&pde->in_use); +	return likely(atomic_inc_unless_negative(&pde->in_use));  }  static void unuse_pde(struct proc_dir_entry *pde)  { -	if (atomic_dec_return(&pde->in_use) == BIAS) +	if (unlikely(atomic_dec_return(&pde->in_use) == BIAS))  		complete(pde->pde_unload_completion);  } @@ -166,7 +167,7 @@ static void close_pdeo(struct proc_dir_entry *pde, struct pde_opener *pdeo)  		spin_lock(&pde->pde_unload_lock);  		/* After ->release. */  		list_del(&pdeo->lh); -		if (pdeo->c) +		if (unlikely(pdeo->c))  			complete(pdeo->c);  		kfree(pdeo);  	} @@ -234,11 +235,11 @@ static ssize_t proc_reg_write(struct file *file, const char __user *buf, size_t  	return rv;  } -static unsigned int proc_reg_poll(struct file *file, struct poll_table_struct *pts) +static __poll_t proc_reg_poll(struct file *file, struct poll_table_struct *pts)  {  	struct proc_dir_entry *pde = PDE(file_inode(file)); -	unsigned int rv = DEFAULT_POLLMASK; -	unsigned int (*poll)(struct file *, struct poll_table_struct *); +	__poll_t rv = DEFAULT_POLLMASK; +	__poll_t (*poll)(struct file *, struct poll_table_struct *);  	if (use_pde(pde)) {  		poll = pde->proc_fops->poll;  		if (poll) @@ -420,7 +421,7 @@ static const char *proc_get_link(struct dentry *dentry,  				 struct delayed_call *done)  {  	struct proc_dir_entry *pde = PDE(inode); -	if (unlikely(!use_pde(pde))) +	if (!use_pde(pde))  		return ERR_PTR(-EINVAL);  	set_delayed_call(done, proc_put_link, pde);  	return pde->data; diff --git a/fs/proc/internal.h b/fs/proc/internal.h index 4a67188c8d74..d697c8ab0a14 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h @@ -31,24 +31,28 @@ struct mempolicy;   * subdir_node is used to build the rb tree "subdir" of the parent.   */  struct proc_dir_entry { +	/* +	 * number of callers into module in progress; +	 * negative -> it's going away RSN +	 */ +	atomic_t in_use; +	atomic_t count;		/* use count */ +	struct list_head pde_openers;	/* who did ->open, but not ->release */ +	/* protects ->pde_openers and all struct pde_opener instances */ +	spinlock_t pde_unload_lock; +	struct completion *pde_unload_completion; +	const struct inode_operations *proc_iops; +	const struct file_operations *proc_fops; +	void *data;  	unsigned int low_ino; -	umode_t mode;  	nlink_t nlink;  	kuid_t uid;  	kgid_t gid;  	loff_t size; -	const struct inode_operations *proc_iops; -	const struct file_operations *proc_fops;  	struct proc_dir_entry *parent;  	struct rb_root_cached subdir;  	struct rb_node subdir_node; -	void *data; -	atomic_t count;		/* use count */ -	atomic_t in_use;	/* number of callers into module in progress; */ -			/* negative -> it's going away RSN */ -	struct completion *pde_unload_completion; -	struct list_head pde_openers;	/* who did ->open, but not ->release */ -	spinlock_t pde_unload_lock; /* proc_fops checks and pde_users bumps */ +	umode_t mode;  	u8 namelen;  	char name[];  } __randomize_layout; @@ -149,10 +153,9 @@ extern bool proc_fill_cache(struct file *, struct dir_context *, const char *, i   * generic.c   */  extern struct dentry *proc_lookup(struct inode *, struct dentry *, unsigned int); -extern struct dentry *proc_lookup_de(struct proc_dir_entry *, struct inode *, -				     struct dentry *); +struct dentry *proc_lookup_de(struct inode *, struct dentry *, struct proc_dir_entry *);  extern int proc_readdir(struct file *, struct dir_context *); -extern int proc_readdir_de(struct proc_dir_entry *, struct file *, struct dir_context *); +int proc_readdir_de(struct file *, struct dir_context *, struct proc_dir_entry *);  static inline struct proc_dir_entry *pde_get(struct proc_dir_entry *pde)  { diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c index 4bc85cb8be6a..d1e82761de81 100644 --- a/fs/proc/kcore.c +++ b/fs/proc/kcore.c @@ -510,25 +510,21 @@ read_kcore(struct file *file, char __user *buffer, size_t buflen, loff_t *fpos)  			/* we have to zero-fill user buffer even if no read */  			if (copy_to_user(buffer, buf, tsz))  				return -EFAULT; +		} else if (m->type == KCORE_USER) { +			/* User page is handled prior to normal kernel page: */ +			if (copy_to_user(buffer, (char *)start, tsz)) +				return -EFAULT;  		} else {  			if (kern_addr_valid(start)) { -				unsigned long n; -  				/*  				 * Using bounce buffer to bypass the  				 * hardened user copy kernel text checks.  				 */ -				memcpy(buf, (char *) start, tsz); -				n = copy_to_user(buffer, buf, tsz); -				/* -				 * We cannot distinguish between fault on source -				 * and fault on destination. When this happens -				 * we clear too and hope it will trigger the -				 * EFAULT again. -				 */ -				if (n) {  -					if (clear_user(buffer + tsz - n, -								n)) +				if (probe_kernel_read(buf, (void *) start, tsz)) { +					if (clear_user(buffer, tsz)) +						return -EFAULT; +				} else { +					if (copy_to_user(buffer, buf, tsz))  						return -EFAULT;  				}  			} else { diff --git a/fs/proc/kmsg.c b/fs/proc/kmsg.c index e0f8774acd65..4f4a2abb225e 100644 --- a/fs/proc/kmsg.c +++ b/fs/proc/kmsg.c @@ -40,11 +40,11 @@ static ssize_t kmsg_read(struct file *file, char __user *buf,  	return do_syslog(SYSLOG_ACTION_READ, buf, count, SYSLOG_FROM_PROC);  } -static unsigned int kmsg_poll(struct file *file, poll_table *wait) +static __poll_t kmsg_poll(struct file *file, poll_table *wait)  {  	poll_wait(file, &log_wait, wait);  	if (do_syslog(SYSLOG_ACTION_SIZE_UNREAD, NULL, 0, SYSLOG_FROM_PROC)) -		return POLLIN | POLLRDNORM; +		return EPOLLIN | EPOLLRDNORM;  	return 0;  } diff --git a/fs/proc/proc_net.c b/fs/proc/proc_net.c index a2bf369c923d..68c06ae7888c 100644 --- a/fs/proc/proc_net.c +++ b/fs/proc/proc_net.c @@ -135,7 +135,7 @@ static struct dentry *proc_tgid_net_lookup(struct inode *dir,  	de = ERR_PTR(-ENOENT);  	net = get_proc_task_net(dir);  	if (net != NULL) { -		de = proc_lookup_de(net->proc_net, dir, dentry); +		de = proc_lookup_de(dir, dentry, net->proc_net);  		put_net(net);  	}  	return de; @@ -172,7 +172,7 @@ static int proc_tgid_net_readdir(struct file *file, struct dir_context *ctx)  	ret = -EINVAL;  	net = get_proc_task_net(file_inode(file));  	if (net != NULL) { -		ret = proc_readdir_de(net->proc_net, file, ctx); +		ret = proc_readdir_de(file, ctx, net->proc_net);  		put_net(net);  	}  	return ret; diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c index c5cbbdff3c3d..c41ab261397d 100644 --- a/fs/proc/proc_sysctl.c +++ b/fs/proc/proc_sysctl.c @@ -630,17 +630,17 @@ static int proc_sys_open(struct inode *inode, struct file *filp)  	return 0;  } -static unsigned int proc_sys_poll(struct file *filp, poll_table *wait) +static __poll_t proc_sys_poll(struct file *filp, poll_table *wait)  {  	struct inode *inode = file_inode(filp);  	struct ctl_table_header *head = grab_header(inode);  	struct ctl_table *table = PROC_I(inode)->sysctl_entry; -	unsigned int ret = DEFAULT_POLLMASK; +	__poll_t ret = DEFAULT_POLLMASK;  	unsigned long event;  	/* sysctl was unregistered */  	if (IS_ERR(head)) -		return POLLERR | POLLHUP; +		return EPOLLERR | EPOLLHUP;  	if (!table->proc_handler)  		goto out; @@ -653,7 +653,7 @@ static unsigned int proc_sys_poll(struct file *filp, poll_table *wait)  	if (event != atomic_read(&table->poll->event)) {  		filp->private_data = proc_sys_poll_event(table->poll); -		ret = POLLIN | POLLRDNORM | POLLERR | POLLPRI; +		ret = EPOLLIN | EPOLLRDNORM | EPOLLERR | EPOLLPRI;  	}  out: diff --git a/fs/proc/self.c b/fs/proc/self.c index 31326bb23b8b..4d7d061696b3 100644 --- a/fs/proc/self.c +++ b/fs/proc/self.c @@ -1,4 +1,5 @@  // SPDX-License-Identifier: GPL-2.0 +#include <linux/cache.h>  #include <linux/sched.h>  #include <linux/slab.h>  #include <linux/pid_namespace.h> @@ -17,11 +18,11 @@ static const char *proc_self_get_link(struct dentry *dentry,  	if (!tgid)  		return ERR_PTR(-ENOENT); -	/* 11 for max length of signed int in decimal + NULL term */ -	name = kmalloc(12, dentry ? GFP_KERNEL : GFP_ATOMIC); +	/* max length of unsigned int in decimal + NULL term */ +	name = kmalloc(10 + 1, dentry ? GFP_KERNEL : GFP_ATOMIC);  	if (unlikely(!name))  		return dentry ? ERR_PTR(-ENOMEM) : ERR_PTR(-ECHILD); -	sprintf(name, "%d", tgid); +	sprintf(name, "%u", tgid);  	set_delayed_call(done, kfree_link, name);  	return name;  } @@ -30,7 +31,7 @@ static const struct inode_operations proc_self_inode_operations = {  	.get_link	= proc_self_get_link,  }; -static unsigned self_inum; +static unsigned self_inum __ro_after_init;  int proc_setup_self(struct super_block *s)  { diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 339e4c1c044d..ec6d2983a5cb 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -47,8 +47,11 @@ void task_mem(struct seq_file *m, struct mm_struct *mm)  	if (hiwater_rss < mm->hiwater_rss)  		hiwater_rss = mm->hiwater_rss; -	text = (PAGE_ALIGN(mm->end_code) - (mm->start_code & PAGE_MASK)) >> 10; -	lib = (mm->exec_vm << (PAGE_SHIFT-10)) - text; +	/* split executable areas between text and lib */ +	text = PAGE_ALIGN(mm->end_code) - (mm->start_code & PAGE_MASK); +	text = min(text, mm->exec_vm << PAGE_SHIFT); +	lib = (mm->exec_vm << PAGE_SHIFT) - text; +  	swap = get_mm_counter(mm, MM_SWAPENTS);  	seq_printf(m,  		"VmPeak:\t%8lu kB\n" @@ -76,7 +79,9 @@ void task_mem(struct seq_file *m, struct mm_struct *mm)  		file << (PAGE_SHIFT-10),  		shmem << (PAGE_SHIFT-10),  		mm->data_vm << (PAGE_SHIFT-10), -		mm->stack_vm << (PAGE_SHIFT-10), text, lib, +		mm->stack_vm << (PAGE_SHIFT-10), +		text >> 10, +		lib >> 10,  		mm_pgtables_bytes(mm) >> 10,  		swap << (PAGE_SHIFT-10));  	hugetlb_report_usage(m, mm); @@ -977,14 +982,14 @@ static inline void clear_soft_dirty(struct vm_area_struct *vma,  static inline void clear_soft_dirty_pmd(struct vm_area_struct *vma,  		unsigned long addr, pmd_t *pmdp)  { -	pmd_t pmd = *pmdp; +	pmd_t old, pmd = *pmdp;  	if (pmd_present(pmd)) {  		/* See comment in change_huge_pmd() */ -		pmdp_invalidate(vma, addr, pmdp); -		if (pmd_dirty(*pmdp)) +		old = pmdp_invalidate(vma, addr, pmdp); +		if (pmd_dirty(old))  			pmd = pmd_mkdirty(pmd); -		if (pmd_young(*pmdp)) +		if (pmd_young(old))  			pmd = pmd_mkyoung(pmd);  		pmd = pmd_wrprotect(pmd); diff --git a/fs/proc/thread_self.c b/fs/proc/thread_self.c index b813e3b529f2..9d2efaca499f 100644 --- a/fs/proc/thread_self.c +++ b/fs/proc/thread_self.c @@ -1,4 +1,5 @@  // SPDX-License-Identifier: GPL-2.0 +#include <linux/cache.h>  #include <linux/sched.h>  #include <linux/slab.h>  #include <linux/pid_namespace.h> @@ -18,11 +19,10 @@ static const char *proc_thread_self_get_link(struct dentry *dentry,  	if (!pid)  		return ERR_PTR(-ENOENT); -	name = kmalloc(PROC_NUMBUF + 6 + PROC_NUMBUF, -				dentry ? GFP_KERNEL : GFP_ATOMIC); +	name = kmalloc(10 + 6 + 10 + 1, dentry ? GFP_KERNEL : GFP_ATOMIC);  	if (unlikely(!name))  		return dentry ? ERR_PTR(-ENOMEM) : ERR_PTR(-ECHILD); -	sprintf(name, "%d/task/%d", tgid, pid); +	sprintf(name, "%u/task/%u", tgid, pid);  	set_delayed_call(done, kfree_link, name);  	return name;  } @@ -31,7 +31,7 @@ static const struct inode_operations proc_thread_self_inode_operations = {  	.get_link	= proc_thread_self_get_link,  }; -static unsigned thread_self_inum; +static unsigned thread_self_inum __ro_after_init;  int proc_setup_thread_self(struct super_block *s)  { diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c index 885d445afa0d..a45f0af22a60 100644 --- a/fs/proc/vmcore.c +++ b/fs/proc/vmcore.c @@ -1178,18 +1178,16 @@ fs_initcall(vmcore_init);  /* Cleanup function for vmcore module. */  void vmcore_cleanup(void)  { -	struct list_head *pos, *next; -  	if (proc_vmcore) {  		proc_remove(proc_vmcore);  		proc_vmcore = NULL;  	}  	/* clear the vmcore list. */ -	list_for_each_safe(pos, next, &vmcore_list) { +	while (!list_empty(&vmcore_list)) {  		struct vmcore *m; -		m = list_entry(pos, struct vmcore, list); +		m = list_first_entry(&vmcore_list, struct vmcore, list);  		list_del(&m->list);  		kfree(m);  	} |