#include <linux/mount.h>
#include <linux/tty.h>
#include <linux/devpts_fs.h>
-#include <linux/vinline.h>
-#include "xattr.h"
+#include <linux/parser.h>
+#include <linux/vs_base.h>
-#define DEVPTS_SUPER_MAGIC 0x1cd1
+
+static int devpts_permission(struct inode *inode, int mask, struct nameidata *nd)
+{
+ int ret = -EACCES;
+
+ /* devpts is xid tagged */
+ if (vx_check((xid_t)inode->i_tag, VS_WATCH_P|VS_IDENT))
+ ret = generic_permission(inode, mask, NULL);
+ return ret;
+}
+
+static struct inode_operations devpts_file_inode_operations = {
+ .permission = devpts_permission,
+};
static struct vfsmount *devpts_mnt;
static struct dentry *devpts_root;
umode_t mode;
} config = {.mode = 0600};
+enum {
+ Opt_uid, Opt_gid, Opt_mode,
+ Opt_err
+};
+
+static match_table_t tokens = {
+ {Opt_uid, "uid=%u"},
+ {Opt_gid, "gid=%u"},
+ {Opt_mode, "mode=%o"},
+ {Opt_err, NULL}
+};
+
static int devpts_remount(struct super_block *sb, int *flags, char *data)
{
- int setuid = 0;
- int setgid = 0;
- uid_t uid = 0;
- gid_t gid = 0;
- umode_t mode = 0600;
- char *this_char;
-
- this_char = NULL;
- while ((this_char = strsep(&data, ",")) != NULL) {
- int n;
- char dummy;
- if (!*this_char)
+ char *p;
+
+ config.setuid = 0;
+ config.setgid = 0;
+ config.uid = 0;
+ config.gid = 0;
+ config.mode = 0600;
+
+ while ((p = strsep(&data, ",")) != NULL) {
+ substring_t args[MAX_OPT_ARGS];
+ int token;
+ int option;
+
+ if (!*p)
continue;
- if (sscanf(this_char, "uid=%i%c", &n, &dummy) == 1) {
- setuid = 1;
- uid = n;
- } else if (sscanf(this_char, "gid=%i%c", &n, &dummy) == 1) {
- setgid = 1;
- gid = n;
- } else if (sscanf(this_char, "mode=%o%c", &n, &dummy) == 1)
- mode = n & ~S_IFMT;
- else {
- printk("devpts: called with bogus options\n");
+
+ token = match_token(p, tokens, args);
+ switch (token) {
+ case Opt_uid:
+ if (match_int(&args[0], &option))
+ return -EINVAL;
+ config.uid = option;
+ config.setuid = 1;
+ break;
+ case Opt_gid:
+ if (match_int(&args[0], &option))
+ return -EINVAL;
+ config.gid = option;
+ config.setgid = 1;
+ break;
+ case Opt_mode:
+ if (match_octal(&args[0], &option))
+ return -EINVAL;
+ config.mode = option & ~S_IFMT;
+ break;
+ default:
+ printk(KERN_ERR "devpts: called with bogus options\n");
return -EINVAL;
}
}
- config.setuid = setuid;
- config.setgid = setgid;
- config.uid = uid;
- config.gid = gid;
- config.mode = mode;
return 0;
}
+static int devpts_filter(struct dentry *de)
+{
+ /* devpts is xid tagged */
+ return vx_check((xid_t)de->d_inode->i_tag, VS_WATCH_P|VS_IDENT);
+}
+
+static int devpts_readdir(struct file * filp, void * dirent, filldir_t filldir)
+{
+ return dcache_readdir_filter(filp, dirent, filldir, devpts_filter);
+}
+
+static struct file_operations devpts_dir_operations = {
+ .open = dcache_dir_open,
+ .release = dcache_dir_close,
+ .llseek = dcache_dir_lseek,
+ .read = generic_read_dir,
+ .readdir = devpts_readdir,
+};
+
static struct super_operations devpts_sops = {
.statfs = simple_statfs,
.remount_fs = devpts_remount,
s->s_blocksize_bits = 10;
s->s_magic = DEVPTS_SUPER_MAGIC;
s->s_op = &devpts_sops;
+ s->s_time_gran = 1;
inode = new_inode(s);
if (!inode)
inode->i_ino = 1;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
inode->i_blocks = 0;
- inode->i_blksize = 1024;
inode->i_uid = inode->i_gid = 0;
inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
inode->i_op = &simple_dir_inode_operations;
- inode->i_fop = &simple_dir_operations;
+ inode->i_fop = &devpts_dir_operations;
inode->i_nlink = 2;
+ /* devpts is xid tagged */
+ inode->i_tag = (tag_t)vx_current_xid();
devpts_root = s->s_root = d_alloc_root(inode);
if (s->s_root)
return -ENOMEM;
}
-static struct super_block *devpts_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data)
+static int devpts_get_sb(struct file_system_type *fs_type,
+ int flags, const char *dev_name, void *data, struct vfsmount *mnt)
{
- return get_sb_single(fs_type, flags, data, devpts_fill_super);
+ return get_sb_single(fs_type, flags, data, devpts_fill_super, mnt);
}
static struct file_system_type devpts_fs_type = {
{
char s[12];
struct dentry *root = devpts_root;
- down(&root->d_inode->i_sem);
+ mutex_lock(&root->d_inode->i_mutex);
return lookup_one_len(s, root, sprintf(s, "%d", num));
}
-static int devpts_permission(struct inode *inode, int mask, struct nameidata *nd)
-{
- int ret = -EACCES;
-
- if (vx_check(inode->i_xid, VX_IDENT))
- ret = vfs_permission(inode, mask);
- return ret;
-}
-
-static struct inode_operations devpts_file_inode_operations = {
- .setxattr = devpts_setxattr,
- .getxattr = devpts_getxattr,
- .listxattr = devpts_listxattr,
- .removexattr = devpts_removexattr,
- .permission = devpts_permission,
-};
-
int devpts_pty_new(struct tty_struct *tty)
{
int number = tty->index;
return -ENOMEM;
inode->i_ino = number+2;
- inode->i_blksize = 1024;
inode->i_uid = config.setuid ? config.uid : current->fsuid;
inode->i_gid = config.setgid ? config.gid : current->fsgid;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
init_special_inode(inode, S_IFCHR|config.mode, device);
- inode->i_xid = vx_current_xid();
+ /* devpts is xid tagged */
+ inode->i_tag = (tag_t)vx_current_xid();
inode->i_op = &devpts_file_inode_operations;
- inode->u.generic_ip = tty;
+ inode->i_private = tty;
dentry = get_node(number);
if (!IS_ERR(dentry) && !dentry->d_inode)
d_instantiate(dentry, inode);
- up(&devpts_root->d_inode->i_sem);
+ mutex_unlock(&devpts_root->d_inode->i_mutex);
return 0;
}
struct dentry *dentry = get_node(number);
struct tty_struct *tty;
- tty = (IS_ERR(dentry) || !dentry->d_inode) ? NULL :
- dentry->d_inode->u.generic_ip;
+ tty = NULL;
+ if (!IS_ERR(dentry)) {
+ if (dentry->d_inode)
+ tty = dentry->d_inode->i_private;
+ dput(dentry);
+ }
- up(&devpts_root->d_inode->i_sem);
+ mutex_unlock(&devpts_root->d_inode->i_mutex);
return tty;
}
}
dput(dentry);
}
- up(&devpts_root->d_inode->i_sem);
+ mutex_unlock(&devpts_root->d_inode->i_mutex);
}
static int __init init_devpts_fs(void)
{
- int err = init_devpts_xattr();
- if (err)
- return err;
- err = register_filesystem(&devpts_fs_type);
+ int err = register_filesystem(&devpts_fs_type);
if (!err) {
devpts_mnt = kern_mount(&devpts_fs_type);
if (IS_ERR(devpts_mnt))
{
unregister_filesystem(&devpts_fs_type);
mntput(devpts_mnt);
- exit_devpts_xattr();
}
module_init(init_devpts_fs)