]>
Commit | Line | Data |
---|---|---|
59d8053f | 1 | /* Internal procfs definitions |
1da177e4 LT |
2 | * |
3 | * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. | |
4 | * Written by David Howells (dhowells@redhat.com) | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or | |
7 | * modify it under the terms of the GNU General Public License | |
8 | * as published by the Free Software Foundation; either version | |
9 | * 2 of the License, or (at your option) any later version. | |
10 | */ | |
11 | ||
12 | #include <linux/proc_fs.h> | |
59d8053f DH |
13 | #include <linux/proc_ns.h> |
14 | #include <linux/spinlock.h> | |
15 | #include <linux/atomic.h> | |
e579d2c2 | 16 | #include <linux/binfmts.h> |
f7ccbae4 | 17 | #include <linux/sched/coredump.h> |
f719ff9b | 18 | #include <linux/sched/task.h> |
1da177e4 | 19 | |
59d8053f DH |
20 | struct ctl_table_header; |
21 | struct mempolicy; | |
77b14db5 | 22 | |
59d8053f DH |
23 | /* |
24 | * This is not completely implemented yet. The idea is to | |
25 | * create an in-memory tree (like the actual /proc filesystem | |
26 | * tree) of these proc_dir_entries, so that we can dynamically | |
27 | * add new files to /proc. | |
28 | * | |
710585d4 ND |
29 | * parent/subdir are used for the directory structure (every /proc file has a |
30 | * parent, but "subdir" is empty for all non-directory entries). | |
31 | * subdir_node is used to build the rb tree "subdir" of the parent. | |
59d8053f DH |
32 | */ |
33 | struct proc_dir_entry { | |
34 | unsigned int low_ino; | |
35 | umode_t mode; | |
36 | nlink_t nlink; | |
37 | kuid_t uid; | |
38 | kgid_t gid; | |
39 | loff_t size; | |
40 | const struct inode_operations *proc_iops; | |
41 | const struct file_operations *proc_fops; | |
710585d4 ND |
42 | struct proc_dir_entry *parent; |
43 | struct rb_root subdir; | |
44 | struct rb_node subdir_node; | |
59d8053f DH |
45 | void *data; |
46 | atomic_t count; /* use count */ | |
47 | atomic_t in_use; /* number of callers into module in progress; */ | |
48 | /* negative -> it's going away RSN */ | |
49 | struct completion *pde_unload_completion; | |
50 | struct list_head pde_openers; /* who did ->open, but not ->release */ | |
51 | spinlock_t pde_unload_lock; /* proc_fops checks and pde_users bumps */ | |
52 | u8 namelen; | |
53 | char name[]; | |
3859a271 | 54 | } __randomize_layout; |
1da177e4 | 55 | |
59d8053f DH |
56 | union proc_op { |
57 | int (*proc_get_link)(struct dentry *, struct path *); | |
59d8053f DH |
58 | int (*proc_show)(struct seq_file *m, |
59 | struct pid_namespace *ns, struct pid *pid, | |
60 | struct task_struct *task); | |
61 | }; | |
99f89551 | 62 | |
59d8053f | 63 | struct proc_inode { |
f2beb798 | 64 | struct pid *pid; |
771187d6 | 65 | unsigned int fd; |
59d8053f DH |
66 | union proc_op op; |
67 | struct proc_dir_entry *pde; | |
68 | struct ctl_table_header *sysctl; | |
69 | struct ctl_table *sysctl_entry; | |
2fd1d2c4 | 70 | struct hlist_node sysctl_inodes; |
3d3d35b1 | 71 | const struct proc_ns_operations *ns_ops; |
59d8053f | 72 | struct inode vfs_inode; |
3859a271 | 73 | } __randomize_layout; |
f2beb798 | 74 | |
c30480b9 DH |
75 | /* |
76 | * General functions | |
77 | */ | |
78 | static inline struct proc_inode *PROC_I(const struct inode *inode) | |
79 | { | |
80 | return container_of(inode, struct proc_inode, vfs_inode); | |
81 | } | |
82 | ||
83 | static inline struct proc_dir_entry *PDE(const struct inode *inode) | |
84 | { | |
85 | return PROC_I(inode)->pde; | |
86 | } | |
87 | ||
88 | static inline void *__PDE_DATA(const struct inode *inode) | |
89 | { | |
90 | return PDE(inode)->data; | |
91 | } | |
fee781e6 | 92 | |
13b41b09 | 93 | static inline struct pid *proc_pid(struct inode *inode) |
99f89551 | 94 | { |
13b41b09 | 95 | return PROC_I(inode)->pid; |
99f89551 EB |
96 | } |
97 | ||
98 | static inline struct task_struct *get_proc_task(struct inode *inode) | |
1da177e4 | 99 | { |
13b41b09 | 100 | return get_pid_task(proc_pid(inode), PIDTYPE_PID); |
1da177e4 LT |
101 | } |
102 | ||
68eb94f1 EB |
103 | void task_dump_owner(struct task_struct *task, mode_t mode, |
104 | kuid_t *ruid, kgid_t *rgid); | |
faf60af1 | 105 | |
dbcdb504 | 106 | static inline unsigned name_to_int(const struct qstr *qstr) |
faf60af1 | 107 | { |
dbcdb504 AD |
108 | const char *name = qstr->name; |
109 | int len = qstr->len; | |
faf60af1 CG |
110 | unsigned n = 0; |
111 | ||
112 | if (len > 1 && *name == '0') | |
113 | goto out; | |
114 | while (len-- > 0) { | |
115 | unsigned c = *name++ - '0'; | |
116 | if (c > 9) | |
117 | goto out; | |
118 | if (n >= (~0U-9)/10) | |
119 | goto out; | |
120 | n *= 10; | |
121 | n += c; | |
122 | } | |
123 | return n; | |
124 | out: | |
125 | return ~0U; | |
126 | } | |
127 | ||
1dd704b6 | 128 | /* |
59d8053f | 129 | * Offset of the first process in the /proc root directory.. |
1dd704b6 | 130 | */ |
59d8053f | 131 | #define FIRST_PROCESS_ENTRY 256 |
1dd704b6 | 132 | |
59d8053f DH |
133 | /* Worst case buffer size needed for holding an integer. */ |
134 | #define PROC_NUMBUF 13 | |
881adb85 | 135 | |
59d8053f DH |
136 | /* |
137 | * array.c | |
138 | */ | |
139 | extern const struct file_operations proc_tid_children_operations; | |
3174c21b | 140 | |
59d8053f DH |
141 | extern int proc_tid_stat(struct seq_file *, struct pid_namespace *, |
142 | struct pid *, struct task_struct *); | |
143 | extern int proc_tgid_stat(struct seq_file *, struct pid_namespace *, | |
144 | struct pid *, struct task_struct *); | |
145 | extern int proc_pid_status(struct seq_file *, struct pid_namespace *, | |
146 | struct pid *, struct task_struct *); | |
147 | extern int proc_pid_statm(struct seq_file *, struct pid_namespace *, | |
148 | struct pid *, struct task_struct *); | |
149 | ||
150 | /* | |
151 | * base.c | |
152 | */ | |
153 | extern const struct dentry_operations pid_dentry_operations; | |
a528d35e | 154 | extern int pid_getattr(const struct path *, struct kstat *, u32, unsigned int); |
59d8053f | 155 | extern int proc_setattr(struct dentry *, struct iattr *); |
db978da8 | 156 | extern struct inode *proc_pid_make_inode(struct super_block *, struct task_struct *, umode_t); |
59d8053f DH |
157 | extern int pid_revalidate(struct dentry *, unsigned int); |
158 | extern int pid_delete_dentry(const struct dentry *); | |
f0c3b509 | 159 | extern int proc_pid_readdir(struct file *, struct dir_context *); |
59d8053f DH |
160 | extern struct dentry *proc_pid_lookup(struct inode *, struct dentry *, unsigned int); |
161 | extern loff_t mem_lseek(struct file *, loff_t, int); | |
866ad9a7 | 162 | |
59d8053f | 163 | /* Lookups */ |
c52a47ac | 164 | typedef int instantiate_t(struct inode *, struct dentry *, |
59d8053f | 165 | struct task_struct *, const void *); |
f0c3b509 | 166 | extern bool proc_fill_cache(struct file *, struct dir_context *, const char *, int, |
59d8053f | 167 | instantiate_t, struct task_struct *, const void *); |
3174c21b | 168 | |
59d8053f DH |
169 | /* |
170 | * generic.c | |
171 | */ | |
59d8053f DH |
172 | extern struct dentry *proc_lookup(struct inode *, struct dentry *, unsigned int); |
173 | extern struct dentry *proc_lookup_de(struct proc_dir_entry *, struct inode *, | |
174 | struct dentry *); | |
f0c3b509 AV |
175 | extern int proc_readdir(struct file *, struct dir_context *); |
176 | extern int proc_readdir_de(struct proc_dir_entry *, struct file *, struct dir_context *); | |
3174c21b | 177 | |
135d5655 AD |
178 | static inline struct proc_dir_entry *pde_get(struct proc_dir_entry *pde) |
179 | { | |
180 | atomic_inc(&pde->count); | |
181 | return pde; | |
182 | } | |
59d8053f | 183 | extern void pde_put(struct proc_dir_entry *); |
3174c21b | 184 | |
eb6d38d5 EB |
185 | static inline bool is_empty_pde(const struct proc_dir_entry *pde) |
186 | { | |
187 | return S_ISDIR(pde->mode) && !pde->proc_iops; | |
188 | } | |
eb6d38d5 | 189 | |
3174c21b | 190 | /* |
59d8053f | 191 | * inode.c |
3174c21b | 192 | */ |
59d8053f DH |
193 | struct pde_opener { |
194 | struct file *file; | |
195 | struct list_head lh; | |
f5887c71 | 196 | bool closing; |
59d8053f DH |
197 | struct completion *c; |
198 | }; | |
7e0e953b | 199 | extern const struct inode_operations proc_link_inode_operations; |
6b4e306a | 200 | |
59d8053f | 201 | extern const struct inode_operations proc_pid_link_inode_operations; |
6b4e306a | 202 | |
59d8053f | 203 | extern void proc_init_inodecache(void); |
1270dd8d | 204 | void set_proc_pid_nlink(void); |
59d8053f | 205 | extern struct inode *proc_get_inode(struct super_block *, struct proc_dir_entry *); |
e94591d0 | 206 | extern int proc_fill_super(struct super_block *, void *data, int flags); |
59d8053f | 207 | extern void proc_entry_rundown(struct proc_dir_entry *); |
6b4e306a | 208 | |
59d8053f DH |
209 | /* |
210 | * proc_namespaces.c | |
211 | */ | |
6b4e306a EB |
212 | extern const struct inode_operations proc_ns_dir_inode_operations; |
213 | extern const struct file_operations proc_ns_dir_operations; | |
214 | ||
59d8053f DH |
215 | /* |
216 | * proc_net.c | |
217 | */ | |
218 | extern const struct file_operations proc_net_operations; | |
219 | extern const struct inode_operations proc_net_inode_operations; | |
220 | ||
221 | #ifdef CONFIG_NET | |
222 | extern int proc_net_init(void); | |
223 | #else | |
224 | static inline int proc_net_init(void) { return 0; } | |
225 | #endif | |
226 | ||
227 | /* | |
228 | * proc_self.c | |
229 | */ | |
021ada7d | 230 | extern int proc_setup_self(struct super_block *); |
34db8aaf | 231 | |
0097875b EB |
232 | /* |
233 | * proc_thread_self.c | |
234 | */ | |
235 | extern int proc_setup_thread_self(struct super_block *); | |
236 | extern void proc_thread_self_init(void); | |
237 | ||
34db8aaf | 238 | /* |
59d8053f | 239 | * proc_sysctl.c |
34db8aaf | 240 | */ |
59d8053f DH |
241 | #ifdef CONFIG_PROC_SYSCTL |
242 | extern int proc_sys_init(void); | |
d6cffbbe KK |
243 | extern void proc_sys_evict_inode(struct inode *inode, |
244 | struct ctl_table_header *head); | |
59d8053f DH |
245 | #else |
246 | static inline void proc_sys_init(void) { } | |
d6cffbbe KK |
247 | static inline void proc_sys_evict_inode(struct inode *inode, |
248 | struct ctl_table_header *head) { } | |
59d8053f | 249 | #endif |
34db8aaf DH |
250 | |
251 | /* | |
252 | * proc_tty.c | |
253 | */ | |
254 | #ifdef CONFIG_TTY | |
255 | extern void proc_tty_init(void); | |
256 | #else | |
257 | static inline void proc_tty_init(void) {} | |
258 | #endif | |
59d8053f DH |
259 | |
260 | /* | |
261 | * root.c | |
262 | */ | |
263 | extern struct proc_dir_entry proc_root; | |
e94591d0 | 264 | extern int proc_parse_options(char *options, struct pid_namespace *pid); |
59d8053f DH |
265 | |
266 | extern void proc_self_init(void); | |
267 | extern int proc_remount(struct super_block *, int *, char *); | |
268 | ||
269 | /* | |
270 | * task_[no]mmu.c | |
271 | */ | |
272 | struct proc_maps_private { | |
2c03376d | 273 | struct inode *inode; |
59d8053f | 274 | struct task_struct *task; |
29a40ace | 275 | struct mm_struct *mm; |
59d8053f DH |
276 | #ifdef CONFIG_MMU |
277 | struct vm_area_struct *tail_vma; | |
278 | #endif | |
279 | #ifdef CONFIG_NUMA | |
280 | struct mempolicy *task_mempolicy; | |
281 | #endif | |
3859a271 | 282 | } __randomize_layout; |
59d8053f | 283 | |
5381e169 ON |
284 | struct mm_struct *proc_mem_open(struct inode *inode, unsigned int mode); |
285 | ||
59d8053f DH |
286 | extern const struct file_operations proc_pid_maps_operations; |
287 | extern const struct file_operations proc_tid_maps_operations; | |
288 | extern const struct file_operations proc_pid_numa_maps_operations; | |
289 | extern const struct file_operations proc_tid_numa_maps_operations; | |
290 | extern const struct file_operations proc_pid_smaps_operations; | |
291 | extern const struct file_operations proc_tid_smaps_operations; | |
292 | extern const struct file_operations proc_clear_refs_operations; | |
293 | extern const struct file_operations proc_pagemap_operations; | |
294 | ||
295 | extern unsigned long task_vsize(struct mm_struct *); | |
296 | extern unsigned long task_statm(struct mm_struct *, | |
297 | unsigned long *, unsigned long *, | |
298 | unsigned long *, unsigned long *); | |
299 | extern void task_mem(struct seq_file *, struct mm_struct *); |