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