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