This introduces a function which can be used to fetch a file, given an arbitrary task. As long as the user holds a reference (refcnt) to the task_struct it is safe to call, and will either return NULL on failure, or a pointer to the file, with a refcnt. This patch is based on Oleg Nesterov's (cf. [1]) patch from September 2018. [1]: Link: https://lore.kernel.org/r/20180915160423.GA31461@redhat.com
Unified · Split
| @@ -706,9 +706,9 @@ void do_close_on_exec(struct files_struct *files) · 705 unmodified lines | ||
| 706 | 706 | spin_unlock(&files->file_lock); |
| 707 | 707 | } |
| 708 | 708 | |
| 709 | −static struct file *__fget(unsigned int fd, fmode_t mask, unsigned int refs) | |
| 709 | +static struct file *__fget_files(struct files_struct *files, unsigned int fd, | |
| 710 | + fmode_t mask, unsigned int refs) | |
| 710 | 711 | { |
| 711 | − struct files_struct *files = current->files; | |
| 712 | 712 | struct file *file; |
| 713 | 713 | |
| 714 | 714 | rcu_read_lock(); |
| @@ -729,6 +729,12 @@ loop: · 14 unmodified lines | ||
| 729 | 729 | return file; |
| 730 | 730 | } |
| 731 | 731 | |
| 732 | +static inline struct file *__fget(unsigned int fd, fmode_t mask, | |
| 733 | + unsigned int refs) | |
| 734 | +{ | |
| 735 | + return __fget_files(current->files, fd, mask, refs); | |
| 736 | +} | |
| 737 | + | |
| 732 | 738 | struct file *fget_many(unsigned int fd, unsigned int refs) |
| 733 | 739 | { |
| 734 | 740 | return __fget(fd, FMODE_PATH, refs); |
| @@ -746,6 +752,18 @@ struct file *fget_raw(unsigned int fd) · 11 unmodified lines | ||
| 746 | 752 | } |
| 747 | 753 | EXPORT_SYMBOL(fget_raw); |
| 748 | 754 | |
| 755 | +struct file *fget_task(struct task_struct *task, unsigned int fd) | |
| 756 | +{ | |
| 757 | + struct file *file = NULL; | |
| 758 | + | |
| 759 | + task_lock(task); | |
| 760 | + if (task->files) | |
| 761 | + file = __fget_files(task->files, fd, 0, 1); | |
| 762 | + task_unlock(task); | |
| 763 | + | |
| 764 | + return file; | |
| 765 | +} | |
| 766 | + | |
| 749 | 767 | /* |
| 750 | 768 | * Lightweight file lookup - no refcnt increment if fd table isn't shared. |
| 751 | 769 | * |
| @@ -16,6 +16,7 @@ extern void fput(struct file *); · 15 unmodified lines | ||
| 16 | 16 | extern void fput_many(struct file *, unsigned int); |
| 17 | 17 | |
| 18 | 18 | struct file_operations; |
| 19 | +struct task_struct; | |
| 19 | 20 | struct vfsmount; |
| 20 | 21 | struct dentry; |
| 21 | 22 | struct inode; |
| @@ -47,6 +48,7 @@ static inline void fdput(struct fd fd) · 25 unmodified lines | ||
| 47 | 48 | extern struct file *fget(unsigned int fd); |
| 48 | 49 | extern struct file *fget_many(unsigned int fd, unsigned int refs); |
| 49 | 50 | extern struct file *fget_raw(unsigned int fd); |
| 51 | +extern struct file *fget_task(struct task_struct *task, unsigned int fd); | |
| 50 | 52 | extern unsigned long __fdget(unsigned int fd); |
| 51 | 53 | extern unsigned long __fdget_raw(unsigned int fd); |
| 52 | 54 | extern unsigned long __fdget_pos(unsigned int fd); |