diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index 18f6490bfe77..66a3688757dd 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -206,6 +206,18 @@ static void unuse_pde(struct proc_dir_entry *pde)
complete(pde->pde_unload_completion);
}
+/* Pin an entry that can go away around a call into it, see use_pde(). */
+static bool pde_pin(struct proc_dir_entry *pde)
+{
+ return pde_is_permanent(pde) || use_pde(pde);
+}
+
+static void pde_unpin(struct proc_dir_entry *pde)
+{
+ if (!pde_is_permanent(pde))
+ unuse_pde(pde);
+}
+
/*
* At most 2 contexts can enter this function: the one doing the last
* close on the descriptor and whoever is deleting PDE itself.@@ -275,14 +287,12 @@ void proc_entry_rundown(struct proc_dir_entry *de)
static loff_t proc_reg_llseek(struct file *file, loff_t offset, int whence)
{
struct proc_dir_entry *pde = PDE(file_inode(file));
- loff_t rv = -EINVAL;
+ loff_t rv;
- if (pde_is_permanent(pde)) {
- return pde->proc_ops->proc_lseek(file, offset, whence);
- } else if (use_pde(pde)) {
- rv = pde->proc_ops->proc_lseek(file, offset, whence);
- unuse_pde(pde);
- }
+ if (!pde_pin(pde))
+ return -EINVAL;
+ rv = pde->proc_ops->proc_lseek(file, offset, whence);
+ pde_unpin(pde);
return rv;
}
@@ -291,13 +301,10 @@ static ssize_t proc_reg_read_iter(struct kiocb *iocb, struct iov_iter *iter)
struct proc_dir_entry *pde = PDE(file_inode(iocb->ki_filp));
ssize_t ret;
- if (pde_is_permanent(pde))
- return pde->proc_ops->proc_read_iter(iocb, iter);
-
- if (!use_pde(pde))
+ if (!pde_pin(pde))
return -EIO;
ret = pde->proc_ops->proc_read_iter(iocb, iter);
- unuse_pde(pde);
+ pde_unpin(pde);
return ret;
}
@@ -312,14 +319,12 @@ static ssize_t pde_read(struct proc_dir_entry *pde, struct file *file, char __us
static ssize_t proc_reg_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
struct proc_dir_entry *pde = PDE(file_inode(file));
- ssize_t rv = -EIO;
+ ssize_t rv;
- if (pde_is_permanent(pde)) {
- return pde_read(pde, file, buf, count, ppos);
- } else if (use_pde(pde)) {
- rv = pde_read(pde, file, buf, count, ppos);
- unuse_pde(pde);
- }
+ if (!pde_pin(pde))
+ return -EIO;
+ rv = pde_read(pde, file, buf, count, ppos);
+ pde_unpin(pde);
return rv;
}
@@ -334,14 +339,12 @@ static ssize_t pde_write(struct proc_dir_entry *pde, struct file *file, const ch
static ssize_t proc_reg_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
struct proc_dir_entry *pde = PDE(file_inode(file));
- ssize_t rv = -EIO;
+ ssize_t rv;
- if (pde_is_permanent(pde)) {
- return pde_write(pde, file, buf, count, ppos);
- } else if (use_pde(pde)) {
- rv = pde_write(pde, file, buf, count, ppos);
- unuse_pde(pde);
- }
+ if (!pde_pin(pde))
+ return -EIO;
+ rv = pde_write(pde, file, buf, count, ppos);
+ pde_unpin(pde);
return rv;
}
@@ -356,14 +359,12 @@ static __poll_t pde_poll(struct proc_dir_entry *pde, struct file *file, struct p
static __poll_t proc_reg_poll(struct file *file, struct poll_table_struct *pts)
{
struct proc_dir_entry *pde = PDE(file_inode(file));
- __poll_t rv = DEFAULT_POLLMASK;
+ __poll_t rv;
- if (pde_is_permanent(pde)) {
- return pde_poll(pde, file, pts);
- } else if (use_pde(pde)) {
- rv = pde_poll(pde, file, pts);
- unuse_pde(pde);
- }
+ if (!pde_pin(pde))
+ return DEFAULT_POLLMASK;
+ rv = pde_poll(pde, file, pts);
+ pde_unpin(pde);
return rv;
}
@@ -378,14 +379,12 @@ static long pde_ioctl(struct proc_dir_entry *pde, struct file *file, unsigned in
static long proc_reg_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct proc_dir_entry *pde = PDE(file_inode(file));
- long rv = -ENOTTY;
+ long rv;
- if (pde_is_permanent(pde)) {
- return pde_ioctl(pde, file, cmd, arg);
- } else if (use_pde(pde)) {
- rv = pde_ioctl(pde, file, cmd, arg);
- unuse_pde(pde);
- }
+ if (!pde_pin(pde))
+ return -ENOTTY;
+ rv = pde_ioctl(pde, file, cmd, arg);
+ pde_unpin(pde);
return rv;
}
@@ -401,13 +400,12 @@ static long pde_compat_ioctl(struct proc_dir_entry *pde, struct file *file, unsi
static long proc_reg_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct proc_dir_entry *pde = PDE(file_inode(file));
- long rv = -ENOTTY;
- if (pde_is_permanent(pde)) {
- return pde_compat_ioctl(pde, file, cmd, arg);
- } else if (use_pde(pde)) {
- rv = pde_compat_ioctl(pde, file, cmd, arg);
- unuse_pde(pde);
- }
+ long rv;
+
+ if (!pde_pin(pde))
+ return -ENOTTY;
+ rv = pde_compat_ioctl(pde, file, cmd, arg);
+ pde_unpin(pde);
return rv;
}
#else@@ -425,14 +423,12 @@ static int pde_mmap(struct proc_dir_entry *pde, struct file *file, struct vm_are
static int proc_reg_mmap(struct file *file, struct vm_area_struct *vma)
{
struct proc_dir_entry *pde = PDE(file_inode(file));
- int rv = -EIO;
+ int rv;
- if (pde_is_permanent(pde)) {
- return pde_mmap(pde, file, vma);
- } else if (use_pde(pde)) {
- rv = pde_mmap(pde, file, vma);
- unuse_pde(pde);
- }
+ if (!pde_pin(pde))
+ return -EIO;
+ rv = pde_mmap(pde, file, vma);
+ pde_unpin(pde);
return rv;
}
@@ -457,14 +453,12 @@ proc_reg_get_unmapped_area(struct file *file, unsigned long orig_addr,
unsigned long flags)
{
struct proc_dir_entry *pde = PDE(file_inode(file));
- unsigned long rv = -EIO;
+ unsigned long rv;
- if (pde_is_permanent(pde)) {
- return pde_get_unmapped_area(pde, file, orig_addr, len, pgoff, flags);
- } else if (use_pde(pde)) {
- rv = pde_get_unmapped_area(pde, file, orig_addr, len, pgoff, flags);
- unuse_pde(pde);
- }
+ if (!pde_pin(pde))
+ return -EIO;
+ rv = pde_get_unmapped_area(pde, file, orig_addr, len, pgoff, flags);
+ pde_unpin(pde);
return rv;
}
--
2.53.0