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