4 #include <linux/init.h>
5 #include <linux/sysctl.h>
6 #include <linux/poll.h>
7 #include <linux/proc_fs.h>
8 #include <linux/security.h>
9 #include <linux/namei.h>
12 static const struct dentry_operations proc_sys_dentry_operations
;
13 static const struct file_operations proc_sys_file_operations
;
14 static const struct inode_operations proc_sys_inode_operations
;
15 static const struct file_operations proc_sys_dir_file_operations
;
16 static const struct inode_operations proc_sys_dir_operations
;
18 void proc_sys_poll_notify(struct ctl_table_poll
*poll
)
23 atomic_inc(&poll
->event
);
24 wake_up_interruptible(&poll
->wait
);
27 static struct inode
*proc_sys_make_inode(struct super_block
*sb
,
28 struct ctl_table_header
*head
, struct ctl_table
*table
)
31 struct proc_inode
*ei
;
33 inode
= new_inode(sb
);
37 inode
->i_ino
= get_next_ino();
39 sysctl_head_get(head
);
42 ei
->sysctl_entry
= table
;
44 inode
->i_mtime
= inode
->i_atime
= inode
->i_ctime
= CURRENT_TIME
;
45 inode
->i_mode
= table
->mode
;
47 inode
->i_mode
|= S_IFREG
;
48 inode
->i_op
= &proc_sys_inode_operations
;
49 inode
->i_fop
= &proc_sys_file_operations
;
51 inode
->i_mode
|= S_IFDIR
;
53 inode
->i_op
= &proc_sys_dir_operations
;
54 inode
->i_fop
= &proc_sys_dir_file_operations
;
60 static struct ctl_table
*find_in_table(struct ctl_table
*p
, struct qstr
*name
)
63 for ( ; p
->procname
; p
++) {
68 len
= strlen(p
->procname
);
72 if (memcmp(p
->procname
, name
->name
, len
) != 0)
81 static struct ctl_table_header
*grab_header(struct inode
*inode
)
83 if (PROC_I(inode
)->sysctl
)
84 return sysctl_head_grab(PROC_I(inode
)->sysctl
);
86 return sysctl_head_next(NULL
);
89 static struct dentry
*proc_sys_lookup(struct inode
*dir
, struct dentry
*dentry
,
92 struct ctl_table_header
*head
= grab_header(dir
);
93 struct ctl_table
*table
= PROC_I(dir
)->sysctl_entry
;
94 struct ctl_table_header
*h
= NULL
;
95 struct qstr
*name
= &dentry
->d_name
;
98 struct dentry
*err
= ERR_PTR(-ENOENT
);
101 return ERR_CAST(head
);
103 if (table
&& !table
->child
) {
108 table
= table
? table
->child
: head
->ctl_table
;
110 p
= find_in_table(table
, name
);
112 for (h
= sysctl_head_next(NULL
); h
; h
= sysctl_head_next(h
)) {
113 if (h
->attached_to
!= table
)
115 p
= find_in_table(h
->attached_by
, name
);
124 err
= ERR_PTR(-ENOMEM
);
125 inode
= proc_sys_make_inode(dir
->i_sb
, h
? h
: head
, p
);
127 sysctl_head_finish(h
);
133 d_set_d_op(dentry
, &proc_sys_dentry_operations
);
134 d_add(dentry
, inode
);
137 sysctl_head_finish(head
);
141 static ssize_t
proc_sys_call_handler(struct file
*filp
, void __user
*buf
,
142 size_t count
, loff_t
*ppos
, int write
)
144 struct inode
*inode
= filp
->f_path
.dentry
->d_inode
;
145 struct ctl_table_header
*head
= grab_header(inode
);
146 struct ctl_table
*table
= PROC_I(inode
)->sysctl_entry
;
151 return PTR_ERR(head
);
154 * At this point we know that the sysctl was not unregistered
155 * and won't be until we finish.
158 if (sysctl_perm(head
->root
, table
, write
? MAY_WRITE
: MAY_READ
))
161 /* if that can happen at all, it should be -EINVAL, not -EISDIR */
163 if (!table
->proc_handler
)
166 /* careful: calling conventions are nasty here */
168 error
= table
->proc_handler(table
, write
, buf
, &res
, ppos
);
172 sysctl_head_finish(head
);
177 static ssize_t
proc_sys_read(struct file
*filp
, char __user
*buf
,
178 size_t count
, loff_t
*ppos
)
180 return proc_sys_call_handler(filp
, (void __user
*)buf
, count
, ppos
, 0);
183 static ssize_t
proc_sys_write(struct file
*filp
, const char __user
*buf
,
184 size_t count
, loff_t
*ppos
)
186 return proc_sys_call_handler(filp
, (void __user
*)buf
, count
, ppos
, 1);
189 static int proc_sys_open(struct inode
*inode
, struct file
*filp
)
191 struct ctl_table_header
*head
= grab_header(inode
);
192 struct ctl_table
*table
= PROC_I(inode
)->sysctl_entry
;
194 /* sysctl was unregistered */
196 return PTR_ERR(head
);
199 filp
->private_data
= proc_sys_poll_event(table
->poll
);
201 sysctl_head_finish(head
);
206 static unsigned int proc_sys_poll(struct file
*filp
, poll_table
*wait
)
208 struct inode
*inode
= filp
->f_path
.dentry
->d_inode
;
209 struct ctl_table_header
*head
= grab_header(inode
);
210 struct ctl_table
*table
= PROC_I(inode
)->sysctl_entry
;
211 unsigned int ret
= DEFAULT_POLLMASK
;
214 /* sysctl was unregistered */
216 return POLLERR
| POLLHUP
;
218 if (!table
->proc_handler
)
224 event
= (unsigned long)filp
->private_data
;
225 poll_wait(filp
, &table
->poll
->wait
, wait
);
227 if (event
!= atomic_read(&table
->poll
->event
)) {
228 filp
->private_data
= proc_sys_poll_event(table
->poll
);
229 ret
= POLLIN
| POLLRDNORM
| POLLERR
| POLLPRI
;
233 sysctl_head_finish(head
);
238 static int proc_sys_fill_cache(struct file
*filp
, void *dirent
,
240 struct ctl_table_header
*head
,
241 struct ctl_table
*table
)
243 struct dentry
*child
, *dir
= filp
->f_path
.dentry
;
247 unsigned type
= DT_UNKNOWN
;
249 qname
.name
= table
->procname
;
250 qname
.len
= strlen(table
->procname
);
251 qname
.hash
= full_name_hash(qname
.name
, qname
.len
);
253 child
= d_lookup(dir
, &qname
);
255 child
= d_alloc(dir
, &qname
);
257 inode
= proc_sys_make_inode(dir
->d_sb
, head
, table
);
262 d_set_d_op(child
, &proc_sys_dentry_operations
);
269 inode
= child
->d_inode
;
271 type
= inode
->i_mode
>> 12;
273 return !!filldir(dirent
, qname
.name
, qname
.len
, filp
->f_pos
, ino
, type
);
276 static int scan(struct ctl_table_header
*head
, ctl_table
*table
,
277 unsigned long *pos
, struct file
*file
,
278 void *dirent
, filldir_t filldir
)
281 for (; table
->procname
; table
++, (*pos
)++) {
284 /* Can't do anything without a proc name */
285 if (!table
->procname
)
288 if (*pos
< file
->f_pos
)
291 res
= proc_sys_fill_cache(file
, dirent
, filldir
, head
, table
);
295 file
->f_pos
= *pos
+ 1;
300 static int proc_sys_readdir(struct file
*filp
, void *dirent
, filldir_t filldir
)
302 struct dentry
*dentry
= filp
->f_path
.dentry
;
303 struct inode
*inode
= dentry
->d_inode
;
304 struct ctl_table_header
*head
= grab_header(inode
);
305 struct ctl_table
*table
= PROC_I(inode
)->sysctl_entry
;
306 struct ctl_table_header
*h
= NULL
;
311 return PTR_ERR(head
);
313 if (table
&& !table
->child
) {
318 table
= table
? table
->child
: head
->ctl_table
;
321 /* Avoid a switch here: arm builds fail with missing __cmpdi2 */
322 if (filp
->f_pos
== 0) {
323 if (filldir(dirent
, ".", 1, filp
->f_pos
,
324 inode
->i_ino
, DT_DIR
) < 0)
328 if (filp
->f_pos
== 1) {
329 if (filldir(dirent
, "..", 2, filp
->f_pos
,
330 parent_ino(dentry
), DT_DIR
) < 0)
336 ret
= scan(head
, table
, &pos
, filp
, dirent
, filldir
);
340 for (h
= sysctl_head_next(NULL
); h
; h
= sysctl_head_next(h
)) {
341 if (h
->attached_to
!= table
)
343 ret
= scan(h
, h
->attached_by
, &pos
, filp
, dirent
, filldir
);
345 sysctl_head_finish(h
);
351 sysctl_head_finish(head
);
355 static int proc_sys_permission(struct inode
*inode
, int mask
)
358 * sysctl entries that are not writeable,
359 * are _NOT_ writeable, capabilities or not.
361 struct ctl_table_header
*head
;
362 struct ctl_table
*table
;
365 /* Executable files are not allowed under /proc/sys/ */
366 if ((mask
& MAY_EXEC
) && S_ISREG(inode
->i_mode
))
369 head
= grab_header(inode
);
371 return PTR_ERR(head
);
373 table
= PROC_I(inode
)->sysctl_entry
;
374 if (!table
) /* global root - r-xr-xr-x */
375 error
= mask
& MAY_WRITE
? -EACCES
: 0;
376 else /* Use the permissions on the sysctl table entry */
377 error
= sysctl_perm(head
->root
, table
, mask
& ~MAY_NOT_BLOCK
);
379 sysctl_head_finish(head
);
383 static int proc_sys_setattr(struct dentry
*dentry
, struct iattr
*attr
)
385 struct inode
*inode
= dentry
->d_inode
;
388 if (attr
->ia_valid
& (ATTR_MODE
| ATTR_UID
| ATTR_GID
))
391 error
= inode_change_ok(inode
, attr
);
395 if ((attr
->ia_valid
& ATTR_SIZE
) &&
396 attr
->ia_size
!= i_size_read(inode
)) {
397 error
= vmtruncate(inode
, attr
->ia_size
);
402 setattr_copy(inode
, attr
);
403 mark_inode_dirty(inode
);
407 static int proc_sys_getattr(struct vfsmount
*mnt
, struct dentry
*dentry
, struct kstat
*stat
)
409 struct inode
*inode
= dentry
->d_inode
;
410 struct ctl_table_header
*head
= grab_header(inode
);
411 struct ctl_table
*table
= PROC_I(inode
)->sysctl_entry
;
414 return PTR_ERR(head
);
416 generic_fillattr(inode
, stat
);
418 stat
->mode
= (stat
->mode
& S_IFMT
) | table
->mode
;
420 sysctl_head_finish(head
);
424 static const struct file_operations proc_sys_file_operations
= {
425 .open
= proc_sys_open
,
426 .poll
= proc_sys_poll
,
427 .read
= proc_sys_read
,
428 .write
= proc_sys_write
,
429 .llseek
= default_llseek
,
432 static const struct file_operations proc_sys_dir_file_operations
= {
433 .read
= generic_read_dir
,
434 .readdir
= proc_sys_readdir
,
435 .llseek
= generic_file_llseek
,
438 static const struct inode_operations proc_sys_inode_operations
= {
439 .permission
= proc_sys_permission
,
440 .setattr
= proc_sys_setattr
,
441 .getattr
= proc_sys_getattr
,
444 static const struct inode_operations proc_sys_dir_operations
= {
445 .lookup
= proc_sys_lookup
,
446 .permission
= proc_sys_permission
,
447 .setattr
= proc_sys_setattr
,
448 .getattr
= proc_sys_getattr
,
451 static int proc_sys_revalidate(struct dentry
*dentry
, struct nameidata
*nd
)
453 if (nd
->flags
& LOOKUP_RCU
)
455 return !PROC_I(dentry
->d_inode
)->sysctl
->unregistering
;
458 static int proc_sys_delete(const struct dentry
*dentry
)
460 return !!PROC_I(dentry
->d_inode
)->sysctl
->unregistering
;
463 static int proc_sys_compare(const struct dentry
*parent
,
464 const struct inode
*pinode
,
465 const struct dentry
*dentry
, const struct inode
*inode
,
466 unsigned int len
, const char *str
, const struct qstr
*name
)
468 struct ctl_table_header
*head
;
469 /* Although proc doesn't have negative dentries, rcu-walk means
470 * that inode here can be NULL */
471 /* AV: can it, indeed? */
474 if (name
->len
!= len
)
476 if (memcmp(name
->name
, str
, len
))
478 head
= rcu_dereference(PROC_I(inode
)->sysctl
);
479 return !head
|| !sysctl_is_seen(head
);
482 static const struct dentry_operations proc_sys_dentry_operations
= {
483 .d_revalidate
= proc_sys_revalidate
,
484 .d_delete
= proc_sys_delete
,
485 .d_compare
= proc_sys_compare
,
488 int __init
proc_sys_init(void)
490 struct proc_dir_entry
*proc_sys_root
;
492 proc_sys_root
= proc_mkdir("sys", NULL
);
493 proc_sys_root
->proc_iops
= &proc_sys_dir_operations
;
494 proc_sys_root
->proc_fops
= &proc_sys_dir_file_operations
;
495 proc_sys_root
->nlink
= 0;