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
39
40
41
42
43static int pty_limit = NR_UNIX98_PTY_DEFAULT;
44static int pty_reserve = NR_UNIX98_PTY_RESERVE;
45static int pty_limit_min;
46static int pty_limit_max = INT_MAX;
47static int pty_count;
48
49static struct ctl_table pty_table[] = {
50 {
51 .procname = "max",
52 .maxlen = sizeof(int),
53 .mode = 0644,
54 .data = &pty_limit,
55 .proc_handler = proc_dointvec_minmax,
56 .extra1 = &pty_limit_min,
57 .extra2 = &pty_limit_max,
58 }, {
59 .procname = "reserve",
60 .maxlen = sizeof(int),
61 .mode = 0644,
62 .data = &pty_reserve,
63 .proc_handler = proc_dointvec_minmax,
64 .extra1 = &pty_limit_min,
65 .extra2 = &pty_limit_max,
66 }, {
67 .procname = "nr",
68 .maxlen = sizeof(int),
69 .mode = 0444,
70 .data = &pty_count,
71 .proc_handler = proc_dointvec,
72 },
73 {}
74};
75
76static struct ctl_table pty_kern_table[] = {
77 {
78 .procname = "pty",
79 .mode = 0555,
80 .child = pty_table,
81 },
82 {}
83};
84
85static struct ctl_table pty_root_table[] = {
86 {
87 .procname = "kernel",
88 .mode = 0555,
89 .child = pty_kern_table,
90 },
91 {}
92};
93
94static DEFINE_MUTEX(allocated_ptys_lock);
95
96static struct vfsmount *devpts_mnt;
97
98struct pts_mount_opts {
99 int setuid;
100 int setgid;
101 kuid_t uid;
102 kgid_t gid;
103 umode_t mode;
104 umode_t ptmxmode;
105 int newinstance;
106 int max;
107};
108
109enum {
110 Opt_uid, Opt_gid, Opt_mode, Opt_ptmxmode, Opt_newinstance, Opt_max,
111 Opt_err
112};
113
114static const match_table_t tokens = {
115 {Opt_uid, "uid=%u"},
116 {Opt_gid, "gid=%u"},
117 {Opt_mode, "mode=%o"},
118#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
119 {Opt_ptmxmode, "ptmxmode=%o"},
120 {Opt_newinstance, "newinstance"},
121 {Opt_max, "max=%d"},
122#endif
123 {Opt_err, NULL}
124};
125
126struct pts_fs_info {
127 struct ida allocated_ptys;
128 struct pts_mount_opts mount_opts;
129 struct super_block *sb;
130 struct dentry *ptmx_dentry;
131};
132
133static inline struct pts_fs_info *DEVPTS_SB(struct super_block *sb)
134{
135 return sb->s_fs_info;
136}
137
138static inline struct super_block *pts_sb_from_inode(struct inode *inode)
139{
140#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
141 if (inode->i_sb->s_magic == DEVPTS_SUPER_MAGIC)
142 return inode->i_sb;
143#endif
144 if (!devpts_mnt)
145 return NULL;
146 return devpts_mnt->mnt_sb;
147}
148
149#define PARSE_MOUNT 0
150#define PARSE_REMOUNT 1
151
152
153
154
155
156
157
158
159
160
161static int parse_mount_options(char *data, int op, struct pts_mount_opts *opts)
162{
163 char *p;
164 kuid_t uid;
165 kgid_t gid;
166
167 opts->setuid = 0;
168 opts->setgid = 0;
169 opts->uid = GLOBAL_ROOT_UID;
170 opts->gid = GLOBAL_ROOT_GID;
171 opts->mode = DEVPTS_DEFAULT_MODE;
172 opts->ptmxmode = DEVPTS_DEFAULT_PTMX_MODE;
173 opts->max = NR_UNIX98_PTY_MAX;
174
175
176 if (op == PARSE_MOUNT)
177 opts->newinstance = 0;
178
179 while ((p = strsep(&data, ",")) != NULL) {
180 substring_t args[MAX_OPT_ARGS];
181 int token;
182 int option;
183
184 if (!*p)
185 continue;
186
187 token = match_token(p, tokens, args);
188 switch (token) {
189 case Opt_uid:
190 if (match_int(&args[0], &option))
191 return -EINVAL;
192 uid = make_kuid(current_user_ns(), option);
193 if (!uid_valid(uid))
194 return -EINVAL;
195 opts->uid = uid;
196 opts->setuid = 1;
197 break;
198 case Opt_gid:
199 if (match_int(&args[0], &option))
200 return -EINVAL;
201 gid = make_kgid(current_user_ns(), option);
202 if (!gid_valid(gid))
203 return -EINVAL;
204 opts->gid = gid;
205 opts->setgid = 1;
206 break;
207 case Opt_mode:
208 if (match_octal(&args[0], &option))
209 return -EINVAL;
210 opts->mode = option & S_IALLUGO;
211 break;
212#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
213 case Opt_ptmxmode:
214 if (match_octal(&args[0], &option))
215 return -EINVAL;
216 opts->ptmxmode = option & S_IALLUGO;
217 break;
218 case Opt_newinstance:
219
220 if (op == PARSE_MOUNT)
221 opts->newinstance = 1;
222 break;
223 case Opt_max:
224 if (match_int(&args[0], &option) ||
225 option < 0 || option > NR_UNIX98_PTY_MAX)
226 return -EINVAL;
227 opts->max = option;
228 break;
229#endif
230 default:
231 printk(KERN_ERR "devpts: called with bogus options\n");
232 return -EINVAL;
233 }
234 }
235
236 return 0;
237}
238
239#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
240static int mknod_ptmx(struct super_block *sb)
241{
242 int mode;
243 int rc = -ENOMEM;
244 struct dentry *dentry;
245 struct inode *inode;
246 struct dentry *root = sb->s_root;
247 struct pts_fs_info *fsi = DEVPTS_SB(sb);
248 struct pts_mount_opts *opts = &fsi->mount_opts;
249 kuid_t ptmx_uid = current_fsuid();
250 kgid_t ptmx_gid = current_fsgid();
251
252 mutex_lock(&root->d_inode->i_mutex);
253
254
255 if (fsi->ptmx_dentry) {
256 rc = 0;
257 goto out;
258 }
259
260 dentry = d_alloc_name(root, "ptmx");
261 if (!dentry) {
262 printk(KERN_NOTICE "Unable to alloc dentry for ptmx node\n");
263 goto out;
264 }
265
266
267
268
269 inode = new_inode(sb);
270 if (!inode) {
271 printk(KERN_ERR "Unable to alloc inode for ptmx node\n");
272 dput(dentry);
273 goto out;
274 }
275
276 inode->i_ino = 2;
277 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
278
279 mode = S_IFCHR|opts->ptmxmode;
280 init_special_inode(inode, mode, MKDEV(TTYAUX_MAJOR, 2));
281 inode->i_uid = ptmx_uid;
282 inode->i_gid = ptmx_gid;
283
284 d_add(dentry, inode);
285
286 fsi->ptmx_dentry = dentry;
287 rc = 0;
288out:
289 mutex_unlock(&root->d_inode->i_mutex);
290 return rc;
291}
292
293static void update_ptmx_mode(struct pts_fs_info *fsi)
294{
295 struct inode *inode;
296 if (fsi->ptmx_dentry) {
297 inode = fsi->ptmx_dentry->d_inode;
298 inode->i_mode = S_IFCHR|fsi->mount_opts.ptmxmode;
299 }
300}
301#else
302static inline void update_ptmx_mode(struct pts_fs_info *fsi)
303{
304 return;
305}
306#endif
307
308static int devpts_remount(struct super_block *sb, int *flags, char *data)
309{
310 int err;
311 struct pts_fs_info *fsi = DEVPTS_SB(sb);
312 struct pts_mount_opts *opts = &fsi->mount_opts;
313
314 err = parse_mount_options(data, PARSE_REMOUNT, opts);
315
316
317
318
319
320
321
322 update_ptmx_mode(fsi);
323
324 return err;
325}
326
327static int devpts_show_options(struct seq_file *seq, struct dentry *root)
328{
329 struct pts_fs_info *fsi = DEVPTS_SB(root->d_sb);
330 struct pts_mount_opts *opts = &fsi->mount_opts;
331
332 if (opts->setuid)
333 seq_printf(seq, ",uid=%u", from_kuid_munged(&init_user_ns, opts->uid));
334 if (opts->setgid)
335 seq_printf(seq, ",gid=%u", from_kgid_munged(&init_user_ns, opts->gid));
336 seq_printf(seq, ",mode=%03o", opts->mode);
337#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
338 seq_printf(seq, ",ptmxmode=%03o", opts->ptmxmode);
339 if (opts->max < NR_UNIX98_PTY_MAX)
340 seq_printf(seq, ",max=%d", opts->max);
341#endif
342
343 return 0;
344}
345
346static const struct super_operations devpts_sops = {
347 .statfs = simple_statfs,
348 .remount_fs = devpts_remount,
349 .show_options = devpts_show_options,
350};
351
352static void *new_pts_fs_info(struct super_block *sb)
353{
354 struct pts_fs_info *fsi;
355
356 fsi = kzalloc(sizeof(struct pts_fs_info), GFP_KERNEL);
357 if (!fsi)
358 return NULL;
359
360 ida_init(&fsi->allocated_ptys);
361 fsi->mount_opts.mode = DEVPTS_DEFAULT_MODE;
362 fsi->mount_opts.ptmxmode = DEVPTS_DEFAULT_PTMX_MODE;
363 fsi->sb = sb;
364
365 return fsi;
366}
367
368static int
369devpts_fill_super(struct super_block *s, void *data, int silent)
370{
371 struct inode *inode;
372
373 s->s_iflags &= ~SB_I_NODEV;
374 s->s_blocksize = 1024;
375 s->s_blocksize_bits = 10;
376 s->s_magic = DEVPTS_SUPER_MAGIC;
377 s->s_op = &devpts_sops;
378 s->s_time_gran = 1;
379
380 s->s_fs_info = new_pts_fs_info(s);
381 if (!s->s_fs_info)
382 goto fail;
383
384 inode = new_inode(s);
385 if (!inode)
386 goto fail;
387 inode->i_ino = 1;
388 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
389 inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
390 inode->i_op = &simple_dir_inode_operations;
391 inode->i_fop = &simple_dir_operations;
392 set_nlink(inode, 2);
393
394 s->s_root = d_make_root(inode);
395 if (s->s_root)
396 return 0;
397
398 printk(KERN_ERR "devpts: get root dentry failed\n");
399
400fail:
401 return -ENOMEM;
402}
403
404#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
405static int compare_init_pts_sb(struct super_block *s, void *p)
406{
407 if (devpts_mnt)
408 return devpts_mnt->mnt_sb == s;
409 return 0;
410}
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439static struct dentry *devpts_mount(struct file_system_type *fs_type,
440 int flags, const char *dev_name, void *data)
441{
442 int error;
443 struct pts_mount_opts opts;
444 struct super_block *s;
445
446 error = parse_mount_options(data, PARSE_MOUNT, &opts);
447 if (error)
448 return ERR_PTR(error);
449
450
451
452
453 if ((current_user_ns() != &init_user_ns) && !opts.newinstance)
454 return ERR_PTR(-EINVAL);
455
456 if (opts.newinstance)
457 s = sget(fs_type, NULL, set_anon_super, flags, NULL);
458 else
459 s = sget(fs_type, compare_init_pts_sb, set_anon_super, flags,
460 NULL);
461
462 if (IS_ERR(s))
463 return ERR_CAST(s);
464
465 if (!s->s_root) {
466 error = devpts_fill_super(s, data, flags & MS_SILENT ? 1 : 0);
467 if (error)
468 goto out_undo_sget;
469 s->s_flags |= MS_ACTIVE;
470 }
471
472 memcpy(&(DEVPTS_SB(s))->mount_opts, &opts, sizeof(opts));
473
474 error = mknod_ptmx(s);
475 if (error)
476 goto out_undo_sget;
477
478 return dget(s->s_root);
479
480out_undo_sget:
481 deactivate_locked_super(s);
482 return ERR_PTR(error);
483}
484
485#else
486
487
488
489
490static struct dentry *devpts_mount(struct file_system_type *fs_type, int flags,
491 const char *dev_name, void *data)
492{
493 return mount_single(fs_type, flags, data, devpts_fill_super);
494}
495#endif
496
497static void devpts_kill_sb(struct super_block *sb)
498{
499 struct pts_fs_info *fsi = DEVPTS_SB(sb);
500
501 if (fsi)
502 ida_destroy(&fsi->allocated_ptys);
503 kfree(fsi);
504 kill_litter_super(sb);
505}
506
507static struct file_system_type devpts_fs_type = {
508 .name = "devpts",
509 .mount = devpts_mount,
510 .kill_sb = devpts_kill_sb,
511#ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
512 .fs_flags = FS_USERNS_MOUNT,
513#endif
514};
515
516
517
518
519
520
521int devpts_new_index(struct pts_fs_info *fsi)
522{
523 int index;
524 int ida_ret;
525
526 if (!fsi)
527 return -ENODEV;
528
529retry:
530 if (!ida_pre_get(&fsi->allocated_ptys, GFP_KERNEL))
531 return -ENOMEM;
532
533 mutex_lock(&allocated_ptys_lock);
534 if (pty_count >= pty_limit -
535 (fsi->mount_opts.newinstance ? pty_reserve : 0)) {
536 mutex_unlock(&allocated_ptys_lock);
537 return -ENOSPC;
538 }
539
540 ida_ret = ida_get_new(&fsi->allocated_ptys, &index);
541 if (ida_ret < 0) {
542 mutex_unlock(&allocated_ptys_lock);
543 if (ida_ret == -EAGAIN)
544 goto retry;
545 return -EIO;
546 }
547
548 if (index >= fsi->mount_opts.max) {
549 ida_remove(&fsi->allocated_ptys, index);
550 mutex_unlock(&allocated_ptys_lock);
551 return -ENOSPC;
552 }
553 pty_count++;
554 mutex_unlock(&allocated_ptys_lock);
555 return index;
556}
557
558void devpts_kill_index(struct pts_fs_info *fsi, int idx)
559{
560 mutex_lock(&allocated_ptys_lock);
561 ida_remove(&fsi->allocated_ptys, idx);
562 pty_count--;
563 mutex_unlock(&allocated_ptys_lock);
564}
565
566
567
568
569struct pts_fs_info *devpts_get_ref(struct inode *ptmx_inode, struct file *file)
570{
571 struct super_block *sb;
572 struct pts_fs_info *fsi;
573
574 sb = pts_sb_from_inode(ptmx_inode);
575 if (!sb)
576 return NULL;
577 fsi = DEVPTS_SB(sb);
578 if (!fsi)
579 return NULL;
580
581 atomic_inc(&sb->s_active);
582 return fsi;
583}
584
585void devpts_put_ref(struct pts_fs_info *fsi)
586{
587 deactivate_super(fsi->sb);
588}
589
590
591
592
593
594
595
596
597
598
599struct inode *devpts_pty_new(struct pts_fs_info *fsi, dev_t device, int index,
600 void *priv)
601{
602 struct dentry *dentry;
603 struct super_block *sb;
604 struct inode *inode;
605 struct dentry *root;
606 struct pts_mount_opts *opts;
607 char s[12];
608
609 if (!fsi)
610 return ERR_PTR(-ENODEV);
611
612 sb = fsi->sb;
613 root = sb->s_root;
614 opts = &fsi->mount_opts;
615
616 inode = new_inode(sb);
617 if (!inode)
618 return ERR_PTR(-ENOMEM);
619
620 inode->i_ino = index + 3;
621 inode->i_uid = opts->setuid ? opts->uid : current_fsuid();
622 inode->i_gid = opts->setgid ? opts->gid : current_fsgid();
623 inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
624 init_special_inode(inode, S_IFCHR|opts->mode, device);
625 inode->i_private = priv;
626
627 sprintf(s, "%d", index);
628
629 mutex_lock(&root->d_inode->i_mutex);
630
631 dentry = d_alloc_name(root, s);
632 if (dentry) {
633 d_add(dentry, inode);
634 fsnotify_create(root->d_inode, dentry);
635 } else {
636 iput(inode);
637 inode = ERR_PTR(-ENOMEM);
638 }
639
640 mutex_unlock(&root->d_inode->i_mutex);
641
642 return inode;
643}
644
645
646
647
648
649
650
651void *devpts_get_priv(struct inode *pts_inode)
652{
653 struct dentry *dentry;
654 void *priv = NULL;
655
656 BUG_ON(pts_inode->i_rdev == MKDEV(TTYAUX_MAJOR, PTMX_MINOR));
657
658
659 dentry = d_find_alias(pts_inode);
660 if (!dentry)
661 return NULL;
662
663 if (pts_inode->i_sb->s_magic == DEVPTS_SUPER_MAGIC)
664 priv = pts_inode->i_private;
665
666 dput(dentry);
667
668 return priv;
669}
670
671
672
673
674
675
676
677void devpts_pty_kill(struct inode *inode)
678{
679 struct super_block *sb = pts_sb_from_inode(inode);
680 struct dentry *root = sb->s_root;
681 struct dentry *dentry;
682
683 BUG_ON(inode->i_rdev == MKDEV(TTYAUX_MAJOR, PTMX_MINOR));
684
685 mutex_lock(&root->d_inode->i_mutex);
686
687 dentry = d_find_alias(inode);
688
689 drop_nlink(inode);
690 d_delete(dentry);
691 dput(dentry);
692 dput(dentry);
693
694 mutex_unlock(&root->d_inode->i_mutex);
695}
696
697static int __init init_devpts_fs(void)
698{
699 int err = register_filesystem(&devpts_fs_type);
700 struct ctl_table_header *table;
701
702 if (!err) {
703 struct vfsmount *mnt;
704
705 table = register_sysctl_table(pty_root_table);
706 mnt = kern_mount(&devpts_fs_type);
707 if (IS_ERR(mnt)) {
708 err = PTR_ERR(mnt);
709 unregister_filesystem(&devpts_fs_type);
710 unregister_sysctl_table(table);
711 } else {
712 devpts_mnt = mnt;
713 }
714 }
715 return err;
716}
717module_init(init_devpts_fs)
718