linux/fs/proc/inode.c
<<
>>
Prefs
   1/*
   2 *  linux/fs/proc/inode.c
   3 *
   4 *  Copyright (C) 1991, 1992  Linus Torvalds
   5 */
   6
   7#include <linux/time.h>
   8#include <linux/proc_fs.h>
   9#include <linux/kernel.h>
  10#include <linux/mm.h>
  11#include <linux/string.h>
  12#include <linux/stat.h>
  13#include <linux/completion.h>
  14#include <linux/poll.h>
  15#include <linux/file.h>
  16#include <linux/limits.h>
  17#include <linux/init.h>
  18#include <linux/module.h>
  19#include <linux/smp_lock.h>
  20#include <linux/sysctl.h>
  21
  22#include <asm/system.h>
  23#include <asm/uaccess.h>
  24
  25#include "internal.h"
  26
  27struct proc_dir_entry *de_get(struct proc_dir_entry *de)
  28{
  29        atomic_inc(&de->count);
  30        return de;
  31}
  32
  33/*
  34 * Decrements the use count and checks for deferred deletion.
  35 */
  36void de_put(struct proc_dir_entry *de)
  37{
  38        lock_kernel();
  39        if (!atomic_read(&de->count)) {
  40                printk("de_put: entry %s already free!\n", de->name);
  41                unlock_kernel();
  42                return;
  43        }
  44
  45        if (atomic_dec_and_test(&de->count))
  46                free_proc_entry(de);
  47        unlock_kernel();
  48}
  49
  50/*
  51 * Decrement the use count of the proc_dir_entry.
  52 */
  53static void proc_delete_inode(struct inode *inode)
  54{
  55        struct proc_dir_entry *de;
  56
  57        truncate_inode_pages(&inode->i_data, 0);
  58
  59        /* Stop tracking associated processes */
  60        put_pid(PROC_I(inode)->pid);
  61
  62        /* Let go of any associated proc directory entry */
  63        de = PROC_I(inode)->pde;
  64        if (de) {
  65                if (de->owner)
  66                        module_put(de->owner);
  67                de_put(de);
  68        }
  69        if (PROC_I(inode)->sysctl)
  70                sysctl_head_put(PROC_I(inode)->sysctl);
  71        clear_inode(inode);
  72}
  73
  74struct vfsmount *proc_mnt;
  75
  76static struct kmem_cache * proc_inode_cachep;
  77
  78static struct inode *proc_alloc_inode(struct super_block *sb)
  79{
  80        struct proc_inode *ei;
  81        struct inode *inode;
  82
  83        ei = (struct proc_inode *)kmem_cache_alloc(proc_inode_cachep, GFP_KERNEL);
  84        if (!ei)
  85                return NULL;
  86        ei->pid = NULL;
  87        ei->fd = 0;
  88        ei->op.proc_get_link = NULL;
  89        ei->pde = NULL;
  90        ei->sysctl = NULL;
  91        ei->sysctl_entry = NULL;
  92        inode = &ei->vfs_inode;
  93        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
  94        return inode;
  95}
  96
  97static void proc_destroy_inode(struct inode *inode)
  98{
  99        kmem_cache_free(proc_inode_cachep, PROC_I(inode));
 100}
 101
 102static void init_once(void *foo)
 103{
 104        struct proc_inode *ei = (struct proc_inode *) foo;
 105
 106        inode_init_once(&ei->vfs_inode);
 107}
 108
 109void __init proc_init_inodecache(void)
 110{
 111        proc_inode_cachep = kmem_cache_create("proc_inode_cache",
 112                                             sizeof(struct proc_inode),
 113                                             0, (SLAB_RECLAIM_ACCOUNT|
 114                                                SLAB_MEM_SPREAD|SLAB_PANIC),
 115                                             init_once);
 116}
 117
 118static const struct super_operations proc_sops = {
 119        .alloc_inode    = proc_alloc_inode,
 120        .destroy_inode  = proc_destroy_inode,
 121        .drop_inode     = generic_delete_inode,
 122        .delete_inode   = proc_delete_inode,
 123        .statfs         = simple_statfs,
 124};
 125
 126static void __pde_users_dec(struct proc_dir_entry *pde)
 127{
 128        pde->pde_users--;
 129        if (pde->pde_unload_completion && pde->pde_users == 0)
 130                complete(pde->pde_unload_completion);
 131}
 132
 133static void pde_users_dec(struct proc_dir_entry *pde)
 134{
 135        spin_lock(&pde->pde_unload_lock);
 136        __pde_users_dec(pde);
 137        spin_unlock(&pde->pde_unload_lock);
 138}
 139
 140static loff_t proc_reg_llseek(struct file *file, loff_t offset, int whence)
 141{
 142        struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
 143        loff_t rv = -EINVAL;
 144        loff_t (*llseek)(struct file *, loff_t, int);
 145
 146        spin_lock(&pde->pde_unload_lock);
 147        /*
 148         * remove_proc_entry() is going to delete PDE (as part of module
 149         * cleanup sequence). No new callers into module allowed.
 150         */
 151        if (!pde->proc_fops) {
 152                spin_unlock(&pde->pde_unload_lock);
 153                return rv;
 154        }
 155        /*
 156         * Bump refcount so that remove_proc_entry will wail for ->llseek to
 157         * complete.
 158         */
 159        pde->pde_users++;
 160        /*
 161         * Save function pointer under lock, to protect against ->proc_fops
 162         * NULL'ifying right after ->pde_unload_lock is dropped.
 163         */
 164        llseek = pde->proc_fops->llseek;
 165        spin_unlock(&pde->pde_unload_lock);
 166
 167        if (!llseek)
 168                llseek = default_llseek;
 169        rv = llseek(file, offset, whence);
 170
 171        pde_users_dec(pde);
 172        return rv;
 173}
 174
 175static ssize_t proc_reg_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 176{
 177        struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
 178        ssize_t rv = -EIO;
 179        ssize_t (*read)(struct file *, char __user *, size_t, loff_t *);
 180
 181        spin_lock(&pde->pde_unload_lock);
 182        if (!pde->proc_fops) {
 183                spin_unlock(&pde->pde_unload_lock);
 184                return rv;
 185        }
 186        pde->pde_users++;
 187        read = pde->proc_fops->read;
 188        spin_unlock(&pde->pde_unload_lock);
 189
 190        if (read)
 191                rv = read(file, buf, count, ppos);
 192
 193        pde_users_dec(pde);
 194        return rv;
 195}
 196
 197static ssize_t proc_reg_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
 198{
 199        struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
 200        ssize_t rv = -EIO;
 201        ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *);
 202
 203        spin_lock(&pde->pde_unload_lock);
 204        if (!pde->proc_fops) {
 205                spin_unlock(&pde->pde_unload_lock);
 206                return rv;
 207        }
 208        pde->pde_users++;
 209        write = pde->proc_fops->write;
 210        spin_unlock(&pde->pde_unload_lock);
 211
 212        if (write)
 213                rv = write(file, buf, count, ppos);
 214
 215        pde_users_dec(pde);
 216        return rv;
 217}
 218
 219static unsigned int proc_reg_poll(struct file *file, struct poll_table_struct *pts)
 220{
 221        struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
 222        unsigned int rv = DEFAULT_POLLMASK;
 223        unsigned int (*poll)(struct file *, struct poll_table_struct *);
 224
 225        spin_lock(&pde->pde_unload_lock);
 226        if (!pde->proc_fops) {
 227                spin_unlock(&pde->pde_unload_lock);
 228                return rv;
 229        }
 230        pde->pde_users++;
 231        poll = pde->proc_fops->poll;
 232        spin_unlock(&pde->pde_unload_lock);
 233
 234        if (poll)
 235                rv = poll(file, pts);
 236
 237        pde_users_dec(pde);
 238        return rv;
 239}
 240
 241static long proc_reg_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 242{
 243        struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
 244        long rv = -ENOTTY;
 245        long (*unlocked_ioctl)(struct file *, unsigned int, unsigned long);
 246        int (*ioctl)(struct inode *, struct file *, unsigned int, unsigned long);
 247
 248        spin_lock(&pde->pde_unload_lock);
 249        if (!pde->proc_fops) {
 250                spin_unlock(&pde->pde_unload_lock);
 251                return rv;
 252        }
 253        pde->pde_users++;
 254        unlocked_ioctl = pde->proc_fops->unlocked_ioctl;
 255        ioctl = pde->proc_fops->ioctl;
 256        spin_unlock(&pde->pde_unload_lock);
 257
 258        if (unlocked_ioctl) {
 259                rv = unlocked_ioctl(file, cmd, arg);
 260                if (rv == -ENOIOCTLCMD)
 261                        rv = -EINVAL;
 262        } else if (ioctl) {
 263                lock_kernel();
 264                rv = ioctl(file->f_path.dentry->d_inode, file, cmd, arg);
 265                unlock_kernel();
 266        }
 267
 268        pde_users_dec(pde);
 269        return rv;
 270}
 271
 272#ifdef CONFIG_COMPAT
 273static long proc_reg_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 274{
 275        struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
 276        long rv = -ENOTTY;
 277        long (*compat_ioctl)(struct file *, unsigned int, unsigned long);
 278
 279        spin_lock(&pde->pde_unload_lock);
 280        if (!pde->proc_fops) {
 281                spin_unlock(&pde->pde_unload_lock);
 282                return rv;
 283        }
 284        pde->pde_users++;
 285        compat_ioctl = pde->proc_fops->compat_ioctl;
 286        spin_unlock(&pde->pde_unload_lock);
 287
 288        if (compat_ioctl)
 289                rv = compat_ioctl(file, cmd, arg);
 290
 291        pde_users_dec(pde);
 292        return rv;
 293}
 294#endif
 295
 296static int proc_reg_mmap(struct file *file, struct vm_area_struct *vma)
 297{
 298        struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
 299        int rv = -EIO;
 300        int (*mmap)(struct file *, struct vm_area_struct *);
 301
 302        spin_lock(&pde->pde_unload_lock);
 303        if (!pde->proc_fops) {
 304                spin_unlock(&pde->pde_unload_lock);
 305                return rv;
 306        }
 307        pde->pde_users++;
 308        mmap = pde->proc_fops->mmap;
 309        spin_unlock(&pde->pde_unload_lock);
 310
 311        if (mmap)
 312                rv = mmap(file, vma);
 313
 314        pde_users_dec(pde);
 315        return rv;
 316}
 317
 318static int proc_reg_open(struct inode *inode, struct file *file)
 319{
 320        struct proc_dir_entry *pde = PDE(inode);
 321        int rv = 0;
 322        int (*open)(struct inode *, struct file *);
 323        int (*release)(struct inode *, struct file *);
 324        struct pde_opener *pdeo;
 325
 326        /*
 327         * What for, you ask? Well, we can have open, rmmod, remove_proc_entry
 328         * sequence. ->release won't be called because ->proc_fops will be
 329         * cleared. Depending on complexity of ->release, consequences vary.
 330         *
 331         * We can't wait for mercy when close will be done for real, it's
 332         * deadlockable: rmmod foo </proc/foo . So, we're going to do ->release
 333         * by hand in remove_proc_entry(). For this, save opener's credentials
 334         * for later.
 335         */
 336        pdeo = kmalloc(sizeof(struct pde_opener), GFP_KERNEL);
 337        if (!pdeo)
 338                return -ENOMEM;
 339
 340        spin_lock(&pde->pde_unload_lock);
 341        if (!pde->proc_fops) {
 342                spin_unlock(&pde->pde_unload_lock);
 343                kfree(pdeo);
 344                return -EINVAL;
 345        }
 346        pde->pde_users++;
 347        open = pde->proc_fops->open;
 348        release = pde->proc_fops->release;
 349        spin_unlock(&pde->pde_unload_lock);
 350
 351        if (open)
 352                rv = open(inode, file);
 353
 354        spin_lock(&pde->pde_unload_lock);
 355        if (rv == 0 && release) {
 356                /* To know what to release. */
 357                pdeo->inode = inode;
 358                pdeo->file = file;
 359                /* Strictly for "too late" ->release in proc_reg_release(). */
 360                pdeo->release = release;
 361                list_add(&pdeo->lh, &pde->pde_openers);
 362        } else
 363                kfree(pdeo);
 364        __pde_users_dec(pde);
 365        spin_unlock(&pde->pde_unload_lock);
 366        return rv;
 367}
 368
 369static struct pde_opener *find_pde_opener(struct proc_dir_entry *pde,
 370                                        struct inode *inode, struct file *file)
 371{
 372        struct pde_opener *pdeo;
 373
 374        list_for_each_entry(pdeo, &pde->pde_openers, lh) {
 375                if (pdeo->inode == inode && pdeo->file == file)
 376                        return pdeo;
 377        }
 378        return NULL;
 379}
 380
 381static int proc_reg_release(struct inode *inode, struct file *file)
 382{
 383        struct proc_dir_entry *pde = PDE(inode);
 384        int rv = 0;
 385        int (*release)(struct inode *, struct file *);
 386        struct pde_opener *pdeo;
 387
 388        spin_lock(&pde->pde_unload_lock);
 389        pdeo = find_pde_opener(pde, inode, file);
 390        if (!pde->proc_fops) {
 391                /*
 392                 * Can't simply exit, __fput() will think that everything is OK,
 393                 * and move on to freeing struct file. remove_proc_entry() will
 394                 * find slacker in opener's list and will try to do non-trivial
 395                 * things with struct file. Therefore, remove opener from list.
 396                 *
 397                 * But if opener is removed from list, who will ->release it?
 398                 */
 399                if (pdeo) {
 400                        list_del(&pdeo->lh);
 401                        spin_unlock(&pde->pde_unload_lock);
 402                        rv = pdeo->release(inode, file);
 403                        kfree(pdeo);
 404                } else
 405                        spin_unlock(&pde->pde_unload_lock);
 406                return rv;
 407        }
 408        pde->pde_users++;
 409        release = pde->proc_fops->release;
 410        if (pdeo) {
 411                list_del(&pdeo->lh);
 412                kfree(pdeo);
 413        }
 414        spin_unlock(&pde->pde_unload_lock);
 415
 416        if (release)
 417                rv = release(inode, file);
 418
 419        pde_users_dec(pde);
 420        return rv;
 421}
 422
 423static const struct file_operations proc_reg_file_ops = {
 424        .llseek         = proc_reg_llseek,
 425        .read           = proc_reg_read,
 426        .write          = proc_reg_write,
 427        .poll           = proc_reg_poll,
 428        .unlocked_ioctl = proc_reg_unlocked_ioctl,
 429#ifdef CONFIG_COMPAT
 430        .compat_ioctl   = proc_reg_compat_ioctl,
 431#endif
 432        .mmap           = proc_reg_mmap,
 433        .open           = proc_reg_open,
 434        .release        = proc_reg_release,
 435};
 436
 437#ifdef CONFIG_COMPAT
 438static const struct file_operations proc_reg_file_ops_no_compat = {
 439        .llseek         = proc_reg_llseek,
 440        .read           = proc_reg_read,
 441        .write          = proc_reg_write,
 442        .poll           = proc_reg_poll,
 443        .unlocked_ioctl = proc_reg_unlocked_ioctl,
 444        .mmap           = proc_reg_mmap,
 445        .open           = proc_reg_open,
 446        .release        = proc_reg_release,
 447};
 448#endif
 449
 450struct inode *proc_get_inode(struct super_block *sb, unsigned int ino,
 451                                struct proc_dir_entry *de)
 452{
 453        struct inode * inode;
 454
 455        if (!try_module_get(de->owner))
 456                goto out_mod;
 457
 458        inode = iget_locked(sb, ino);
 459        if (!inode)
 460                goto out_ino;
 461        if (inode->i_state & I_NEW) {
 462                inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
 463                PROC_I(inode)->fd = 0;
 464                PROC_I(inode)->pde = de;
 465
 466                if (de->mode) {
 467                        inode->i_mode = de->mode;
 468                        inode->i_uid = de->uid;
 469                        inode->i_gid = de->gid;
 470                }
 471                if (de->size)
 472                        inode->i_size = de->size;
 473                if (de->nlink)
 474                        inode->i_nlink = de->nlink;
 475                if (de->proc_iops)
 476                        inode->i_op = de->proc_iops;
 477                if (de->proc_fops) {
 478                        if (S_ISREG(inode->i_mode)) {
 479#ifdef CONFIG_COMPAT
 480                                if (!de->proc_fops->compat_ioctl)
 481                                        inode->i_fop =
 482                                                &proc_reg_file_ops_no_compat;
 483                                else
 484#endif
 485                                        inode->i_fop = &proc_reg_file_ops;
 486                        } else {
 487                                inode->i_fop = de->proc_fops;
 488                        }
 489                }
 490                unlock_new_inode(inode);
 491        } else
 492               module_put(de->owner);
 493        return inode;
 494
 495out_ino:
 496        module_put(de->owner);
 497out_mod:
 498        return NULL;
 499}                       
 500
 501int proc_fill_super(struct super_block *s)
 502{
 503        struct inode * root_inode;
 504
 505        s->s_flags |= MS_NODIRATIME | MS_NOSUID | MS_NOEXEC;
 506        s->s_blocksize = 1024;
 507        s->s_blocksize_bits = 10;
 508        s->s_magic = PROC_SUPER_MAGIC;
 509        s->s_op = &proc_sops;
 510        s->s_time_gran = 1;
 511        
 512        de_get(&proc_root);
 513        root_inode = proc_get_inode(s, PROC_ROOT_INO, &proc_root);
 514        if (!root_inode)
 515                goto out_no_root;
 516        root_inode->i_uid = 0;
 517        root_inode->i_gid = 0;
 518        s->s_root = d_alloc_root(root_inode);
 519        if (!s->s_root)
 520                goto out_no_root;
 521        return 0;
 522
 523out_no_root:
 524        printk("proc_read_super: get root inode failed\n");
 525        iput(root_inode);
 526        de_put(&proc_root);
 527        return -ENOMEM;
 528}
 529
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.