aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2006-10-02 05:18:48 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-10-02 10:57:24 -0400
commit801199ce805a2412bbcd9bfe213092ec656013dd (patch)
tree18e465cd852cc8a5105fea4e08b6a63503ee8077 /fs/proc
parentc5f2420a063fcc5a4cd6610c3ef6934827853001 (diff)
[PATCH] proc: Make the generation of the self symlink table driven
This patch generalizes the concept of files in /proc that are related to processes but live in the root directory of /proc Ideally this would reuse infrastructure from the rest of the process specific parts of proc but unfortunately security_task_to_inode must not be called on files that are not strictly per process. security_task_to_inode really needs to be reexamined as the security label can change in important places that we are not currently catching, but I'm not certain that simplifies this problem. By at least matching the structure of the rest of proc we get more idiom reuse and it becomes easier to spot problems in the way things are put together. Later things like /proc/mounts are likely to be moved into proc_base as well. If union mounts are ever supported we may be able to make /proc a union mount, and properly split it into 2 filesystems. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/proc')
-rw-r--r--fs/proc/base.c133
1 files changed, 111 insertions, 22 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 6d00ccc48c1c..7832efbd43a6 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -1674,6 +1674,108 @@ static struct inode_operations proc_self_inode_operations = {
1674}; 1674};
1675 1675
1676/* 1676/*
1677 * proc base
1678 *
1679 * These are the directory entries in the root directory of /proc
1680 * that properly belong to the /proc filesystem, as they describe
1681 * describe something that is process related.
1682 */
1683static struct pid_entry proc_base_stuff[] = {
1684 NOD(PROC_TGID_INO, "self", S_IFLNK|S_IRWXUGO,
1685 &proc_self_inode_operations, NULL, {}),
1686 {}
1687};
1688
1689/*
1690 * Exceptional case: normally we are not allowed to unhash a busy
1691 * directory. In this case, however, we can do it - no aliasing problems
1692 * due to the way we treat inodes.
1693 */
1694static int proc_base_revalidate(struct dentry *dentry, struct nameidata *nd)
1695{
1696 struct inode *inode = dentry->d_inode;
1697 struct task_struct *task = get_proc_task(inode);
1698 if (task) {
1699 put_task_struct(task);
1700 return 1;
1701 }
1702 d_drop(dentry);
1703 return 0;
1704}
1705
1706static struct dentry_operations proc_base_dentry_operations =
1707{
1708 .d_revalidate = proc_base_revalidate,
1709 .d_delete = pid_delete_dentry,
1710};
1711
1712static struct dentry *proc_base_lookup(struct inode *dir, struct dentry *dentry)
1713{
1714 struct inode *inode;
1715 struct dentry *error;
1716 struct task_struct *task = get_proc_task(dir);
1717 struct pid_entry *p;
1718 struct proc_inode *ei;
1719
1720 error = ERR_PTR(-ENOENT);
1721 inode = NULL;
1722
1723 if (!task)
1724 goto out_no_task;
1725
1726 /* Lookup the directory entry */
1727 for (p = proc_base_stuff; p->name; p++) {
1728 if (p->len != dentry->d_name.len)
1729 continue;
1730 if (!memcmp(dentry->d_name.name, p->name, p->len))
1731 break;
1732 }
1733 if (!p->name)
1734 goto out;
1735
1736 /* Allocate the inode */
1737 error = ERR_PTR(-ENOMEM);
1738 inode = new_inode(dir->i_sb);
1739 if (!inode)
1740 goto out;
1741
1742 /* Initialize the inode */
1743 ei = PROC_I(inode);
1744 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
1745 inode->i_ino = fake_ino(0, p->type);
1746
1747 /*
1748 * grab the reference to the task.
1749 */
1750 ei->pid = get_pid(task_pid(task));
1751 if (!ei->pid)
1752 goto out_iput;
1753
1754 inode->i_uid = 0;
1755 inode->i_gid = 0;
1756 inode->i_mode = p->mode;
1757 if (S_ISDIR(inode->i_mode))
1758 inode->i_nlink = 2;
1759 if (S_ISLNK(inode->i_mode))
1760 inode->i_size = 64;
1761 if (p->iop)
1762 inode->i_op = p->iop;
1763 if (p->fop)
1764 inode->i_fop = p->fop;
1765 ei->op = p->op;
1766 dentry->d_op = &proc_base_dentry_operations;
1767 d_add(dentry, inode);
1768 error = NULL;
1769out:
1770 put_task_struct(task);
1771out_no_task:
1772 return error;
1773out_iput:
1774 iput(inode);
1775 goto out;
1776}
1777
1778/*
1677 * Thread groups 1779 * Thread groups
1678 */ 1780 */
1679static struct file_operations proc_task_operations; 1781static struct file_operations proc_task_operations;
@@ -1819,24 +1921,12 @@ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct
1819 struct dentry *result = ERR_PTR(-ENOENT); 1921 struct dentry *result = ERR_PTR(-ENOENT);
1820 struct task_struct *task; 1922 struct task_struct *task;
1821 struct inode *inode; 1923 struct inode *inode;
1822 struct proc_inode *ei;
1823 unsigned tgid; 1924 unsigned tgid;
1824 1925
1825 if (dentry->d_name.len == 4 && !memcmp(dentry->d_name.name,"self",4)) { 1926 result = proc_base_lookup(dir, dentry);
1826 inode = new_inode(dir->i_sb); 1927 if (!IS_ERR(result) || PTR_ERR(result) != -ENOENT)
1827 if (!inode) 1928 goto out;
1828 return ERR_PTR(-ENOMEM); 1929
1829 ei = PROC_I(inode);
1830 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
1831 inode->i_ino = fake_ino(0, PROC_TGID_INO);
1832 ei->pde = NULL;
1833 inode->i_mode = S_IFLNK|S_IRWXUGO;
1834 inode->i_uid = inode->i_gid = 0;
1835 inode->i_size = 64;
1836 inode->i_op = &proc_self_inode_operations;
1837 d_add(dentry, inode);
1838 return NULL;
1839 }
1840 tgid = name_to_int(dentry); 1930 tgid = name_to_int(dentry);
1841 if (tgid == ~0U) 1931 if (tgid == ~0U)
1842 goto out; 1932 goto out;
@@ -1922,12 +2012,11 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir)
1922 struct task_struct *task; 2012 struct task_struct *task;
1923 int tgid; 2013 int tgid;
1924 2014
1925 if (!nr) { 2015 for (; nr < (ARRAY_SIZE(proc_base_stuff) - 1); filp->f_pos++, nr++) {
1926 ino_t ino = fake_ino(0,PROC_TGID_INO); 2016 struct pid_entry *p = &proc_base_stuff[nr];
1927 if (filldir(dirent, "self", 4, filp->f_pos, ino, DT_LNK) < 0) 2017 if (filldir(dirent, p->name, p->len, filp->f_pos,
1928 return 0; 2018 fake_ino(0, p->type), p->mode >> 12) < 0)
1929 filp->f_pos++; 2019 goto out;
1930 nr++;
1931 } 2020 }
1932 2021
1933 tgid = filp->f_pos - TGID_OFFSET; 2022 tgid = filp->f_pos - TGID_OFFSET;