Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 125031
b: refs/heads/master
c: 1f8f1e2
h: refs/heads/master
i:
  125029: e21eb27
  125027: 15f7039
  125023: 88c056f
v: v3
  • Loading branch information
Sukadev Bhattiprolu authored and Linus Torvalds committed Jan 2, 2009
1 parent 6abf91a commit f99585b
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 6 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: e4adca27bcbb8a73c4cf1dfa71392654cfa33345
refs/heads/master: 1f8f1e296583f9f832c2fe7b5a219675b74bf43e
115 changes: 110 additions & 5 deletions trunk/fs/devpts/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@
#define DEVPTS_SUPER_MAGIC 0x1cd1

#define DEVPTS_DEFAULT_MODE 0600
/*
* ptmx is a new node in /dev/pts and will be unused in legacy (single-
* instance) mode. To prevent surprises in user space, set permissions of
* ptmx to 0. Use 'chmod' or remount with '-o ptmxmode' to set meaningful
* permissions.
*/
#define DEVPTS_DEFAULT_PTMX_MODE 0000
#define PTMX_MINOR 2

extern int pty_limit; /* Config limit on Unix98 ptys */
Expand All @@ -40,23 +47,28 @@ struct pts_mount_opts {
uid_t uid;
gid_t gid;
umode_t mode;
umode_t ptmxmode;
};

enum {
Opt_uid, Opt_gid, Opt_mode,
Opt_uid, Opt_gid, Opt_mode, Opt_ptmxmode,
Opt_err
};

static const match_table_t tokens = {
{Opt_uid, "uid=%u"},
{Opt_gid, "gid=%u"},
{Opt_mode, "mode=%o"},
#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
{Opt_ptmxmode, "ptmxmode=%o"},
#endif
{Opt_err, NULL}
};

struct pts_fs_info {
struct ida allocated_ptys;
struct pts_mount_opts mount_opts;
struct dentry *ptmx_dentry;
};

static inline struct pts_fs_info *DEVPTS_SB(struct super_block *sb)
Expand All @@ -81,6 +93,7 @@ static int parse_mount_options(char *data, struct pts_mount_opts *opts)
opts->uid = 0;
opts->gid = 0;
opts->mode = DEVPTS_DEFAULT_MODE;
opts->ptmxmode = DEVPTS_DEFAULT_PTMX_MODE;

while ((p = strsep(&data, ",")) != NULL) {
substring_t args[MAX_OPT_ARGS];
Expand Down Expand Up @@ -109,6 +122,13 @@ static int parse_mount_options(char *data, struct pts_mount_opts *opts)
return -EINVAL;
opts->mode = option & S_IALLUGO;
break;
#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
case Opt_ptmxmode:
if (match_octal(&args[0], &option))
return -EINVAL;
opts->ptmxmode = option & S_IALLUGO;
break;
#endif
default:
printk(KERN_ERR "devpts: called with bogus options\n");
return -EINVAL;
Expand All @@ -118,12 +138,93 @@ static int parse_mount_options(char *data, struct pts_mount_opts *opts)
return 0;
}

#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
static int mknod_ptmx(struct super_block *sb)
{
int mode;
int rc = -ENOMEM;
struct dentry *dentry;
struct inode *inode;
struct dentry *root = sb->s_root;
struct pts_fs_info *fsi = DEVPTS_SB(sb);
struct pts_mount_opts *opts = &fsi->mount_opts;

mutex_lock(&root->d_inode->i_mutex);

/* If we have already created ptmx node, return */
if (fsi->ptmx_dentry) {
rc = 0;
goto out;
}

dentry = d_alloc_name(root, "ptmx");
if (!dentry) {
printk(KERN_NOTICE "Unable to alloc dentry for ptmx node\n");
goto out;
}

/*
* Create a new 'ptmx' node in this mount of devpts.
*/
inode = new_inode(sb);
if (!inode) {
printk(KERN_ERR "Unable to alloc inode for ptmx node\n");
dput(dentry);
goto out;
}

inode->i_ino = 2;
inode->i_uid = inode->i_gid = 0;
inode->i_blocks = 0;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;

mode = S_IFCHR|opts->ptmxmode;
init_special_inode(inode, mode, MKDEV(TTYAUX_MAJOR, 2));

d_add(dentry, inode);

fsi->ptmx_dentry = dentry;
rc = 0;

printk(KERN_DEBUG "Created ptmx node in devpts ino %lu\n",
inode->i_ino);
out:
mutex_unlock(&root->d_inode->i_mutex);
return rc;
}

static void update_ptmx_mode(struct pts_fs_info *fsi)
{
struct inode *inode;
if (fsi->ptmx_dentry) {
inode = fsi->ptmx_dentry->d_inode;
inode->i_mode = S_IFCHR|fsi->mount_opts.ptmxmode;
}
}
#else
static inline void update_ptmx_mode(struct pts_fs_info *fsi)
{
return;
}
#endif

static int devpts_remount(struct super_block *sb, int *flags, char *data)
{
int err;
struct pts_fs_info *fsi = DEVPTS_SB(sb);
struct pts_mount_opts *opts = &fsi->mount_opts;

return parse_mount_options(data, opts);
err = parse_mount_options(data, opts);

/*
* parse_mount_options() restores options to default values
* before parsing and may have changed ptmxmode. So, update the
* mode in the inode too. Bogus options don't fail the remount,
* so do this even on error return.
*/
update_ptmx_mode(fsi);

return err;
}

static int devpts_show_options(struct seq_file *seq, struct vfsmount *vfs)
Expand All @@ -136,6 +237,9 @@ static int devpts_show_options(struct seq_file *seq, struct vfsmount *vfs)
if (opts->setgid)
seq_printf(seq, ",gid=%u", opts->gid);
seq_printf(seq, ",mode=%03o", opts->mode);
#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
seq_printf(seq, ",ptmxmode=%03o", opts->ptmxmode);
#endif

return 0;
}
Expand All @@ -156,14 +260,15 @@ static void *new_pts_fs_info(void)

ida_init(&fsi->allocated_ptys);
fsi->mount_opts.mode = DEVPTS_DEFAULT_MODE;
fsi->mount_opts.ptmxmode = DEVPTS_DEFAULT_PTMX_MODE;

return fsi;
}

static int
devpts_fill_super(struct super_block *s, void *data, int silent)
{
struct inode * inode;
struct inode *inode;

s->s_blocksize = 1024;
s->s_blocksize_bits = 10;
Expand All @@ -190,7 +295,7 @@ devpts_fill_super(struct super_block *s, void *data, int silent)
s->s_root = d_alloc_root(inode);
if (s->s_root)
return 0;

printk("devpts: get root dentry failed\n");
iput(inode);

Expand All @@ -211,7 +316,7 @@ static void devpts_kill_sb(struct super_block *sb)
struct pts_fs_info *fsi = DEVPTS_SB(sb);

kfree(fsi);
kill_anon_super(sb);
kill_litter_super(sb);
}

static struct file_system_type devpts_fs_type = {
Expand Down

0 comments on commit f99585b

Please sign in to comment.