Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * fs/inotify_user.c - inotify support for userspace
0004  *
0005  * Authors:
0006  *  John McCutchan  <ttb@tentacle.dhs.org>
0007  *  Robert Love <rml@novell.com>
0008  *
0009  * Copyright (C) 2005 John McCutchan
0010  * Copyright 2006 Hewlett-Packard Development Company, L.P.
0011  *
0012  * Copyright (C) 2009 Eric Paris <Red Hat Inc>
0013  * inotify was largely rewriten to make use of the fsnotify infrastructure
0014  */
0015 
0016 #include <linux/dcache.h> /* d_unlinked */
0017 #include <linux/fs.h> /* struct inode */
0018 #include <linux/fsnotify_backend.h>
0019 #include <linux/inotify.h>
0020 #include <linux/path.h> /* struct path */
0021 #include <linux/slab.h> /* kmem_* */
0022 #include <linux/types.h>
0023 #include <linux/sched.h>
0024 #include <linux/sched/user.h>
0025 #include <linux/sched/mm.h>
0026 
0027 #include "inotify.h"
0028 
0029 /*
0030  * Check if 2 events contain the same information.
0031  */
0032 static bool event_compare(struct fsnotify_event *old_fsn,
0033               struct fsnotify_event *new_fsn)
0034 {
0035     struct inotify_event_info *old, *new;
0036 
0037     old = INOTIFY_E(old_fsn);
0038     new = INOTIFY_E(new_fsn);
0039     if (old->mask & FS_IN_IGNORED)
0040         return false;
0041     if ((old->mask == new->mask) &&
0042         (old->wd == new->wd) &&
0043         (old->name_len == new->name_len) &&
0044         (!old->name_len || !strcmp(old->name, new->name)))
0045         return true;
0046     return false;
0047 }
0048 
0049 static int inotify_merge(struct fsnotify_group *group,
0050              struct fsnotify_event *event)
0051 {
0052     struct list_head *list = &group->notification_list;
0053     struct fsnotify_event *last_event;
0054 
0055     last_event = list_entry(list->prev, struct fsnotify_event, list);
0056     return event_compare(last_event, event);
0057 }
0058 
0059 int inotify_handle_inode_event(struct fsnotify_mark *inode_mark, u32 mask,
0060                    struct inode *inode, struct inode *dir,
0061                    const struct qstr *name, u32 cookie)
0062 {
0063     struct inotify_inode_mark *i_mark;
0064     struct inotify_event_info *event;
0065     struct fsnotify_event *fsn_event;
0066     struct fsnotify_group *group = inode_mark->group;
0067     int ret;
0068     int len = 0;
0069     int alloc_len = sizeof(struct inotify_event_info);
0070     struct mem_cgroup *old_memcg;
0071 
0072     if (name) {
0073         len = name->len;
0074         alloc_len += len + 1;
0075     }
0076 
0077     pr_debug("%s: group=%p mark=%p mask=%x\n", __func__, group, inode_mark,
0078          mask);
0079 
0080     i_mark = container_of(inode_mark, struct inotify_inode_mark,
0081                   fsn_mark);
0082 
0083     /*
0084      * Whoever is interested in the event, pays for the allocation. Do not
0085      * trigger OOM killer in the target monitoring memcg as it may have
0086      * security repercussion.
0087      */
0088     old_memcg = set_active_memcg(group->memcg);
0089     event = kmalloc(alloc_len, GFP_KERNEL_ACCOUNT | __GFP_RETRY_MAYFAIL);
0090     set_active_memcg(old_memcg);
0091 
0092     if (unlikely(!event)) {
0093         /*
0094          * Treat lost event due to ENOMEM the same way as queue
0095          * overflow to let userspace know event was lost.
0096          */
0097         fsnotify_queue_overflow(group);
0098         return -ENOMEM;
0099     }
0100 
0101     /*
0102      * We now report FS_ISDIR flag with MOVE_SELF and DELETE_SELF events
0103      * for fanotify. inotify never reported IN_ISDIR with those events.
0104      * It looks like an oversight, but to avoid the risk of breaking
0105      * existing inotify programs, mask the flag out from those events.
0106      */
0107     if (mask & (IN_MOVE_SELF | IN_DELETE_SELF))
0108         mask &= ~IN_ISDIR;
0109 
0110     fsn_event = &event->fse;
0111     fsnotify_init_event(fsn_event);
0112     event->mask = mask;
0113     event->wd = i_mark->wd;
0114     event->sync_cookie = cookie;
0115     event->name_len = len;
0116     if (len)
0117         strcpy(event->name, name->name);
0118 
0119     ret = fsnotify_add_event(group, fsn_event, inotify_merge);
0120     if (ret) {
0121         /* Our event wasn't used in the end. Free it. */
0122         fsnotify_destroy_event(group, fsn_event);
0123     }
0124 
0125     if (inode_mark->flags & FSNOTIFY_MARK_FLAG_IN_ONESHOT)
0126         fsnotify_destroy_mark(inode_mark, group);
0127 
0128     return 0;
0129 }
0130 
0131 static void inotify_freeing_mark(struct fsnotify_mark *fsn_mark, struct fsnotify_group *group)
0132 {
0133     inotify_ignored_and_remove_idr(fsn_mark, group);
0134 }
0135 
0136 /*
0137  * This is NEVER supposed to be called.  Inotify marks should either have been
0138  * removed from the idr when the watch was removed or in the
0139  * fsnotify_destroy_mark_by_group() call when the inotify instance was being
0140  * torn down.  This is only called if the idr is about to be freed but there
0141  * are still marks in it.
0142  */
0143 static int idr_callback(int id, void *p, void *data)
0144 {
0145     struct fsnotify_mark *fsn_mark;
0146     struct inotify_inode_mark *i_mark;
0147     static bool warned = false;
0148 
0149     if (warned)
0150         return 0;
0151 
0152     warned = true;
0153     fsn_mark = p;
0154     i_mark = container_of(fsn_mark, struct inotify_inode_mark, fsn_mark);
0155 
0156     WARN(1, "inotify closing but id=%d for fsn_mark=%p in group=%p still in "
0157         "idr.  Probably leaking memory\n", id, p, data);
0158 
0159     /*
0160      * I'm taking the liberty of assuming that the mark in question is a
0161      * valid address and I'm dereferencing it.  This might help to figure
0162      * out why we got here and the panic is no worse than the original
0163      * BUG() that was here.
0164      */
0165     if (fsn_mark)
0166         printk(KERN_WARNING "fsn_mark->group=%p wd=%d\n",
0167             fsn_mark->group, i_mark->wd);
0168     return 0;
0169 }
0170 
0171 static void inotify_free_group_priv(struct fsnotify_group *group)
0172 {
0173     /* ideally the idr is empty and we won't hit the BUG in the callback */
0174     idr_for_each(&group->inotify_data.idr, idr_callback, group);
0175     idr_destroy(&group->inotify_data.idr);
0176     if (group->inotify_data.ucounts)
0177         dec_inotify_instances(group->inotify_data.ucounts);
0178 }
0179 
0180 static void inotify_free_event(struct fsnotify_group *group,
0181                    struct fsnotify_event *fsn_event)
0182 {
0183     kfree(INOTIFY_E(fsn_event));
0184 }
0185 
0186 /* ding dong the mark is dead */
0187 static void inotify_free_mark(struct fsnotify_mark *fsn_mark)
0188 {
0189     struct inotify_inode_mark *i_mark;
0190 
0191     i_mark = container_of(fsn_mark, struct inotify_inode_mark, fsn_mark);
0192 
0193     kmem_cache_free(inotify_inode_mark_cachep, i_mark);
0194 }
0195 
0196 const struct fsnotify_ops inotify_fsnotify_ops = {
0197     .handle_inode_event = inotify_handle_inode_event,
0198     .free_group_priv = inotify_free_group_priv,
0199     .free_event = inotify_free_event,
0200     .freeing_mark = inotify_freeing_mark,
0201     .free_mark = inotify_free_mark,
0202 };