linux/fs/tracefs/inode.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 *  inode.c - part of tracefs, a pseudo file system for activating tracing
   4 *
   5 * Based on debugfs by: Greg Kroah-Hartman <greg@kroah.com>
   6 *
   7 *  Copyright (C) 2014 Red Hat Inc, author: Steven Rostedt <srostedt@redhat.com>
   8 *
   9 * tracefs is the file system that is used by the tracing infrastructure.
  10 */
  11
  12#include <linux/module.h>
  13#include <linux/fs.h>
  14#include <linux/mount.h>
  15#include <linux/kobject.h>
  16#include <linux/namei.h>
  17#include <linux/tracefs.h>
  18#include <linux/fsnotify.h>
  19#include <linux/seq_file.h>
  20#include <linux/parser.h>
  21#include <linux/magic.h>
  22#include <linux/slab.h>
  23
  24#define TRACEFS_DEFAULT_MODE    0700
  25
  26static struct vfsmount *tracefs_mount;
  27static int tracefs_mount_count;
  28static bool tracefs_registered;
  29
  30static ssize_t default_read_file(struct file *file, char __user *buf,
  31                                 size_t count, loff_t *ppos)
  32{
  33        return 0;
  34}
  35
  36static ssize_t default_write_file(struct file *file, const char __user *buf,
  37                                   size_t count, loff_t *ppos)
  38{
  39        return count;
  40}
  41
  42static const struct file_operations tracefs_file_operations = {
  43        .read =         default_read_file,
  44        .write =        default_write_file,
  45        .open =         simple_open,
  46        .llseek =       noop_llseek,
  47};
  48
  49static struct tracefs_dir_ops {
  50        int (*mkdir)(const char *name);
  51        int (*rmdir)(const char *name);
  52} tracefs_ops __ro_after_init;
  53
  54static char *get_dname(struct dentry *dentry)
  55{
  56        const char *dname;
  57        char *name;
  58        int len = dentry->d_name.len;
  59
  60        dname = dentry->d_name.name;
  61        name = kmalloc(len + 1, GFP_KERNEL);
  62        if (!name)
  63                return NULL;
  64        memcpy(name, dname, len);
  65        name[len] = 0;
  66        return name;
  67}
  68
  69static int tracefs_syscall_mkdir(struct inode *inode, struct dentry *dentry, umode_t mode)
  70{
  71        char *name;
  72        int ret;
  73
  74        name = get_dname(dentry);
  75        if (!name)
  76                return -ENOMEM;
  77
  78        /*
  79         * The mkdir call can call the generic functions that create
  80         * the files within the tracefs system. It is up to the individual
  81         * mkdir routine to handle races.
  82         */
  83        inode_unlock(inode);
  84        ret = tracefs_ops.mkdir(name);
  85        inode_lock(inode);
  86
  87        kfree(name);
  88
  89        return ret;
  90}
  91
  92static int tracefs_syscall_rmdir(struct inode *inode, struct dentry *dentry)
  93{
  94        char *name;
  95        int ret;
  96
  97        name = get_dname(dentry);
  98        if (!name)
  99                return -ENOMEM;
 100
 101        /*
 102         * The rmdir call can call the generic functions that create
 103         * the files within the tracefs system. It is up to the individual
 104         * rmdir routine to handle races.
 105         * This time we need to unlock not only the parent (inode) but
 106         * also the directory that is being deleted.
 107         */
 108        inode_unlock(inode);
 109        inode_unlock(dentry->d_inode);
 110
 111        ret = tracefs_ops.rmdir(name);
 112
 113        inode_lock_nested(inode, I_MUTEX_PARENT);
 114        inode_lock(dentry->d_inode);
 115
 116        kfree(name);
 117
 118        return ret;
 119}
 120
 121static const struct inode_operations tracefs_dir_inode_operations = {
 122        .lookup         = simple_lookup,
 123        .mkdir          = tracefs_syscall_mkdir,
 124        .rmdir          = tracefs_syscall_rmdir,
 125};
 126
 127static struct inode *tracefs_get_inode(struct super_block *sb)
 128{
 129        struct inode *inode = new_inode(sb);
 130        if (inode) {
 131                inode->i_ino = get_next_ino();
 132                inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
 133        }
 134        return inode;
 135}
 136
 137struct tracefs_mount_opts {
 138        kuid_t uid;
 139        kgid_t gid;
 140        umode_t mode;
 141};
 142
 143enum {
 144        Opt_uid,
 145        Opt_gid,
 146        Opt_mode,
 147        Opt_err
 148};
 149
 150static const match_table_t tokens = {
 151        {Opt_uid, "uid=%u"},
 152        {Opt_gid, "gid=%u"},
 153        {Opt_mode, "mode=%o"},
 154        {Opt_err, NULL}
 155};
 156
 157struct tracefs_fs_info {
 158        struct tracefs_mount_opts mount_opts;
 159};
 160
 161static int tracefs_parse_options(char *data, struct tracefs_mount_opts *opts)
 162{
 163        substring_t args[MAX_OPT_ARGS];
 164        int option;
 165        int token;
 166        kuid_t uid;
 167        kgid_t gid;
 168        char *p;
 169
 170        opts->mode = TRACEFS_DEFAULT_MODE;
 171
 172        while ((p = strsep(&data, ",")) != NULL) {
 173                if (!*p)
 174                        continue;
 175
 176                token = match_token(p, tokens, args);
 177                switch (token) {
 178                case Opt_uid:
 179                        if (match_int(&args[0], &option))
 180                                return -EINVAL;
 181                        uid = make_kuid(current_user_ns(), option);
 182                        if (!uid_valid(uid))
 183                                return -EINVAL;
 184                        opts->uid = uid;
 185                        break;
 186                case Opt_gid:
 187                        if (match_int(&args[0], &option))
 188                                return -EINVAL;
 189                        gid = make_kgid(current_user_ns(), option);
 190                        if (!gid_valid(gid))
 191                                return -EINVAL;
 192                        opts->gid = gid;
 193                        break;
 194                case Opt_mode:
 195                        if (match_octal(&args[0], &option))
 196                                return -EINVAL;
 197                        opts->mode = option & S_IALLUGO;
 198                        break;
 199                /*
 200                 * We might like to report bad mount options here;
 201                 * but traditionally tracefs has ignored all mount options
 202                 */
 203                }
 204        }
 205
 206        return 0;
 207}
 208
 209static int tracefs_apply_options(struct super_block *sb)
 210{
 211        struct tracefs_fs_info *fsi = sb->s_fs_info;
 212        struct inode *inode = sb->s_root->d_inode;
 213        struct tracefs_mount_opts *opts = &fsi->mount_opts;
 214
 215        inode->i_mode &= ~S_IALLUGO;
 216        inode->i_mode |= opts->mode;
 217
 218        inode->i_uid = opts->uid;
 219        inode->i_gid = opts->gid;
 220
 221        return 0;
 222}
 223
 224static int tracefs_remount(struct super_block *sb, int *flags, char *data)
 225{
 226        int err;
 227        struct tracefs_fs_info *fsi = sb->s_fs_info;
 228
 229        sync_filesystem(sb);
 230        err = tracefs_parse_options(data, &fsi->mount_opts);
 231        if (err)
 232                goto fail;
 233
 234        tracefs_apply_options(sb);
 235
 236fail:
 237        return err;
 238}
 239
 240static int tracefs_show_options(struct seq_file *m, struct dentry *root)
 241{
 242        struct tracefs_fs_info *fsi = root->d_sb->s_fs_info;
 243        struct tracefs_mount_opts *opts = &fsi->mount_opts;
 244
 245        if (!uid_eq(opts->uid, GLOBAL_ROOT_UID))
 246                seq_printf(m, ",uid=%u",
 247                           from_kuid_munged(&init_user_ns, opts->uid));
 248        if (!gid_eq(opts->gid, GLOBAL_ROOT_GID))
 249                seq_printf(m, ",gid=%u",
 250                           from_kgid_munged(&init_user_ns, opts->gid));
 251        if (opts->mode != TRACEFS_DEFAULT_MODE)
 252                seq_printf(m, ",mode=%o", opts->mode);
 253
 254        return 0;
 255}
 256
 257static const struct super_operations tracefs_super_operations = {
 258        .statfs         = simple_statfs,
 259        .remount_fs     = tracefs_remount,
 260        .show_options   = tracefs_show_options,
 261};
 262
 263static int trace_fill_super(struct super_block *sb, void *data, int silent)
 264{
 265        static const struct tree_descr trace_files[] = {{""}};
 266        struct tracefs_fs_info *fsi;
 267        int err;
 268
 269        fsi = kzalloc(sizeof(struct tracefs_fs_info), GFP_KERNEL);
 270        sb->s_fs_info = fsi;
 271        if (!fsi) {
 272                err = -ENOMEM;
 273                goto fail;
 274        }
 275
 276        err = tracefs_parse_options(data, &fsi->mount_opts);
 277        if (err)
 278                goto fail;
 279
 280        err  =  simple_fill_super(sb, TRACEFS_MAGIC, trace_files);
 281        if (err)
 282                goto fail;
 283
 284        sb->s_op = &tracefs_super_operations;
 285
 286        tracefs_apply_options(sb);
 287
 288        return 0;
 289
 290fail:
 291        kfree(fsi);
 292        sb->s_fs_info = NULL;
 293        return err;
 294}
 295
 296static struct dentry *trace_mount(struct file_system_type *fs_type,
 297                        int flags, const char *dev_name,
 298                        void *data)
 299{
 300        return mount_single(fs_type, flags, data, trace_fill_super);
 301}
 302
 303static struct file_system_type trace_fs_type = {
 304        .owner =        THIS_MODULE,
 305        .name =         "tracefs",
 306        .mount =        trace_mount,
 307        .kill_sb =      kill_litter_super,
 308};
 309MODULE_ALIAS_FS("tracefs");
 310
 311static struct dentry *start_creating(const char *name, struct dentry *parent)
 312{
 313        struct dentry *dentry;
 314        int error;
 315
 316        pr_debug("tracefs: creating file '%s'\n",name);
 317
 318        error = simple_pin_fs(&trace_fs_type, &tracefs_mount,
 319                              &tracefs_mount_count);
 320        if (error)
 321                return ERR_PTR(error);
 322
 323        /* If the parent is not specified, we create it in the root.
 324         * We need the root dentry to do this, which is in the super
 325         * block. A pointer to that is in the struct vfsmount that we
 326         * have around.
 327         */
 328        if (!parent)
 329                parent = tracefs_mount->mnt_root;
 330
 331        inode_lock(parent->d_inode);
 332        dentry = lookup_one_len(name, parent, strlen(name));
 333        if (!IS_ERR(dentry) && dentry->d_inode) {
 334                dput(dentry);
 335                dentry = ERR_PTR(-EEXIST);
 336        }
 337
 338        if (IS_ERR(dentry)) {
 339                inode_unlock(parent->d_inode);
 340                simple_release_fs(&tracefs_mount, &tracefs_mount_count);
 341        }
 342
 343        return dentry;
 344}
 345
 346static struct dentry *failed_creating(struct dentry *dentry)
 347{
 348        inode_unlock(dentry->d_parent->d_inode);
 349        dput(dentry);
 350        simple_release_fs(&tracefs_mount, &tracefs_mount_count);
 351        return NULL;
 352}
 353
 354static struct dentry *end_creating(struct dentry *dentry)
 355{
 356        inode_unlock(dentry->d_parent->d_inode);
 357        return dentry;
 358}
 359
 360/**
 361 * tracefs_create_file - create a file in the tracefs filesystem
 362 * @name: a pointer to a string containing the name of the file to create.
 363 * @mode: the permission that the file should have.
 364 * @parent: a pointer to the parent dentry for this file.  This should be a
 365 *          directory dentry if set.  If this parameter is NULL, then the
 366 *          file will be created in the root of the tracefs filesystem.
 367 * @data: a pointer to something that the caller will want to get to later
 368 *        on.  The inode.i_private pointer will point to this value on
 369 *        the open() call.
 370 * @fops: a pointer to a struct file_operations that should be used for
 371 *        this file.
 372 *
 373 * This is the basic "create a file" function for tracefs.  It allows for a
 374 * wide range of flexibility in creating a file, or a directory (if you want
 375 * to create a directory, the tracefs_create_dir() function is
 376 * recommended to be used instead.)
 377 *
 378 * This function will return a pointer to a dentry if it succeeds.  This
 379 * pointer must be passed to the tracefs_remove() function when the file is
 380 * to be removed (no automatic cleanup happens if your module is unloaded,
 381 * you are responsible here.)  If an error occurs, %NULL will be returned.
 382 *
 383 * If tracefs is not enabled in the kernel, the value -%ENODEV will be
 384 * returned.
 385 */
 386struct dentry *tracefs_create_file(const char *name, umode_t mode,
 387                                   struct dentry *parent, void *data,
 388                                   const struct file_operations *fops)
 389{
 390        struct dentry *dentry;
 391        struct inode *inode;
 392
 393        if (!(mode & S_IFMT))
 394                mode |= S_IFREG;
 395        BUG_ON(!S_ISREG(mode));
 396        dentry = start_creating(name, parent);
 397
 398        if (IS_ERR(dentry))
 399                return NULL;
 400
 401        inode = tracefs_get_inode(dentry->d_sb);
 402        if (unlikely(!inode))
 403                return failed_creating(dentry);
 404
 405        inode->i_mode = mode;
 406        inode->i_fop = fops ? fops : &tracefs_file_operations;
 407        inode->i_private = data;
 408        d_instantiate(dentry, inode);
 409        fsnotify_create(dentry->d_parent->d_inode, dentry);
 410        return end_creating(dentry);
 411}
 412
 413static struct dentry *__create_dir(const char *name, struct dentry *parent,
 414                                   const struct inode_operations *ops)
 415{
 416        struct dentry *dentry = start_creating(name, parent);
 417        struct inode *inode;
 418
 419        if (IS_ERR(dentry))
 420                return NULL;
 421
 422        inode = tracefs_get_inode(dentry->d_sb);
 423        if (unlikely(!inode))
 424                return failed_creating(dentry);
 425
 426        inode->i_mode = S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO;
 427        inode->i_op = ops;
 428        inode->i_fop = &simple_dir_operations;
 429
 430        /* directory inodes start off with i_nlink == 2 (for "." entry) */
 431        inc_nlink(inode);
 432        d_instantiate(dentry, inode);
 433        inc_nlink(dentry->d_parent->d_inode);
 434        fsnotify_mkdir(dentry->d_parent->d_inode, dentry);
 435        return end_creating(dentry);
 436}
 437
 438/**
 439 * tracefs_create_dir - create a directory in the tracefs filesystem
 440 * @name: a pointer to a string containing the name of the directory to
 441 *        create.
 442 * @parent: a pointer to the parent dentry for this file.  This should be a
 443 *          directory dentry if set.  If this parameter is NULL, then the
 444 *          directory will be created in the root of the tracefs filesystem.
 445 *
 446 * This function creates a directory in tracefs with the given name.
 447 *
 448 * This function will return a pointer to a dentry if it succeeds.  This
 449 * pointer must be passed to the tracefs_remove() function when the file is
 450 * to be removed. If an error occurs, %NULL will be returned.
 451 *
 452 * If tracing is not enabled in the kernel, the value -%ENODEV will be
 453 * returned.
 454 */
 455struct dentry *tracefs_create_dir(const char *name, struct dentry *parent)
 456{
 457        return __create_dir(name, parent, &simple_dir_inode_operations);
 458}
 459
 460/**
 461 * tracefs_create_instance_dir - create the tracing instances directory
 462 * @name: The name of the instances directory to create
 463 * @parent: The parent directory that the instances directory will exist
 464 * @mkdir: The function to call when a mkdir is performed.
 465 * @rmdir: The function to call when a rmdir is performed.
 466 *
 467 * Only one instances directory is allowed.
 468 *
 469 * The instances directory is special as it allows for mkdir and rmdir to
 470 * to be done by userspace. When a mkdir or rmdir is performed, the inode
 471 * locks are released and the methhods passed in (@mkdir and @rmdir) are
 472 * called without locks and with the name of the directory being created
 473 * within the instances directory.
 474 *
 475 * Returns the dentry of the instances directory.
 476 */
 477__init struct dentry *tracefs_create_instance_dir(const char *name,
 478                                          struct dentry *parent,
 479                                          int (*mkdir)(const char *name),
 480                                          int (*rmdir)(const char *name))
 481{
 482        struct dentry *dentry;
 483
 484        /* Only allow one instance of the instances directory. */
 485        if (WARN_ON(tracefs_ops.mkdir || tracefs_ops.rmdir))
 486                return NULL;
 487
 488        dentry = __create_dir(name, parent, &tracefs_dir_inode_operations);
 489        if (!dentry)
 490                return NULL;
 491
 492        tracefs_ops.mkdir = mkdir;
 493        tracefs_ops.rmdir = rmdir;
 494
 495        return dentry;
 496}
 497
 498static int __tracefs_remove(struct dentry *dentry, struct dentry *parent)
 499{
 500        int ret = 0;
 501
 502        if (simple_positive(dentry)) {
 503                if (dentry->d_inode) {
 504                        dget(dentry);
 505                        switch (dentry->d_inode->i_mode & S_IFMT) {
 506                        case S_IFDIR:
 507                                ret = simple_rmdir(parent->d_inode, dentry);
 508                                if (!ret)
 509                                        fsnotify_rmdir(parent->d_inode, dentry);
 510                                break;
 511                        default:
 512                                simple_unlink(parent->d_inode, dentry);
 513                                fsnotify_unlink(parent->d_inode, dentry);
 514                                break;
 515                        }
 516                        if (!ret)
 517                                d_delete(dentry);
 518                        dput(dentry);
 519                }
 520        }
 521        return ret;
 522}
 523
 524/**
 525 * tracefs_remove - removes a file or directory from the tracefs filesystem
 526 * @dentry: a pointer to a the dentry of the file or directory to be
 527 *          removed.
 528 *
 529 * This function removes a file or directory in tracefs that was previously
 530 * created with a call to another tracefs function (like
 531 * tracefs_create_file() or variants thereof.)
 532 */
 533void tracefs_remove(struct dentry *dentry)
 534{
 535        struct dentry *parent;
 536        int ret;
 537
 538        if (IS_ERR_OR_NULL(dentry))
 539                return;
 540
 541        parent = dentry->d_parent;
 542        inode_lock(parent->d_inode);
 543        ret = __tracefs_remove(dentry, parent);
 544        inode_unlock(parent->d_inode);
 545        if (!ret)
 546                simple_release_fs(&tracefs_mount, &tracefs_mount_count);
 547}
 548
 549/**
 550 * tracefs_remove_recursive - recursively removes a directory
 551 * @dentry: a pointer to a the dentry of the directory to be removed.
 552 *
 553 * This function recursively removes a directory tree in tracefs that
 554 * was previously created with a call to another tracefs function
 555 * (like tracefs_create_file() or variants thereof.)
 556 */
 557void tracefs_remove_recursive(struct dentry *dentry)
 558{
 559        struct dentry *child, *parent;
 560
 561        if (IS_ERR_OR_NULL(dentry))
 562                return;
 563
 564        parent = dentry;
 565 down:
 566        inode_lock(parent->d_inode);
 567 loop:
 568        /*
 569         * The parent->d_subdirs is protected by the d_lock. Outside that
 570         * lock, the child can be unlinked and set to be freed which can
 571         * use the d_u.d_child as the rcu head and corrupt this list.
 572         */
 573        spin_lock(&parent->d_lock);
 574        list_for_each_entry(child, &parent->d_subdirs, d_child) {
 575                if (!simple_positive(child))
 576                        continue;
 577
 578                /* perhaps simple_empty(child) makes more sense */
 579                if (!list_empty(&child->d_subdirs)) {
 580                        spin_unlock(&parent->d_lock);
 581                        inode_unlock(parent->d_inode);
 582                        parent = child;
 583                        goto down;
 584                }
 585
 586                spin_unlock(&parent->d_lock);
 587
 588                if (!__tracefs_remove(child, parent))
 589                        simple_release_fs(&tracefs_mount, &tracefs_mount_count);
 590
 591                /*
 592                 * The parent->d_lock protects agaist child from unlinking
 593                 * from d_subdirs. When releasing the parent->d_lock we can
 594                 * no longer trust that the next pointer is valid.
 595                 * Restart the loop. We'll skip this one with the
 596                 * simple_positive() check.
 597                 */
 598                goto loop;
 599        }
 600        spin_unlock(&parent->d_lock);
 601
 602        inode_unlock(parent->d_inode);
 603        child = parent;
 604        parent = parent->d_parent;
 605        inode_lock(parent->d_inode);
 606
 607        if (child != dentry)
 608                /* go up */
 609                goto loop;
 610
 611        if (!__tracefs_remove(child, parent))
 612                simple_release_fs(&tracefs_mount, &tracefs_mount_count);
 613        inode_unlock(parent->d_inode);
 614}
 615
 616/**
 617 * tracefs_initialized - Tells whether tracefs has been registered
 618 */
 619bool tracefs_initialized(void)
 620{
 621        return tracefs_registered;
 622}
 623
 624static int __init tracefs_init(void)
 625{
 626        int retval;
 627
 628        retval = sysfs_create_mount_point(kernel_kobj, "tracing");
 629        if (retval)
 630                return -EINVAL;
 631
 632        retval = register_filesystem(&trace_fs_type);
 633        if (!retval)
 634                tracefs_registered = true;
 635
 636        return retval;
 637}
 638core_initcall(tracefs_init);
 639