1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 */
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * descriptor table internals; you almost certainly want file.h instead.
4*4882a593Smuzhiyun */
5*4882a593Smuzhiyun
6*4882a593Smuzhiyun #ifndef __LINUX_FDTABLE_H
7*4882a593Smuzhiyun #define __LINUX_FDTABLE_H
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun #include <linux/posix_types.h>
10*4882a593Smuzhiyun #include <linux/compiler.h>
11*4882a593Smuzhiyun #include <linux/spinlock.h>
12*4882a593Smuzhiyun #include <linux/rcupdate.h>
13*4882a593Smuzhiyun #include <linux/nospec.h>
14*4882a593Smuzhiyun #include <linux/types.h>
15*4882a593Smuzhiyun #include <linux/init.h>
16*4882a593Smuzhiyun #include <linux/fs.h>
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun #include <linux/atomic.h>
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun /*
21*4882a593Smuzhiyun * The default fd array needs to be at least BITS_PER_LONG,
22*4882a593Smuzhiyun * as this is the granularity returned by copy_fdset().
23*4882a593Smuzhiyun */
24*4882a593Smuzhiyun #define NR_OPEN_DEFAULT BITS_PER_LONG
25*4882a593Smuzhiyun #define NR_OPEN_MAX ~0U
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun struct fdtable {
28*4882a593Smuzhiyun unsigned int max_fds;
29*4882a593Smuzhiyun struct file __rcu **fd; /* current fd array */
30*4882a593Smuzhiyun unsigned long *close_on_exec;
31*4882a593Smuzhiyun unsigned long *open_fds;
32*4882a593Smuzhiyun unsigned long *full_fds_bits;
33*4882a593Smuzhiyun struct rcu_head rcu;
34*4882a593Smuzhiyun };
35*4882a593Smuzhiyun
close_on_exec(unsigned int fd,const struct fdtable * fdt)36*4882a593Smuzhiyun static inline bool close_on_exec(unsigned int fd, const struct fdtable *fdt)
37*4882a593Smuzhiyun {
38*4882a593Smuzhiyun return test_bit(fd, fdt->close_on_exec);
39*4882a593Smuzhiyun }
40*4882a593Smuzhiyun
fd_is_open(unsigned int fd,const struct fdtable * fdt)41*4882a593Smuzhiyun static inline bool fd_is_open(unsigned int fd, const struct fdtable *fdt)
42*4882a593Smuzhiyun {
43*4882a593Smuzhiyun return test_bit(fd, fdt->open_fds);
44*4882a593Smuzhiyun }
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun /*
47*4882a593Smuzhiyun * Open file table structure
48*4882a593Smuzhiyun */
49*4882a593Smuzhiyun struct files_struct {
50*4882a593Smuzhiyun /*
51*4882a593Smuzhiyun * read mostly part
52*4882a593Smuzhiyun */
53*4882a593Smuzhiyun atomic_t count;
54*4882a593Smuzhiyun bool resize_in_progress;
55*4882a593Smuzhiyun wait_queue_head_t resize_wait;
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun struct fdtable __rcu *fdt;
58*4882a593Smuzhiyun struct fdtable fdtab;
59*4882a593Smuzhiyun /*
60*4882a593Smuzhiyun * written part on a separate cache line in SMP
61*4882a593Smuzhiyun */
62*4882a593Smuzhiyun spinlock_t file_lock ____cacheline_aligned_in_smp;
63*4882a593Smuzhiyun unsigned int next_fd;
64*4882a593Smuzhiyun unsigned long close_on_exec_init[1];
65*4882a593Smuzhiyun unsigned long open_fds_init[1];
66*4882a593Smuzhiyun unsigned long full_fds_bits_init[1];
67*4882a593Smuzhiyun struct file __rcu * fd_array[NR_OPEN_DEFAULT];
68*4882a593Smuzhiyun };
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun struct file_operations;
71*4882a593Smuzhiyun struct vfsmount;
72*4882a593Smuzhiyun struct dentry;
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun #define rcu_dereference_check_fdtable(files, fdtfd) \
75*4882a593Smuzhiyun rcu_dereference_check((fdtfd), lockdep_is_held(&(files)->file_lock))
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun #define files_fdtable(files) \
78*4882a593Smuzhiyun rcu_dereference_check_fdtable((files), (files)->fdt)
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun /*
81*4882a593Smuzhiyun * The caller must ensure that fd table isn't shared or hold rcu or file lock
82*4882a593Smuzhiyun */
__fcheck_files(struct files_struct * files,unsigned int fd)83*4882a593Smuzhiyun static inline struct file *__fcheck_files(struct files_struct *files, unsigned int fd)
84*4882a593Smuzhiyun {
85*4882a593Smuzhiyun struct fdtable *fdt = rcu_dereference_raw(files->fdt);
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun if (fd < fdt->max_fds) {
88*4882a593Smuzhiyun fd = array_index_nospec(fd, fdt->max_fds);
89*4882a593Smuzhiyun return rcu_dereference_raw(fdt->fd[fd]);
90*4882a593Smuzhiyun }
91*4882a593Smuzhiyun return NULL;
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun
fcheck_files(struct files_struct * files,unsigned int fd)94*4882a593Smuzhiyun static inline struct file *fcheck_files(struct files_struct *files, unsigned int fd)
95*4882a593Smuzhiyun {
96*4882a593Smuzhiyun RCU_LOCKDEP_WARN(!rcu_read_lock_held() &&
97*4882a593Smuzhiyun !lockdep_is_held(&files->file_lock),
98*4882a593Smuzhiyun "suspicious rcu_dereference_check() usage");
99*4882a593Smuzhiyun return __fcheck_files(files, fd);
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun /*
103*4882a593Smuzhiyun * Check whether the specified fd has an open file.
104*4882a593Smuzhiyun */
105*4882a593Smuzhiyun #define fcheck(fd) fcheck_files(current->files, fd)
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun struct task_struct;
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun struct files_struct *get_files_struct(struct task_struct *);
110*4882a593Smuzhiyun void put_files_struct(struct files_struct *fs);
111*4882a593Smuzhiyun void reset_files_struct(struct files_struct *);
112*4882a593Smuzhiyun int unshare_files(struct files_struct **);
113*4882a593Smuzhiyun struct files_struct *dup_fd(struct files_struct *, unsigned, int *) __latent_entropy;
114*4882a593Smuzhiyun void do_close_on_exec(struct files_struct *);
115*4882a593Smuzhiyun int iterate_fd(struct files_struct *, unsigned,
116*4882a593Smuzhiyun int (*)(const void *, struct file *, unsigned),
117*4882a593Smuzhiyun const void *);
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun extern int __alloc_fd(struct files_struct *files,
120*4882a593Smuzhiyun unsigned start, unsigned end, unsigned flags);
121*4882a593Smuzhiyun extern void __fd_install(struct files_struct *files,
122*4882a593Smuzhiyun unsigned int fd, struct file *file);
123*4882a593Smuzhiyun extern int __close_fd(struct files_struct *files,
124*4882a593Smuzhiyun unsigned int fd);
125*4882a593Smuzhiyun extern int __close_range(unsigned int fd, unsigned int max_fd, unsigned int flags);
126*4882a593Smuzhiyun extern int close_fd_get_file(unsigned int fd, struct file **res);
127*4882a593Smuzhiyun extern int unshare_fd(unsigned long unshare_flags, unsigned int max_fds,
128*4882a593Smuzhiyun struct files_struct **new_fdp);
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun extern struct kmem_cache *files_cachep;
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun #endif /* __LINUX_FDTABLE_H */
133