1
2
3
4
5
6
7
8
9
10
11
12
13#include <linux/module.h>
14#include <linux/init.h>
15#include <linux/fs.h>
16#include <linux/sched.h>
17#include <linux/namei.h>
18#include <linux/slab.h>
19#include <linux/mount.h>
20#include <linux/tty.h>
21#include <linux/mutex.h>
22#include <linux/magic.h>
23#include <linux/idr.h>
24#include <linux/devpts_fs.h>
25#include <linux/parser.h>
26#include <linux/fsnotify.h>
27#include <linux/seq_file.h>
28
29#define DEVPTS_DEFAULT_MODE 0600
30
31
32
33
34
35
36#define DEVPTS_DEFAULT_PTMX_MODE 0000
37#define PTMX_MINOR 2
38
39extern int pty_limit;
40static DEFINE_MUTEX(allocated_ptys_lock);
41
42static struct vfsmount *devpts_mnt;
43
44struct pts_mount_opts {
45 int setuid;
46 int setgid;
47 uid_t uid;
48 gid_t gid;
49 umode_t mode;
50 umode_t ptmxmode;
51 int newinstance;
52};
53
54enum {
55 Opt_uid, Opt_gid, Opt_mode, Opt_ptmxmode, Opt_newinstance,
56 Opt_err
57};
58
59static const match_table_t tokens = {
60 {Opt_uid, "uid=%u"},
61 {Opt_gid, "gid=%u"},
62 {Opt_mode, "mode=%o"},
63#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
64 {Opt_ptmxmode, "ptmxmode=%o"},
65 {Opt_newinstance, "newinstance"},
66#endif
67 {Opt_err, NULL}
68};
69
70struct pts_fs_info {
71 struct ida allocated_ptys;
72 struct pts_mount_opts mount_opts;
73 struct dentry *ptmx_dentry;
74};
75
76static inline struct pts_fs_info *DEVPTS_SB(struct super_block *sb)
77{
78 return sb->s_fs_info;
79}
80
81static inline struct super_block *pts_sb_from_inode(struct inode *inode)
82{
83#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
84 if (inode->i_sb->s_magic == DEVPTS_SUPER_MAGIC)
85 return inode->i_sb;
86#endif
87 return devpts_mnt->mnt_sb;
88}
89
90#define PARSE_MOUNT 0
91#define PARSE_REMOUNT 1
92
93
94
95
96
97
98
99
100
101
102static int parse_mount_options(char *data, int op, struct pts_mount_opts *opts)
103{
104 char *p;
105
106 opts->setuid = 0;
107 opts->setgid = 0;
108 opts->uid = 0;
109 opts->gid = 0;
110 opts->mode = DEVPTS_DEFAULT_MODE;
111 opts->ptmxmode = DEVPTS_DEFAULT_PTMX_MODE;
112
113
114 if (op == PARSE_MOUNT)
115 opts->newinstance = 0;
116
117 while ((p = strsep(&data, ",")) != NULL) {
118 substring_t args[MAX_OPT_ARGS];
119 int token;
120 int option;
121
122 if (!*p)
123 continue;
124
125 token = match_token(p, tokens, args);
126 switch (token) {
127 case Opt_uid:
128 if (match_int(&args[0], &option))
129 return -EINVAL;
130 opts->uid = option;
131 opts->setuid = 1;
132 break;
133 case Opt_gid:
134 if (match_int(&args[0], &option))
135 return -EINVAL;
136 opts->gid = option;
137 opts->setgid = 1;
138 break;
139 case Opt_mode:
140 if (match_octal(&args[0], &option))
141 return -EINVAL;
142 opts->mode = option & S_IALLUGO;
143 break;
144#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
145 case Opt_ptmxmode:
146 if (match_octal(&args[0], &option))
147 return -EINVAL;
148 opts->ptmxmode = option & S_IALLUGO;
149 break;
150 case Opt_newinstance:
151
152 if (op == PARSE_MOUNT)
153 opts->newinstance = 1;
154 break;
155#endif
156 default:
157 printk(KERN_ERR "devpts: called with bogus options\n");
158 return -EINVAL;
159 }
160 }
161
162 return 0;
163}
164
165#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
166static int mknod_ptmx(struct super_block *sb)
167{
168 int mode;
169 int rc = -ENOMEM;
170 struct dentry *dentry;
171 struct inode *inode;
172 struct dentry *root = sb->s_root;
173 struct pts_fs_info *fsi = DEVPTS_SB(sb);
174 struct pts_mount_opts *opts = &fsi->mount_opts;
175
176 mutex_lock(&root->d_inode->i_mutex);
177
178
179 if (fsi->ptmx_dentry) {
180 rc = 0;
181 goto out;
182 }
183
184 dentry = d_alloc_name(root, "ptmx");
185 if (!dentry) {
186 printk(KERN_NOTICE "Unable to alloc dentry for ptmx node\n");
187 goto out;
188 }
189
190
191
192
193 inode = new_inode(sb);
194 if (!inode) {
195 printk(KERN_ERR "Unable to alloc inode for ptmx node\n");
196 dput(dentry);
197 goto out;
198 }
199
200 inode->i_ino = 2;
201 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
202
203 mode = S_IFCHR|opts->ptmxmode;
204 init_special_inode(inode, mode, MKDEV(TTYAUX_MAJOR, 2));
205
206 d_add(dentry, inode);
207
208 fsi->ptmx_dentry = dentry;
209 rc = 0;
210out:
211 mutex_unlock(&root->d_inode->i_mutex);
212 return rc;
213}
214
215static void update_ptmx_mode(struct pts_fs_info *fsi)
216{
217 struct inode *inode;
218 if (fsi->ptmx_dentry) {
219 inode = fsi->ptmx_dentry->d_inode;
220 inode->i_mode = S_IFCHR|fsi->mount_opts.ptmxmode;
221 }
222}
223#else
224static inline void update_ptmx_mode(struct pts_fs_info *fsi)
225{
226 return;
227}
228#endif
229
230static int devpts_remount(struct super_block *sb, int *flags, char *data)
231{
232 int err;
233 struct pts_fs_info *fsi = DEVPTS_SB(sb);
234 struct pts_mount_opts *opts = &fsi->mount_opts;
235
236 err = parse_mount_options(data, PARSE_REMOUNT, opts);
237
238
239
240
241
242
243
244 update_ptmx_mode(fsi);
245
246 return err;
247}
248
249static int devpts_show_options(struct seq_file *seq, struct vfsmount *vfs)
250{
251 struct pts_fs_info *fsi = DEVPTS_SB(vfs->mnt_sb);
252 struct pts_mount_opts *opts = &fsi->mount_opts;
253
254 if (opts->setuid)
255 seq_printf(seq, ",uid=%u", opts->uid);
256 if (opts->setgid)
257 seq_printf(seq, ",gid=%u", opts->gid);
258 seq_printf(seq, ",mode=%03o", opts->mode);
259#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
260 seq_printf(seq, ",ptmxmode=%03o", opts->ptmxmode);
261#endif
262
263 return 0;
264}
265
266static const struct super_operations devpts_sops = {
267 .statfs = simple_statfs,
268 .remount_fs = devpts_remount,
269 .show_options = devpts_show_options,
270};
271
272static void *new_pts_fs_info(void)
273{
274 struct pts_fs_info *fsi;
275
276 fsi = kzalloc(sizeof(struct pts_fs_info), GFP_KERNEL);
277 if (!fsi)
278 return NULL;
279
280 ida_init(&fsi->allocated_ptys);
281 fsi->mount_opts.mode = DEVPTS_DEFAULT_MODE;
282 fsi->mount_opts.ptmxmode = DEVPTS_DEFAULT_PTMX_MODE;
283
284 return fsi;
285}
286
287static int
288devpts_fill_super(struct super_block *s, void *data, int silent)
289{
290 struct inode *inode;
291
292 s->s_blocksize = 1024;
293 s->s_blocksize_bits = 10;
294 s->s_magic = DEVPTS_SUPER_MAGIC;
295 s->s_op = &devpts_sops;
296 s->s_time_gran = 1;
297
298 s->s_fs_info = new_pts_fs_info();
299 if (!s->s_fs_info)
300 goto fail;
301
302 inode = new_inode(s);
303 if (!inode)
304 goto free_fsi;
305 inode->i_ino = 1;
306 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
307 inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
308 inode->i_op = &simple_dir_inode_operations;
309 inode->i_fop = &simple_dir_operations;
310 inode->i_nlink = 2;
311
312 s->s_root = d_alloc_root(inode);
313 if (s->s_root)
314 return 0;
315
316 printk(KERN_ERR "devpts: get root dentry failed\n");
317 iput(inode);
318
319free_fsi:
320 kfree(s->s_fs_info);
321fail:
322 return -ENOMEM;
323}
324
325#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
326static int compare_init_pts_sb(struct super_block *s, void *p)
327{
328 if (devpts_mnt)
329 return devpts_mnt->mnt_sb == s;
330 return 0;
331}
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360static struct dentry *devpts_mount(struct file_system_type *fs_type,
361 int flags, const char *dev_name, void *data)
362{
363 int error;
364 struct pts_mount_opts opts;
365 struct super_block *s;
366
367 error = parse_mount_options(data, PARSE_MOUNT, &opts);
368 if (error)
369 return ERR_PTR(error);
370
371 if (opts.newinstance)
372 s = sget(fs_type, NULL, set_anon_super, NULL);
373 else
374 s = sget(fs_type, compare_init_pts_sb, set_anon_super, NULL);
375
376 if (IS_ERR(s))
377 return ERR_CAST(s);
378
379 if (!s->s_root) {
380 s->s_flags = flags;
381 error = devpts_fill_super(s, data, flags & MS_SILENT ? 1 : 0);
382 if (error)
383 goto out_undo_sget;
384 s->s_flags |= MS_ACTIVE;
385 }
386
387 memcpy(&(DEVPTS_SB(s))->mount_opts, &opts, sizeof(opts));
388
389 error = mknod_ptmx(s);
390 if (error)
391 goto out_undo_sget;
392
393 return dget(s->s_root);
394
395out_undo_sget:
396 deactivate_locked_super(s);
397 return ERR_PTR(error);
398}
399
400#else
401
402
403
404
405static struct dentry *devpts_mount(struct file_system_type *fs_type, int flags,
406 const char *dev_name, void *data)
407{
408 return mount_single(fs_type, flags, data, devpts_fill_super);
409}
410#endif
411
412static void devpts_kill_sb(struct super_block *sb)
413{
414 struct pts_fs_info *fsi = DEVPTS_SB(sb);
415
416 kfree(fsi);
417 kill_litter_super(sb);
418}
419
420static struct file_system_type devpts_fs_type = {
421 .name = "devpts",
422 .mount = devpts_mount,
423 .kill_sb = devpts_kill_sb,
424};
425
426
427
428
429
430
431int devpts_new_index(struct inode *ptmx_inode)
432{
433 struct super_block *sb = pts_sb_from_inode(ptmx_inode);
434 struct pts_fs_info *fsi = DEVPTS_SB(sb);
435 int index;
436 int ida_ret;
437
438retry:
439 if (!ida_pre_get(&fsi->allocated_ptys, GFP_KERNEL))
440 return -ENOMEM;
441
442 mutex_lock(&allocated_ptys_lock);
443 ida_ret = ida_get_new(&fsi->allocated_ptys, &index);
444 if (ida_ret < 0) {
445 mutex_unlock(&allocated_ptys_lock);
446 if (ida_ret == -EAGAIN)
447 goto retry;
448 return -EIO;
449 }
450
451 if (index >= pty_limit) {
452 ida_remove(&fsi->allocated_ptys, index);
453 mutex_unlock(&allocated_ptys_lock);
454 return -EIO;
455 }
456 mutex_unlock(&allocated_ptys_lock);
457 return index;
458}
459
460void devpts_kill_index(struct inode *ptmx_inode, int idx)
461{
462 struct super_block *sb = pts_sb_from_inode(ptmx_inode);
463 struct pts_fs_info *fsi = DEVPTS_SB(sb);
464
465 mutex_lock(&allocated_ptys_lock);
466 ida_remove(&fsi->allocated_ptys, idx);
467 mutex_unlock(&allocated_ptys_lock);
468}
469
470int devpts_pty_new(struct inode *ptmx_inode, struct tty_struct *tty)
471{
472
473 int number = tty->index;
474 struct tty_driver *driver = tty->driver;
475 dev_t device = MKDEV(driver->major, driver->minor_start+number);
476 struct dentry *dentry;
477 struct super_block *sb = pts_sb_from_inode(ptmx_inode);
478 struct inode *inode = new_inode(sb);
479 struct dentry *root = sb->s_root;
480 struct pts_fs_info *fsi = DEVPTS_SB(sb);
481 struct pts_mount_opts *opts = &fsi->mount_opts;
482 char s[12];
483
484
485 BUG_ON(driver->type != TTY_DRIVER_TYPE_PTY);
486 BUG_ON(driver->subtype != PTY_TYPE_SLAVE);
487
488 if (!inode)
489 return -ENOMEM;
490
491 inode->i_ino = number + 3;
492 inode->i_uid = opts->setuid ? opts->uid : current_fsuid();
493 inode->i_gid = opts->setgid ? opts->gid : current_fsgid();
494 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
495 init_special_inode(inode, S_IFCHR|opts->mode, device);
496 inode->i_private = tty;
497 tty->driver_data = inode;
498
499 sprintf(s, "%d", number);
500
501 mutex_lock(&root->d_inode->i_mutex);
502
503 dentry = d_alloc_name(root, s);
504 if (!IS_ERR(dentry)) {
505 d_add(dentry, inode);
506 fsnotify_create(root->d_inode, dentry);
507 }
508
509 mutex_unlock(&root->d_inode->i_mutex);
510
511 return 0;
512}
513
514struct tty_struct *devpts_get_tty(struct inode *pts_inode, int number)
515{
516 struct dentry *dentry;
517 struct tty_struct *tty;
518
519 BUG_ON(pts_inode->i_rdev == MKDEV(TTYAUX_MAJOR, PTMX_MINOR));
520
521
522 dentry = d_find_alias(pts_inode);
523 if (!dentry)
524 return NULL;
525
526 tty = NULL;
527 if (pts_inode->i_sb->s_magic == DEVPTS_SUPER_MAGIC)
528 tty = (struct tty_struct *)pts_inode->i_private;
529
530 dput(dentry);
531
532 return tty;
533}
534
535void devpts_pty_kill(struct tty_struct *tty)
536{
537 struct inode *inode = tty->driver_data;
538 struct super_block *sb = pts_sb_from_inode(inode);
539 struct dentry *root = sb->s_root;
540 struct dentry *dentry;
541
542 BUG_ON(inode->i_rdev == MKDEV(TTYAUX_MAJOR, PTMX_MINOR));
543
544 mutex_lock(&root->d_inode->i_mutex);
545
546 dentry = d_find_alias(inode);
547 if (IS_ERR(dentry))
548 goto out;
549
550 if (dentry) {
551 inode->i_nlink--;
552 d_delete(dentry);
553 dput(dentry);
554 }
555
556 dput(dentry);
557out:
558 mutex_unlock(&root->d_inode->i_mutex);
559}
560
561static int __init init_devpts_fs(void)
562{
563 int err = register_filesystem(&devpts_fs_type);
564 if (!err) {
565 devpts_mnt = kern_mount(&devpts_fs_type);
566 if (IS_ERR(devpts_mnt)) {
567 err = PTR_ERR(devpts_mnt);
568 unregister_filesystem(&devpts_fs_type);
569 }
570 }
571 return err;
572}
573module_init(init_devpts_fs)
574