]>
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 | |
f77c8014 AV |
60 | struct proc_ns { |
61 | struct ns_common *ns; | |
62 | const struct proc_ns_operations *ns_ops; | |
63 | }; | |
64 | ||
59d8053f | 65 | struct proc_inode { |
f2beb798 | 66 | struct pid *pid; |
59d8053f DH |
67 | int fd; |
68 | union proc_op op; | |
69 | struct proc_dir_entry *pde; | |
70 | struct ctl_table_header *sysctl; | |
71 | struct ctl_table *sysctl_entry; | |
72 | struct proc_ns ns; | |
73 | struct inode vfs_inode; | |
f2beb798 SW |
74 | }; |
75 | ||
c30480b9 DH |
76 | /* |
77 | * General functions | |
78 | */ | |
79 | static inline struct proc_inode *PROC_I(const struct inode *inode) | |
80 | { | |
81 | return container_of(inode, struct proc_inode, vfs_inode); | |
82 | } | |
83 | ||
84 | static inline struct proc_dir_entry *PDE(const struct inode *inode) | |
85 | { | |
86 | return PROC_I(inode)->pde; | |
87 | } | |
88 | ||
89 | static inline void *__PDE_DATA(const struct inode *inode) | |
90 | { | |
91 | return PDE(inode)->data; | |
92 | } | |
fee781e6 | 93 | |
13b41b09 | 94 | static inline struct pid *proc_pid(struct inode *inode) |
99f89551 | 95 | { |
13b41b09 | 96 | return PROC_I(inode)->pid; |
99f89551 EB |
97 | } |
98 | ||
99 | static inline struct task_struct *get_proc_task(struct inode *inode) | |
1da177e4 | 100 | { |
13b41b09 | 101 | return get_pid_task(proc_pid(inode), PIDTYPE_PID); |
1da177e4 LT |
102 | } |
103 | ||
faf60af1 CG |
104 | static inline int task_dumpable(struct task_struct *task) |
105 | { | |
106 | int dumpable = 0; | |
107 | struct mm_struct *mm; | |
108 | ||
109 | task_lock(task); | |
110 | mm = task->mm; | |
111 | if (mm) | |
112 | dumpable = get_dumpable(mm); | |
113 | task_unlock(task); | |
e579d2c2 | 114 | if (dumpable == SUID_DUMP_USER) |
faf60af1 CG |
115 | return 1; |
116 | return 0; | |
117 | } | |
118 | ||
dbcdb504 | 119 | static inline unsigned name_to_int(const struct qstr *qstr) |
faf60af1 | 120 | { |
dbcdb504 AD |
121 | const char *name = qstr->name; |
122 | int len = qstr->len; | |
faf60af1 CG |
123 | unsigned n = 0; |
124 | ||
125 | if (len > 1 && *name == '0') | |
126 | goto out; | |
127 | while (len-- > 0) { | |
128 | unsigned c = *name++ - '0'; | |
129 | if (c > 9) | |
130 | goto out; | |
131 | if (n >= (~0U-9)/10) | |
132 | goto out; | |
133 | n *= 10; | |
134 | n += c; | |
135 | } | |
136 | return n; | |
137 | out: | |
138 | return ~0U; | |
139 | } | |
140 | ||
1dd704b6 | 141 | /* |
59d8053f | 142 | * Offset of the first process in the /proc root directory.. |
1dd704b6 | 143 | */ |
59d8053f | 144 | #define FIRST_PROCESS_ENTRY 256 |
1dd704b6 | 145 | |
59d8053f DH |
146 | /* Worst case buffer size needed for holding an integer. */ |
147 | #define PROC_NUMBUF 13 | |
881adb85 | 148 | |
59d8053f DH |
149 | /* |
150 | * array.c | |
151 | */ | |
152 | extern const struct file_operations proc_tid_children_operations; | |
3174c21b | 153 | |
59d8053f DH |
154 | extern int proc_tid_stat(struct seq_file *, struct pid_namespace *, |
155 | struct pid *, struct task_struct *); | |
156 | extern int proc_tgid_stat(struct seq_file *, struct pid_namespace *, | |
157 | struct pid *, struct task_struct *); | |
158 | extern int proc_pid_status(struct seq_file *, struct pid_namespace *, | |
159 | struct pid *, struct task_struct *); | |
160 | extern int proc_pid_statm(struct seq_file *, struct pid_namespace *, | |
161 | struct pid *, struct task_struct *); | |
162 | ||
163 | /* | |
164 | * base.c | |
165 | */ | |
166 | extern const struct dentry_operations pid_dentry_operations; | |
167 | extern int pid_getattr(struct vfsmount *, struct dentry *, struct kstat *); | |
168 | extern int proc_setattr(struct dentry *, struct iattr *); | |
169 | extern struct inode *proc_pid_make_inode(struct super_block *, struct task_struct *); | |
170 | extern int pid_revalidate(struct dentry *, unsigned int); | |
171 | extern int pid_delete_dentry(const struct dentry *); | |
f0c3b509 | 172 | extern int proc_pid_readdir(struct file *, struct dir_context *); |
59d8053f DH |
173 | extern struct dentry *proc_pid_lookup(struct inode *, struct dentry *, unsigned int); |
174 | extern loff_t mem_lseek(struct file *, loff_t, int); | |
866ad9a7 | 175 | |
59d8053f | 176 | /* Lookups */ |
c52a47ac | 177 | typedef int instantiate_t(struct inode *, struct dentry *, |
59d8053f | 178 | struct task_struct *, const void *); |
f0c3b509 | 179 | extern bool proc_fill_cache(struct file *, struct dir_context *, const char *, int, |
59d8053f | 180 | instantiate_t, struct task_struct *, const void *); |
3174c21b | 181 | |
59d8053f DH |
182 | /* |
183 | * generic.c | |
184 | */ | |
59d8053f DH |
185 | extern struct dentry *proc_lookup(struct inode *, struct dentry *, unsigned int); |
186 | extern struct dentry *proc_lookup_de(struct proc_dir_entry *, struct inode *, | |
187 | struct dentry *); | |
f0c3b509 AV |
188 | extern int proc_readdir(struct file *, struct dir_context *); |
189 | extern int proc_readdir_de(struct proc_dir_entry *, struct file *, struct dir_context *); | |
3174c21b | 190 | |
135d5655 AD |
191 | static inline struct proc_dir_entry *pde_get(struct proc_dir_entry *pde) |
192 | { | |
193 | atomic_inc(&pde->count); | |
194 | return pde; | |
195 | } | |
59d8053f | 196 | extern void pde_put(struct proc_dir_entry *); |
3174c21b AV |
197 | |
198 | /* | |
59d8053f | 199 | * inode.c |
3174c21b | 200 | */ |
59d8053f DH |
201 | struct pde_opener { |
202 | struct file *file; | |
203 | struct list_head lh; | |
204 | int closing; | |
205 | struct completion *c; | |
206 | }; | |
6b4e306a | 207 | |
59d8053f | 208 | extern const struct inode_operations proc_pid_link_inode_operations; |
6b4e306a | 209 | |
59d8053f DH |
210 | extern void proc_init_inodecache(void); |
211 | extern struct inode *proc_get_inode(struct super_block *, struct proc_dir_entry *); | |
212 | extern int proc_fill_super(struct super_block *); | |
213 | extern void proc_entry_rundown(struct proc_dir_entry *); | |
6b4e306a | 214 | |
59d8053f DH |
215 | /* |
216 | * proc_namespaces.c | |
217 | */ | |
6b4e306a EB |
218 | extern const struct inode_operations proc_ns_dir_inode_operations; |
219 | extern const struct file_operations proc_ns_dir_operations; | |
220 | ||
59d8053f DH |
221 | /* |
222 | * proc_net.c | |
223 | */ | |
224 | extern const struct file_operations proc_net_operations; | |
225 | extern const struct inode_operations proc_net_inode_operations; | |
226 | ||
227 | #ifdef CONFIG_NET | |
228 | extern int proc_net_init(void); | |
229 | #else | |
230 | static inline int proc_net_init(void) { return 0; } | |
231 | #endif | |
232 | ||
233 | /* | |
234 | * proc_self.c | |
235 | */ | |
021ada7d | 236 | extern int proc_setup_self(struct super_block *); |
34db8aaf | 237 | |
0097875b EB |
238 | /* |
239 | * proc_thread_self.c | |
240 | */ | |
241 | extern int proc_setup_thread_self(struct super_block *); | |
242 | extern void proc_thread_self_init(void); | |
243 | ||
34db8aaf | 244 | /* |
59d8053f | 245 | * proc_sysctl.c |
34db8aaf | 246 | */ |
59d8053f DH |
247 | #ifdef CONFIG_PROC_SYSCTL |
248 | extern int proc_sys_init(void); | |
249 | extern void sysctl_head_put(struct ctl_table_header *); | |
250 | #else | |
251 | static inline void proc_sys_init(void) { } | |
252 | static inline void sysctl_head_put(struct ctl_table_header *head) { } | |
253 | #endif | |
34db8aaf DH |
254 | |
255 | /* | |
256 | * proc_tty.c | |
257 | */ | |
258 | #ifdef CONFIG_TTY | |
259 | extern void proc_tty_init(void); | |
260 | #else | |
261 | static inline void proc_tty_init(void) {} | |
262 | #endif | |
59d8053f DH |
263 | |
264 | /* | |
265 | * root.c | |
266 | */ | |
267 | extern struct proc_dir_entry proc_root; | |
268 | ||
269 | extern void proc_self_init(void); | |
270 | extern int proc_remount(struct super_block *, int *, char *); | |
271 | ||
272 | /* | |
273 | * task_[no]mmu.c | |
274 | */ | |
275 | struct proc_maps_private { | |
2c03376d | 276 | struct inode *inode; |
59d8053f | 277 | struct task_struct *task; |
29a40ace | 278 | struct mm_struct *mm; |
59d8053f DH |
279 | #ifdef CONFIG_MMU |
280 | struct vm_area_struct *tail_vma; | |
281 | #endif | |
282 | #ifdef CONFIG_NUMA | |
283 | struct mempolicy *task_mempolicy; | |
284 | #endif | |
285 | }; | |
286 | ||
5381e169 ON |
287 | struct mm_struct *proc_mem_open(struct inode *inode, unsigned int mode); |
288 | ||
59d8053f DH |
289 | extern const struct file_operations proc_pid_maps_operations; |
290 | extern const struct file_operations proc_tid_maps_operations; | |
291 | extern const struct file_operations proc_pid_numa_maps_operations; | |
292 | extern const struct file_operations proc_tid_numa_maps_operations; | |
293 | extern const struct file_operations proc_pid_smaps_operations; | |
294 | extern const struct file_operations proc_tid_smaps_operations; | |
295 | extern const struct file_operations proc_clear_refs_operations; | |
296 | extern const struct file_operations proc_pagemap_operations; | |
297 | ||
298 | extern unsigned long task_vsize(struct mm_struct *); | |
299 | extern unsigned long task_statm(struct mm_struct *, | |
300 | unsigned long *, unsigned long *, | |
301 | unsigned long *, unsigned long *); | |
302 | extern void task_mem(struct seq_file *, struct mm_struct *); |