LCOV - code coverage report
Current view: top level - fs/devpts - inode.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 56 150 37.3 %
Date: 2014-02-18 Functions: 6 13 46.2 %
Branches: 15 64 23.4 %

           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                 :        384 :         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                 :        185 :         struct pts_fs_info *fsi = DEVPTS_SB(root->d_sb);
     332                 :            :         struct pts_mount_opts *opts = &fsi->mount_opts;
     333                 :            : 
     334         [ -  + ]:        185 :         if (opts->setuid)
     335                 :          0 :                 seq_printf(seq, ",uid=%u", from_kuid_munged(&init_user_ns, opts->uid));
     336         [ -  + ]:        185 :         if (opts->setgid)
     337                 :          0 :                 seq_printf(seq, ",gid=%u", from_kgid_munged(&init_user_ns, opts->gid));
     338                 :        185 :         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                 :        185 :         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                 :         96 :         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         [ +  - ]:         96 :         if (!ida_pre_get(&fsi->allocated_ptys, GFP_KERNEL))
     529                 :            :                 return -ENOMEM;
     530                 :            : 
     531                 :         96 :         mutex_lock(&allocated_ptys_lock);
     532         [ -  + ]:         96 :         if (pty_count >= pty_limit -
     533         [ -  + ]:         96 :                         (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         [ -  + ]:        192 :         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         [ -  + ]:         96 :         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                 :         96 :         pty_count++;
     552                 :         96 :         mutex_unlock(&allocated_ptys_lock);
     553                 :         96 :         return index;
     554                 :            : }
     555                 :            : 
     556                 :          0 : void devpts_kill_index(struct inode *ptmx_inode, int idx)
     557                 :            : {
     558                 :         96 :         struct super_block *sb = pts_sb_from_inode(ptmx_inode);
     559                 :            :         struct pts_fs_info *fsi = DEVPTS_SB(sb);
     560                 :            : 
     561                 :         96 :         mutex_lock(&allocated_ptys_lock);
     562                 :         96 :         ida_remove(&fsi->allocated_ptys, idx);
     563                 :         96 :         pty_count--;
     564                 :         96 :         mutex_unlock(&allocated_ptys_lock);
     565                 :         96 : }
     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                 :         96 :         struct super_block *sb = pts_sb_from_inode(ptmx_inode);
     581                 :            :         struct inode *inode;
     582                 :         96 :         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                 :         96 :         inode = new_inode(sb);
     588         [ +  - ]:         96 :         if (!inode)
     589                 :            :                 return ERR_PTR(-ENOMEM);
     590                 :            : 
     591                 :         96 :         inode->i_ino = index + 3;
     592         [ -  + ]:         96 :         inode->i_uid = opts->setuid ? opts->uid : current_fsuid();
     593         [ -  + ]:         96 :         inode->i_gid = opts->setgid ? opts->gid : current_fsgid();
     594                 :         96 :         inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
     595                 :         96 :         init_special_inode(inode, S_IFCHR|opts->mode, device);
     596                 :         96 :         inode->i_private = priv;
     597                 :            : 
     598                 :         96 :         sprintf(s, "%d", index);
     599                 :            : 
     600                 :         96 :         mutex_lock(&root->d_inode->i_mutex);
     601                 :            : 
     602                 :         96 :         dentry = d_alloc_name(root, s);
     603         [ +  - ]:         96 :         if (dentry) {
     604                 :            :                 d_add(dentry, inode);
     605                 :         96 :                 fsnotify_create(root->d_inode, dentry);
     606                 :            :         } else {
     607                 :          0 :                 iput(inode);
     608                 :            :                 inode = ERR_PTR(-ENOMEM);
     609                 :            :         }
     610                 :            : 
     611                 :         96 :         mutex_unlock(&root->d_inode->i_mutex);
     612                 :            : 
     613                 :         96 :         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         [ -  + ]:         87 :         BUG_ON(pts_inode->i_rdev == MKDEV(TTYAUX_MAJOR, PTMX_MINOR));
     628                 :            : 
     629                 :            :         /* Ensure dentry has not been deleted by devpts_pty_kill() */
     630                 :         87 :         dentry = d_find_alias(pts_inode);
     631         [ +  - ]:         87 :         if (!dentry)
     632                 :            :                 return NULL;
     633                 :            : 
     634         [ +  - ]:         87 :         if (pts_inode->i_sb->s_magic == DEVPTS_SUPER_MAGIC)
     635                 :         87 :                 priv = pts_inode->i_private;
     636                 :            : 
     637                 :         87 :         dput(dentry);
     638                 :            : 
     639                 :         87 :         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                 :         96 :         struct dentry *root = sb->s_root;
     652                 :            :         struct dentry *dentry;
     653                 :            : 
     654         [ -  + ]:         96 :         BUG_ON(inode->i_rdev == MKDEV(TTYAUX_MAJOR, PTMX_MINOR));
     655                 :            : 
     656                 :         96 :         mutex_lock(&root->d_inode->i_mutex);
     657                 :            : 
     658                 :         96 :         dentry = d_find_alias(inode);
     659                 :            : 
     660                 :         96 :         drop_nlink(inode);
     661                 :         96 :         d_delete(dentry);
     662                 :         96 :         dput(dentry);   /* d_alloc_name() in devpts_pty_new() */
     663                 :         96 :         dput(dentry);           /* d_find_alias above */
     664                 :            : 
     665                 :         96 :         mutex_unlock(&root->d_inode->i_mutex);
     666                 :         96 : }
     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)

Generated by: LCOV version 1.9