Branch data Line data Source code
1 : : /* -*- linux-c -*- --------------------------------------------------------- *
2 : : *
3 : : * linux/fs/devpts/inode.c
4 : : *
5 : : * Copyright 1998-2004 H. Peter Anvin -- All Rights Reserved
6 : : *
7 : : * This file is part of the Linux kernel and is made available under
8 : : * the terms of the GNU General Public License, version 2, or at your
9 : : * option, any later version, incorporated herein by reference.
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 : : * ptmx is a new node in /dev/pts and will be unused in legacy (single-
32 : : * instance) mode. To prevent surprises in user space, set permissions of
33 : : * ptmx to 0. Use 'chmod' or remount with '-o ptmxmode' to set meaningful
34 : : * permissions.
35 : : */
36 : : #define DEVPTS_DEFAULT_PTMX_MODE 0000
37 : : #define PTMX_MINOR 2
38 : :
39 : : /*
40 : : * sysctl support for setting limits on the number of Unix98 ptys allocated.
41 : : * Otherwise one can eat up all kernel memory by opening /dev/ptmx repeatedly.
42 : : */
43 : : static int pty_limit = NR_UNIX98_PTY_DEFAULT;
44 : : static int pty_reserve = NR_UNIX98_PTY_RESERVE;
45 : : static int pty_limit_min;
46 : : static int pty_limit_max = INT_MAX;
47 : : static int pty_count;
48 : :
49 : : static 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 : :
76 : : static struct ctl_table pty_kern_table[] = {
77 : : {
78 : : .procname = "pty",
79 : : .mode = 0555,
80 : : .child = pty_table,
81 : : },
82 : : {}
83 : : };
84 : :
85 : : static struct ctl_table pty_root_table[] = {
86 : : {
87 : : .procname = "kernel",
88 : : .mode = 0555,
89 : : .child = pty_kern_table,
90 : : },
91 : : {}
92 : : };
93 : :
94 : : static DEFINE_MUTEX(allocated_ptys_lock);
95 : :
96 : : static struct vfsmount *devpts_mnt;
97 : :
98 : : struct 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 : :
109 : : enum {
110 : : Opt_uid, Opt_gid, Opt_mode, Opt_ptmxmode, Opt_newinstance, Opt_max,
111 : : Opt_err
112 : : };
113 : :
114 : : static 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 : :
126 : : struct pts_fs_info {
127 : : struct ida allocated_ptys;
128 : : struct pts_mount_opts mount_opts;
129 : : struct dentry *ptmx_dentry;
130 : : };
131 : :
132 : : static inline struct pts_fs_info *DEVPTS_SB(struct super_block *sb)
133 : : {
134 : : return sb->s_fs_info;
135 : : }
136 : :
137 : : static inline struct super_block *pts_sb_from_inode(struct inode *inode)
138 : : {
139 : : #ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
140 : : if (inode->i_sb->s_magic == DEVPTS_SUPER_MAGIC)
141 : : return inode->i_sb;
142 : : #endif
143 : 376 : return devpts_mnt->mnt_sb;
144 : : }
145 : :
146 : : #define PARSE_MOUNT 0
147 : : #define PARSE_REMOUNT 1
148 : :
149 : : /*
150 : : * parse_mount_options():
151 : : * Set @opts to mount options specified in @data. If an option is not
152 : : * specified in @data, set it to its default value. The exception is
153 : : * 'newinstance' option which can only be set/cleared on a mount (i.e.
154 : : * cannot be changed during remount).
155 : : *
156 : : * Note: @data may be NULL (in which case all options are set to default).
157 : : */
158 : 0 : static int parse_mount_options(char *data, int op, struct pts_mount_opts *opts)
159 : : {
160 : : char *p;
161 : : kuid_t uid;
162 : : kgid_t gid;
163 : :
164 : 0 : opts->setuid = 0;
165 : 0 : opts->setgid = 0;
166 : 0 : opts->uid = GLOBAL_ROOT_UID;
167 : 0 : opts->gid = GLOBAL_ROOT_GID;
168 : 0 : opts->mode = DEVPTS_DEFAULT_MODE;
169 : 0 : opts->ptmxmode = DEVPTS_DEFAULT_PTMX_MODE;
170 : 0 : opts->max = NR_UNIX98_PTY_MAX;
171 : :
172 : : /* newinstance makes sense only on initial mount */
173 [ # # ]: 0 : if (op == PARSE_MOUNT)
174 : 0 : opts->newinstance = 0;
175 : :
176 [ # # ]: 0 : while ((p = strsep(&data, ",")) != NULL) {
177 : : substring_t args[MAX_OPT_ARGS];
178 : : int token;
179 : : int option;
180 : :
181 [ # # ]: 0 : if (!*p)
182 : 0 : continue;
183 : :
184 : 0 : token = match_token(p, tokens, args);
185 [ # # # # ]: 0 : switch (token) {
186 : : case Opt_uid:
187 [ # # ]: 0 : if (match_int(&args[0], &option))
188 : 0 : return -EINVAL;
189 : 0 : uid = make_kuid(current_user_ns(), option);
190 [ # # ]: 0 : if (!uid_valid(uid))
191 : : return -EINVAL;
192 : 0 : opts->uid = uid;
193 : 0 : opts->setuid = 1;
194 : 0 : break;
195 : : case Opt_gid:
196 [ # # ]: 0 : if (match_int(&args[0], &option))
197 : : return -EINVAL;
198 : 0 : gid = make_kgid(current_user_ns(), option);
199 [ # # ]: 0 : if (!gid_valid(gid))
200 : : return -EINVAL;
201 : 0 : opts->gid = gid;
202 : 0 : opts->setgid = 1;
203 : 0 : break;
204 : : case Opt_mode:
205 [ # # ]: 0 : if (match_octal(&args[0], &option))
206 : : return -EINVAL;
207 : 0 : opts->mode = option & S_IALLUGO;
208 : 0 : break;
209 : : #ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
210 : : case Opt_ptmxmode:
211 : : if (match_octal(&args[0], &option))
212 : : return -EINVAL;
213 : : opts->ptmxmode = option & S_IALLUGO;
214 : : break;
215 : : case Opt_newinstance:
216 : : /* newinstance makes sense only on initial mount */
217 : : if (op == PARSE_MOUNT)
218 : : opts->newinstance = 1;
219 : : break;
220 : : case Opt_max:
221 : : if (match_int(&args[0], &option) ||
222 : : option < 0 || option > NR_UNIX98_PTY_MAX)
223 : : return -EINVAL;
224 : : opts->max = option;
225 : : break;
226 : : #endif
227 : : default:
228 : 0 : printk(KERN_ERR "devpts: called with bogus options\n");
229 : 0 : return -EINVAL;
230 : : }
231 : : }
232 : :
233 : : return 0;
234 : : }
235 : :
236 : : #ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
237 : : static int mknod_ptmx(struct super_block *sb)
238 : : {
239 : : int mode;
240 : : int rc = -ENOMEM;
241 : : struct dentry *dentry;
242 : : struct inode *inode;
243 : : struct dentry *root = sb->s_root;
244 : : struct pts_fs_info *fsi = DEVPTS_SB(sb);
245 : : struct pts_mount_opts *opts = &fsi->mount_opts;
246 : : kuid_t root_uid;
247 : : kgid_t root_gid;
248 : :
249 : : root_uid = make_kuid(current_user_ns(), 0);
250 : : root_gid = make_kgid(current_user_ns(), 0);
251 : : if (!uid_valid(root_uid) || !gid_valid(root_gid))
252 : : return -EINVAL;
253 : :
254 : : mutex_lock(&root->d_inode->i_mutex);
255 : :
256 : : /* If we have already created ptmx node, return */
257 : : if (fsi->ptmx_dentry) {
258 : : rc = 0;
259 : : goto out;
260 : : }
261 : :
262 : : dentry = d_alloc_name(root, "ptmx");
263 : : if (!dentry) {
264 : : printk(KERN_NOTICE "Unable to alloc dentry for ptmx node\n");
265 : : goto out;
266 : : }
267 : :
268 : : /*
269 : : * Create a new 'ptmx' node in this mount of devpts.
270 : : */
271 : : inode = new_inode(sb);
272 : : if (!inode) {
273 : : printk(KERN_ERR "Unable to alloc inode for ptmx node\n");
274 : : dput(dentry);
275 : : goto out;
276 : : }
277 : :
278 : : inode->i_ino = 2;
279 : : inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
280 : :
281 : : mode = S_IFCHR|opts->ptmxmode;
282 : : init_special_inode(inode, mode, MKDEV(TTYAUX_MAJOR, 2));
283 : : inode->i_uid = root_uid;
284 : : inode->i_gid = root_gid;
285 : :
286 : : d_add(dentry, inode);
287 : :
288 : : fsi->ptmx_dentry = dentry;
289 : : rc = 0;
290 : : out:
291 : : mutex_unlock(&root->d_inode->i_mutex);
292 : : return rc;
293 : : }
294 : :
295 : : static void update_ptmx_mode(struct pts_fs_info *fsi)
296 : : {
297 : : struct inode *inode;
298 : : if (fsi->ptmx_dentry) {
299 : : inode = fsi->ptmx_dentry->d_inode;
300 : : inode->i_mode = S_IFCHR|fsi->mount_opts.ptmxmode;
301 : : }
302 : : }
303 : : #else
304 : : static inline void update_ptmx_mode(struct pts_fs_info *fsi)
305 : : {
306 : : return;
307 : : }
308 : : #endif
309 : :
310 : 0 : static int devpts_remount(struct super_block *sb, int *flags, char *data)
311 : : {
312 : : int err;
313 : : struct pts_fs_info *fsi = DEVPTS_SB(sb);
314 : 0 : struct pts_mount_opts *opts = &fsi->mount_opts;
315 : :
316 : 0 : err = parse_mount_options(data, PARSE_REMOUNT, opts);
317 : :
318 : : /*
319 : : * parse_mount_options() restores options to default values
320 : : * before parsing and may have changed ptmxmode. So, update the
321 : : * mode in the inode too. Bogus options don't fail the remount,
322 : : * so do this even on error return.
323 : : */
324 : : update_ptmx_mode(fsi);
325 : :
326 : 0 : return err;
327 : : }
328 : :
329 : 0 : static int devpts_show_options(struct seq_file *seq, struct dentry *root)
330 : : {
331 : 43 : struct pts_fs_info *fsi = DEVPTS_SB(root->d_sb);
332 : : struct pts_mount_opts *opts = &fsi->mount_opts;
333 : :
334 [ - + ]: 43 : if (opts->setuid)
335 : 0 : seq_printf(seq, ",uid=%u", from_kuid_munged(&init_user_ns, opts->uid));
336 [ - + ]: 43 : if (opts->setgid)
337 : 0 : seq_printf(seq, ",gid=%u", from_kgid_munged(&init_user_ns, opts->gid));
338 : 43 : seq_printf(seq, ",mode=%03o", opts->mode);
339 : : #ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
340 : : seq_printf(seq, ",ptmxmode=%03o", opts->ptmxmode);
341 : : if (opts->max < NR_UNIX98_PTY_MAX)
342 : : seq_printf(seq, ",max=%d", opts->max);
343 : : #endif
344 : :
345 : 43 : return 0;
346 : : }
347 : :
348 : : static const struct super_operations devpts_sops = {
349 : : .statfs = simple_statfs,
350 : : .remount_fs = devpts_remount,
351 : : .show_options = devpts_show_options,
352 : : };
353 : :
354 : 0 : static void *new_pts_fs_info(void)
355 : : {
356 : : struct pts_fs_info *fsi;
357 : :
358 : : fsi = kzalloc(sizeof(struct pts_fs_info), GFP_KERNEL);
359 [ # # ]: 0 : if (!fsi)
360 : : return NULL;
361 : :
362 : 0 : ida_init(&fsi->allocated_ptys);
363 : 0 : fsi->mount_opts.mode = DEVPTS_DEFAULT_MODE;
364 : 0 : fsi->mount_opts.ptmxmode = DEVPTS_DEFAULT_PTMX_MODE;
365 : :
366 : 0 : return fsi;
367 : : }
368 : :
369 : : static int
370 : 0 : devpts_fill_super(struct super_block *s, void *data, int silent)
371 : : {
372 : : struct inode *inode;
373 : :
374 : 0 : s->s_blocksize = 1024;
375 : 0 : s->s_blocksize_bits = 10;
376 : 0 : s->s_magic = DEVPTS_SUPER_MAGIC;
377 : 0 : s->s_op = &devpts_sops;
378 : 0 : s->s_time_gran = 1;
379 : :
380 : 0 : s->s_fs_info = new_pts_fs_info();
381 [ # # ]: 0 : if (!s->s_fs_info)
382 : : goto fail;
383 : :
384 : 0 : inode = new_inode(s);
385 [ # # ]: 0 : if (!inode)
386 : : goto fail;
387 : 0 : inode->i_ino = 1;
388 : 0 : inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
389 : 0 : inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
390 : 0 : inode->i_op = &simple_dir_inode_operations;
391 : 0 : inode->i_fop = &simple_dir_operations;
392 : 0 : set_nlink(inode, 2);
393 : :
394 : 0 : s->s_root = d_make_root(inode);
395 [ # # ]: 0 : if (s->s_root)
396 : : return 0;
397 : :
398 : 0 : printk(KERN_ERR "devpts: get root dentry failed\n");
399 : :
400 : : fail:
401 : : return -ENOMEM;
402 : : }
403 : :
404 : : #ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
405 : : static 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 : : * devpts_mount()
414 : : *
415 : : * If the '-o newinstance' mount option was specified, mount a new
416 : : * (private) instance of devpts. PTYs created in this instance are
417 : : * independent of the PTYs in other devpts instances.
418 : : *
419 : : * If the '-o newinstance' option was not specified, mount/remount the
420 : : * initial kernel mount of devpts. This type of mount gives the
421 : : * legacy, single-instance semantics.
422 : : *
423 : : * The 'newinstance' option is needed to support multiple namespace
424 : : * semantics in devpts while preserving backward compatibility of the
425 : : * current 'single-namespace' semantics. i.e all mounts of devpts
426 : : * without the 'newinstance' mount option should bind to the initial
427 : : * kernel mount, like mount_single().
428 : : *
429 : : * Mounts with 'newinstance' option create a new, private namespace.
430 : : *
431 : : * NOTE:
432 : : *
433 : : * For single-mount semantics, devpts cannot use mount_single(),
434 : : * because mount_single()/sget() find and use the super-block from
435 : : * the most recent mount of devpts. But that recent mount may be a
436 : : * 'newinstance' mount and mount_single() would pick the newinstance
437 : : * super-block instead of the initial super-block.
438 : : */
439 : : static 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 : : /* Require newinstance for all user namespace mounts to ensure
451 : : * the mount options are not changed.
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 : :
480 : : out_undo_sget:
481 : : deactivate_locked_super(s);
482 : : return ERR_PTR(error);
483 : : }
484 : :
485 : : #else
486 : : /*
487 : : * This supports only the legacy single-instance semantics (no
488 : : * multiple-instance semantics)
489 : : */
490 : 0 : static struct dentry *devpts_mount(struct file_system_type *fs_type, int flags,
491 : : const char *dev_name, void *data)
492 : : {
493 : 0 : return mount_single(fs_type, flags, data, devpts_fill_super);
494 : : }
495 : : #endif
496 : :
497 : 0 : static void devpts_kill_sb(struct super_block *sb)
498 : : {
499 : : struct pts_fs_info *fsi = DEVPTS_SB(sb);
500 : :
501 : 0 : ida_destroy(&fsi->allocated_ptys);
502 : 0 : kfree(fsi);
503 : 0 : kill_litter_super(sb);
504 : 0 : }
505 : :
506 : : static struct file_system_type devpts_fs_type = {
507 : : .name = "devpts",
508 : : .mount = devpts_mount,
509 : : .kill_sb = devpts_kill_sb,
510 : : #ifdef CONFIG_DEVPTS_MULTIPLE_INSTANCES
511 : : .fs_flags = FS_USERNS_MOUNT | FS_USERNS_DEV_MOUNT,
512 : : #endif
513 : : };
514 : :
515 : : /*
516 : : * The normal naming convention is simply /dev/pts/<number>; this conforms
517 : : * to the System V naming convention
518 : : */
519 : :
520 : 0 : int devpts_new_index(struct inode *ptmx_inode)
521 : : {
522 : 94 : struct super_block *sb = pts_sb_from_inode(ptmx_inode);
523 : : struct pts_fs_info *fsi = DEVPTS_SB(sb);
524 : : int index;
525 : : int ida_ret;
526 : :
527 : : retry:
528 [ + - ]: 94 : if (!ida_pre_get(&fsi->allocated_ptys, GFP_KERNEL))
529 : : return -ENOMEM;
530 : :
531 : 94 : mutex_lock(&allocated_ptys_lock);
532 [ - + ]: 94 : if (pty_count >= pty_limit -
533 [ - + ]: 94 : (fsi->mount_opts.newinstance ? pty_reserve : 0)) {
534 : 0 : mutex_unlock(&allocated_ptys_lock);
535 : 0 : return -ENOSPC;
536 : : }
537 : :
538 : : ida_ret = ida_get_new(&fsi->allocated_ptys, &index);
539 [ - + ]: 188 : if (ida_ret < 0) {
540 : 0 : mutex_unlock(&allocated_ptys_lock);
541 [ # # ]: 0 : if (ida_ret == -EAGAIN)
542 : : goto retry;
543 : : return -EIO;
544 : : }
545 : :
546 [ - + ]: 94 : if (index >= fsi->mount_opts.max) {
547 : 0 : ida_remove(&fsi->allocated_ptys, index);
548 : 0 : mutex_unlock(&allocated_ptys_lock);
549 : 0 : return -ENOSPC;
550 : : }
551 : 94 : pty_count++;
552 : 94 : mutex_unlock(&allocated_ptys_lock);
553 : 94 : return index;
554 : : }
555 : :
556 : 0 : void devpts_kill_index(struct inode *ptmx_inode, int idx)
557 : : {
558 : 94 : struct super_block *sb = pts_sb_from_inode(ptmx_inode);
559 : : struct pts_fs_info *fsi = DEVPTS_SB(sb);
560 : :
561 : 94 : mutex_lock(&allocated_ptys_lock);
562 : 94 : ida_remove(&fsi->allocated_ptys, idx);
563 : 94 : pty_count--;
564 : 94 : mutex_unlock(&allocated_ptys_lock);
565 : 94 : }
566 : :
567 : : /**
568 : : * devpts_pty_new -- create a new inode in /dev/pts/
569 : : * @ptmx_inode: inode of the master
570 : : * @device: major+minor of the node to be created
571 : : * @index: used as a name of the node
572 : : * @priv: what's given back by devpts_get_priv
573 : : *
574 : : * The created inode is returned. Remove it from /dev/pts/ by devpts_pty_kill.
575 : : */
576 : 0 : struct inode *devpts_pty_new(struct inode *ptmx_inode, dev_t device, int index,
577 : : void *priv)
578 : : {
579 : : struct dentry *dentry;
580 : 94 : struct super_block *sb = pts_sb_from_inode(ptmx_inode);
581 : : struct inode *inode;
582 : 94 : struct dentry *root = sb->s_root;
583 : : struct pts_fs_info *fsi = DEVPTS_SB(sb);
584 : : struct pts_mount_opts *opts = &fsi->mount_opts;
585 : : char s[12];
586 : :
587 : 94 : inode = new_inode(sb);
588 [ + - ]: 94 : if (!inode)
589 : : return ERR_PTR(-ENOMEM);
590 : :
591 : 94 : inode->i_ino = index + 3;
592 [ - + ]: 94 : inode->i_uid = opts->setuid ? opts->uid : current_fsuid();
593 [ - + ]: 94 : inode->i_gid = opts->setgid ? opts->gid : current_fsgid();
594 : 94 : inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
595 : 94 : init_special_inode(inode, S_IFCHR|opts->mode, device);
596 : 94 : inode->i_private = priv;
597 : :
598 : 94 : sprintf(s, "%d", index);
599 : :
600 : 94 : mutex_lock(&root->d_inode->i_mutex);
601 : :
602 : 94 : dentry = d_alloc_name(root, s);
603 [ + - ]: 94 : if (dentry) {
604 : : d_add(dentry, inode);
605 : 94 : fsnotify_create(root->d_inode, dentry);
606 : : } else {
607 : 0 : iput(inode);
608 : : inode = ERR_PTR(-ENOMEM);
609 : : }
610 : :
611 : 94 : mutex_unlock(&root->d_inode->i_mutex);
612 : :
613 : 94 : return inode;
614 : : }
615 : :
616 : : /**
617 : : * devpts_get_priv -- get private data for a slave
618 : : * @pts_inode: inode of the slave
619 : : *
620 : : * Returns whatever was passed as priv in devpts_pty_new for a given inode.
621 : : */
622 : 0 : void *devpts_get_priv(struct inode *pts_inode)
623 : : {
624 : : struct dentry *dentry;
625 : : void *priv = NULL;
626 : :
627 [ - + ]: 85 : BUG_ON(pts_inode->i_rdev == MKDEV(TTYAUX_MAJOR, PTMX_MINOR));
628 : :
629 : : /* Ensure dentry has not been deleted by devpts_pty_kill() */
630 : 85 : dentry = d_find_alias(pts_inode);
631 [ + - ]: 85 : if (!dentry)
632 : : return NULL;
633 : :
634 [ + - ]: 85 : if (pts_inode->i_sb->s_magic == DEVPTS_SUPER_MAGIC)
635 : 85 : priv = pts_inode->i_private;
636 : :
637 : 85 : dput(dentry);
638 : :
639 : 85 : return priv;
640 : : }
641 : :
642 : : /**
643 : : * devpts_pty_kill -- remove inode form /dev/pts/
644 : : * @inode: inode of the slave to be removed
645 : : *
646 : : * This is an inverse operation of devpts_pty_new.
647 : : */
648 : 0 : void devpts_pty_kill(struct inode *inode)
649 : : {
650 : : struct super_block *sb = pts_sb_from_inode(inode);
651 : 94 : struct dentry *root = sb->s_root;
652 : : struct dentry *dentry;
653 : :
654 [ - + ]: 94 : BUG_ON(inode->i_rdev == MKDEV(TTYAUX_MAJOR, PTMX_MINOR));
655 : :
656 : 94 : mutex_lock(&root->d_inode->i_mutex);
657 : :
658 : 94 : dentry = d_find_alias(inode);
659 : :
660 : 94 : drop_nlink(inode);
661 : 94 : d_delete(dentry);
662 : 94 : dput(dentry); /* d_alloc_name() in devpts_pty_new() */
663 : 94 : dput(dentry); /* d_find_alias above */
664 : :
665 : 94 : mutex_unlock(&root->d_inode->i_mutex);
666 : 94 : }
667 : :
668 : 0 : static int __init init_devpts_fs(void)
669 : : {
670 : 0 : int err = register_filesystem(&devpts_fs_type);
671 : : struct ctl_table_header *table;
672 : :
673 [ # # ]: 0 : if (!err) {
674 : 0 : table = register_sysctl_table(pty_root_table);
675 : 0 : devpts_mnt = kern_mount(&devpts_fs_type);
676 [ # # ]: 0 : if (IS_ERR(devpts_mnt)) {
677 : : err = PTR_ERR(devpts_mnt);
678 : 0 : unregister_filesystem(&devpts_fs_type);
679 : 0 : unregister_sysctl_table(table);
680 : : }
681 : : }
682 : 0 : return err;
683 : : }
684 : : module_init(init_devpts_fs)
|