Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linux-davinci
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
linux
linux-davinci
Commits
b8ed8e7c
Commit
b8ed8e7c
authored
Sep 16, 2009
by
Stephen Rothwell
Browse files
Options
Browse Files
Download
Plain Diff
Merge commit 'fsnotify/for-next'
parents
93b7074e
cf71f3cf
Changes
23
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
23 changed files
with
730 additions
and
526 deletions
+730
-526
Documentation/feature-removal-schedule.txt
Documentation/feature-removal-schedule.txt
+7
-0
fs/compat.c
fs/compat.c
+2
-3
fs/exec.c
fs/exec.c
+2
-2
fs/nfsd/vfs.c
fs/nfsd/vfs.c
+2
-2
fs/notify/dnotify/dnotify.c
fs/notify/dnotify/dnotify.c
+4
-4
fs/notify/fsnotify.c
fs/notify/fsnotify.c
+12
-4
fs/notify/group.c
fs/notify/group.c
+3
-47
fs/notify/inode_mark.c
fs/notify/inode_mark.c
+17
-7
fs/notify/inotify/inotify_fsnotify.c
fs/notify/inotify/inotify_fsnotify.c
+57
-2
fs/notify/inotify/inotify_user.c
fs/notify/inotify/inotify_user.c
+148
-71
fs/notify/notification.c
fs/notify/notification.c
+90
-71
fs/open.c
fs/open.c
+1
-1
fs/read_write.c
fs/read_write.c
+4
-4
include/linux/fsnotify.h
include/linux/fsnotify.h
+24
-20
include/linux/fsnotify_backend.h
include/linux/fsnotify_backend.h
+18
-12
init/Kconfig
init/Kconfig
+7
-3
kernel/Makefile
kernel/Makefile
+3
-2
kernel/audit.c
kernel/audit.c
+0
-1
kernel/audit.h
kernel/audit.h
+16
-10
kernel/audit_tree.c
kernel/audit_tree.c
+124
-99
kernel/audit_watch.c
kernel/audit_watch.c
+170
-126
kernel/auditfilter.c
kernel/auditfilter.c
+12
-27
kernel/auditsc.c
kernel/auditsc.c
+7
-8
No files found.
Documentation/feature-removal-schedule.txt
View file @
b8ed8e7c
...
@@ -426,6 +426,13 @@ When: 2.6.33
...
@@ -426,6 +426,13 @@ When: 2.6.33
Why: Should be implemented in userspace, policy daemon.
Why: Should be implemented in userspace, policy daemon.
Who: Johannes Berg <johannes@sipsolutions.net>
Who: Johannes Berg <johannes@sipsolutions.net>
---------------------------
What: CONFIG_INOTIFY
When: 2.6.33
Why: No known users, fsnotify more generic and more easily maintained.
Who: Eric Paris <eparis@redhat.com>
----------------------------
----------------------------
What: CONFIG_X86_OLD_MCE
What: CONFIG_X86_OLD_MCE
...
...
fs/compat.c
View file @
b8ed8e7c
...
@@ -1177,11 +1177,10 @@ out:
...
@@ -1177,11 +1177,10 @@ out:
if
(
iov
!=
iovstack
)
if
(
iov
!=
iovstack
)
kfree
(
iov
);
kfree
(
iov
);
if
((
ret
+
(
type
==
READ
))
>
0
)
{
if
((
ret
+
(
type
==
READ
))
>
0
)
{
struct
dentry
*
dentry
=
file
->
f_path
.
dentry
;
if
(
type
==
READ
)
if
(
type
==
READ
)
fsnotify_access
(
dentry
);
fsnotify_access
(
file
);
else
else
fsnotify_modify
(
dentry
);
fsnotify_modify
(
file
);
}
}
return
ret
;
return
ret
;
}
}
...
...
fs/exec.c
View file @
b8ed8e7c
...
@@ -128,7 +128,7 @@ SYSCALL_DEFINE1(uselib, const char __user *, library)
...
@@ -128,7 +128,7 @@ SYSCALL_DEFINE1(uselib, const char __user *, library)
if
(
file
->
f_path
.
mnt
->
mnt_flags
&
MNT_NOEXEC
)
if
(
file
->
f_path
.
mnt
->
mnt_flags
&
MNT_NOEXEC
)
goto
exit
;
goto
exit
;
fsnotify_open
(
file
->
f_path
.
dentry
);
fsnotify_open
(
file
);
error
=
-
ENOEXEC
;
error
=
-
ENOEXEC
;
if
(
file
->
f_op
)
{
if
(
file
->
f_op
)
{
...
@@ -663,7 +663,7 @@ struct file *open_exec(const char *name)
...
@@ -663,7 +663,7 @@ struct file *open_exec(const char *name)
if
(
file
->
f_path
.
mnt
->
mnt_flags
&
MNT_NOEXEC
)
if
(
file
->
f_path
.
mnt
->
mnt_flags
&
MNT_NOEXEC
)
goto
exit
;
goto
exit
;
fsnotify_open
(
file
->
f_path
.
dentry
);
fsnotify_open
(
file
);
err
=
deny_write_access
(
file
);
err
=
deny_write_access
(
file
);
if
(
err
)
if
(
err
)
...
...
fs/nfsd/vfs.c
View file @
b8ed8e7c
...
@@ -951,7 +951,7 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
...
@@ -951,7 +951,7 @@ nfsd_vfs_read(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
nfsdstats
.
io_read
+=
host_err
;
nfsdstats
.
io_read
+=
host_err
;
*
count
=
host_err
;
*
count
=
host_err
;
err
=
0
;
err
=
0
;
fsnotify_access
(
file
->
f_path
.
dentry
);
fsnotify_access
(
file
);
}
else
}
else
err
=
nfserrno
(
host_err
);
err
=
nfserrno
(
host_err
);
out:
out:
...
@@ -1062,7 +1062,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
...
@@ -1062,7 +1062,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
goto
out_nfserr
;
goto
out_nfserr
;
*
cnt
=
host_err
;
*
cnt
=
host_err
;
nfsdstats
.
io_write
+=
host_err
;
nfsdstats
.
io_write
+=
host_err
;
fsnotify_modify
(
file
->
f_path
.
dentry
);
fsnotify_modify
(
file
);
/* clear setuid/setgid flag after write */
/* clear setuid/setgid flag after write */
if
(
inode
->
i_mode
&
(
S_ISUID
|
S_ISGID
))
if
(
inode
->
i_mode
&
(
S_ISUID
|
S_ISGID
))
...
...
fs/notify/dnotify/dnotify.c
View file @
b8ed8e7c
...
@@ -132,7 +132,8 @@ static int dnotify_handle_event(struct fsnotify_group *group,
...
@@ -132,7 +132,8 @@ static int dnotify_handle_event(struct fsnotify_group *group,
* userspace notification for that pair.
* userspace notification for that pair.
*/
*/
static
bool
dnotify_should_send_event
(
struct
fsnotify_group
*
group
,
static
bool
dnotify_should_send_event
(
struct
fsnotify_group
*
group
,
struct
inode
*
inode
,
__u32
mask
)
struct
inode
*
inode
,
__u32
mask
,
void
*
data
,
int
data_type
)
{
{
struct
fsnotify_mark_entry
*
entry
;
struct
fsnotify_mark_entry
*
entry
;
bool
send
;
bool
send
;
...
@@ -361,7 +362,7 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg)
...
@@ -361,7 +362,7 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg)
dnentry
=
container_of
(
entry
,
struct
dnotify_mark_entry
,
fsn_entry
);
dnentry
=
container_of
(
entry
,
struct
dnotify_mark_entry
,
fsn_entry
);
spin_lock
(
&
entry
->
lock
);
spin_lock
(
&
entry
->
lock
);
}
else
{
}
else
{
fsnotify_add_mark
(
new_entry
,
dnotify_group
,
inode
);
fsnotify_add_mark
(
new_entry
,
dnotify_group
,
inode
,
0
);
spin_lock
(
&
new_entry
->
lock
);
spin_lock
(
&
new_entry
->
lock
);
entry
=
new_entry
;
entry
=
new_entry
;
dnentry
=
new_dnentry
;
dnentry
=
new_dnentry
;
...
@@ -431,8 +432,7 @@ static int __init dnotify_init(void)
...
@@ -431,8 +432,7 @@ static int __init dnotify_init(void)
dnotify_struct_cache
=
KMEM_CACHE
(
dnotify_struct
,
SLAB_PANIC
);
dnotify_struct_cache
=
KMEM_CACHE
(
dnotify_struct
,
SLAB_PANIC
);
dnotify_mark_entry_cache
=
KMEM_CACHE
(
dnotify_mark_entry
,
SLAB_PANIC
);
dnotify_mark_entry_cache
=
KMEM_CACHE
(
dnotify_mark_entry
,
SLAB_PANIC
);
dnotify_group
=
fsnotify_obtain_group
(
DNOTIFY_GROUP_NUM
,
dnotify_group
=
fsnotify_obtain_group
(
0
,
&
dnotify_fsnotify_ops
);
0
,
&
dnotify_fsnotify_ops
);
if
(
IS_ERR
(
dnotify_group
))
if
(
IS_ERR
(
dnotify_group
))
panic
(
"unable to allocate fsnotify group for dnotify
\n
"
);
panic
(
"unable to allocate fsnotify group for dnotify
\n
"
);
return
0
;
return
0
;
...
...
fs/notify/fsnotify.c
View file @
b8ed8e7c
...
@@ -77,13 +77,16 @@ void __fsnotify_update_child_dentry_flags(struct inode *inode)
...
@@ -77,13 +77,16 @@ void __fsnotify_update_child_dentry_flags(struct inode *inode)
}
}
/* Notify this dentry's parent about a child's events. */
/* Notify this dentry's parent about a child's events. */
void
__fsnotify_parent
(
struct
dentry
*
dentry
,
__u32
mask
)
void
__fsnotify_parent
(
struct
file
*
file
,
struct
dentry
*
dentry
,
__u32
mask
)
{
{
struct
dentry
*
parent
;
struct
dentry
*
parent
;
struct
inode
*
p_inode
;
struct
inode
*
p_inode
;
bool
send
=
false
;
bool
send
=
false
;
bool
should_update_children
=
false
;
bool
should_update_children
=
false
;
if
(
file
)
dentry
=
file
->
f_path
.
dentry
;
if
(
!
(
dentry
->
d_flags
&
DCACHE_FSNOTIFY_PARENT_WATCHED
))
if
(
!
(
dentry
->
d_flags
&
DCACHE_FSNOTIFY_PARENT_WATCHED
))
return
;
return
;
...
@@ -114,6 +117,10 @@ void __fsnotify_parent(struct dentry *dentry, __u32 mask)
...
@@ -114,6 +117,10 @@ void __fsnotify_parent(struct dentry *dentry, __u32 mask)
* specifies these are events which came from a child. */
* specifies these are events which came from a child. */
mask
|=
FS_EVENT_ON_CHILD
;
mask
|=
FS_EVENT_ON_CHILD
;
if
(
file
)
fsnotify
(
p_inode
,
mask
,
file
,
FSNOTIFY_EVENT_FILE
,
dentry
->
d_name
.
name
,
0
);
else
fsnotify
(
p_inode
,
mask
,
dentry
->
d_inode
,
FSNOTIFY_EVENT_INODE
,
fsnotify
(
p_inode
,
mask
,
dentry
->
d_inode
,
FSNOTIFY_EVENT_INODE
,
dentry
->
d_name
.
name
,
0
);
dentry
->
d_name
.
name
,
0
);
dput
(
parent
);
dput
(
parent
);
...
@@ -156,7 +163,8 @@ void fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, const
...
@@ -156,7 +163,8 @@ void fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is, const
idx
=
srcu_read_lock
(
&
fsnotify_grp_srcu
);
idx
=
srcu_read_lock
(
&
fsnotify_grp_srcu
);
list_for_each_entry_rcu
(
group
,
&
fsnotify_groups
,
group_list
)
{
list_for_each_entry_rcu
(
group
,
&
fsnotify_groups
,
group_list
)
{
if
(
test_mask
&
group
->
mask
)
{
if
(
test_mask
&
group
->
mask
)
{
if
(
!
group
->
ops
->
should_send_event
(
group
,
to_tell
,
mask
))
if
(
!
group
->
ops
->
should_send_event
(
group
,
to_tell
,
mask
,
data
,
data_is
))
continue
;
continue
;
if
(
!
event
)
{
if
(
!
event
)
{
event
=
fsnotify_create_event
(
to_tell
,
mask
,
data
,
event
=
fsnotify_create_event
(
to_tell
,
mask
,
data
,
...
...
fs/notify/group.c
View file @
b8ed8e7c
...
@@ -77,15 +77,6 @@ void fsnotify_recalc_group_mask(struct fsnotify_group *group)
...
@@ -77,15 +77,6 @@ void fsnotify_recalc_group_mask(struct fsnotify_group *group)
fsnotify_recalc_global_mask
();
fsnotify_recalc_global_mask
();
}
}
/*
* Take a reference to a group so things found under the fsnotify_grp_mutex
* can't get freed under us
*/
static
void
fsnotify_get_group
(
struct
fsnotify_group
*
group
)
{
atomic_inc
(
&
group
->
refcnt
);
}
/*
/*
* Final freeing of a group
* Final freeing of a group
*/
*/
...
@@ -170,51 +161,24 @@ void fsnotify_put_group(struct fsnotify_group *group)
...
@@ -170,51 +161,24 @@ void fsnotify_put_group(struct fsnotify_group *group)
fsnotify_destroy_group
(
group
);
fsnotify_destroy_group
(
group
);
}
}
/*
* Simply run the fsnotify_groups list and find a group which matches
* the given parameters. If a group is found we take a reference to that
* group.
*/
static
struct
fsnotify_group
*
fsnotify_find_group
(
unsigned
int
group_num
,
__u32
mask
,
const
struct
fsnotify_ops
*
ops
)
{
struct
fsnotify_group
*
group_iter
;
struct
fsnotify_group
*
group
=
NULL
;
BUG_ON
(
!
mutex_is_locked
(
&
fsnotify_grp_mutex
));
list_for_each_entry_rcu
(
group_iter
,
&
fsnotify_groups
,
group_list
)
{
if
(
group_iter
->
group_num
==
group_num
)
{
if
((
group_iter
->
mask
==
mask
)
&&
(
group_iter
->
ops
==
ops
))
{
fsnotify_get_group
(
group_iter
);
group
=
group_iter
;
}
else
group
=
ERR_PTR
(
-
EEXIST
);
}
}
return
group
;
}
/*
/*
* Either finds an existing group which matches the group_num, mask, and ops or
* Either finds an existing group which matches the group_num, mask, and ops or
* creates a new group and adds it to the global group list. In either case we
* creates a new group and adds it to the global group list. In either case we
* take a reference for the group returned.
* take a reference for the group returned.
*/
*/
struct
fsnotify_group
*
fsnotify_obtain_group
(
unsigned
int
group_num
,
__u32
mask
,
struct
fsnotify_group
*
fsnotify_obtain_group
(
__u32
mask
,
const
struct
fsnotify_ops
*
ops
)
const
struct
fsnotify_ops
*
ops
)
{
{
struct
fsnotify_group
*
group
,
*
tgroup
;
struct
fsnotify_group
*
group
;
/* very low use, simpler locking if we just always alloc */
/* very low use, simpler locking if we just always alloc */
group
=
k
m
alloc
(
sizeof
(
struct
fsnotify_group
),
GFP_KERNEL
);
group
=
k
z
alloc
(
sizeof
(
struct
fsnotify_group
),
GFP_KERNEL
);
if
(
!
group
)
if
(
!
group
)
return
ERR_PTR
(
-
ENOMEM
);
return
ERR_PTR
(
-
ENOMEM
);
atomic_set
(
&
group
->
refcnt
,
1
);
atomic_set
(
&
group
->
refcnt
,
1
);
group
->
on_group_list
=
0
;
group
->
on_group_list
=
0
;
group
->
group_num
=
group_num
;
group
->
mask
=
mask
;
group
->
mask
=
mask
;
mutex_init
(
&
group
->
notification_mutex
);
mutex_init
(
&
group
->
notification_mutex
);
...
@@ -230,14 +194,6 @@ struct fsnotify_group *fsnotify_obtain_group(unsigned int group_num, __u32 mask,
...
@@ -230,14 +194,6 @@ struct fsnotify_group *fsnotify_obtain_group(unsigned int group_num, __u32 mask,
group
->
ops
=
ops
;
group
->
ops
=
ops
;
mutex_lock
(
&
fsnotify_grp_mutex
);
mutex_lock
(
&
fsnotify_grp_mutex
);
tgroup
=
fsnotify_find_group
(
group_num
,
mask
,
ops
);
if
(
tgroup
)
{
/* group already exists */
mutex_unlock
(
&
fsnotify_grp_mutex
);
/* destroy the new one we made */
fsnotify_put_group
(
group
);
return
tgroup
;
}
/* group not found, add a new one */
/* group not found, add a new one */
list_add_rcu
(
&
group
->
group_list
,
&
fsnotify_groups
);
list_add_rcu
(
&
group
->
group_list
,
&
fsnotify_groups
);
...
...
fs/notify/inode_mark.c
View file @
b8ed8e7c
...
@@ -283,12 +283,20 @@ struct fsnotify_mark_entry *fsnotify_find_mark_entry(struct fsnotify_group *grou
...
@@ -283,12 +283,20 @@ struct fsnotify_mark_entry *fsnotify_find_mark_entry(struct fsnotify_group *grou
return
NULL
;
return
NULL
;
}
}
void
fsnotify_duplicate_mark
(
struct
fsnotify_mark_entry
*
new
,
struct
fsnotify_mark_entry
*
old
)
{
assert_spin_locked
(
&
old
->
lock
);
new
->
inode
=
old
->
inode
;
new
->
group
=
old
->
group
;
new
->
mask
=
old
->
mask
;
new
->
free_mark
=
old
->
free_mark
;
}
/*
/*
* Nothing fancy, just initialize lists and locks and counters.
* Nothing fancy, just initialize lists and locks and counters.
*/
*/
void
fsnotify_init_mark
(
struct
fsnotify_mark_entry
*
entry
,
void
fsnotify_init_mark
(
struct
fsnotify_mark_entry
*
entry
,
void
(
*
free_mark
)(
struct
fsnotify_mark_entry
*
entry
))
void
(
*
free_mark
)(
struct
fsnotify_mark_entry
*
entry
))
{
{
spin_lock_init
(
&
entry
->
lock
);
spin_lock_init
(
&
entry
->
lock
);
atomic_set
(
&
entry
->
refcnt
,
1
);
atomic_set
(
&
entry
->
refcnt
,
1
);
...
@@ -305,9 +313,10 @@ void fsnotify_init_mark(struct fsnotify_mark_entry *entry,
...
@@ -305,9 +313,10 @@ void fsnotify_init_mark(struct fsnotify_mark_entry *entry,
* event types should be delivered to which group and for which inodes.
* event types should be delivered to which group and for which inodes.
*/
*/
int
fsnotify_add_mark
(
struct
fsnotify_mark_entry
*
entry
,
int
fsnotify_add_mark
(
struct
fsnotify_mark_entry
*
entry
,
struct
fsnotify_group
*
group
,
struct
inode
*
inode
)
struct
fsnotify_group
*
group
,
struct
inode
*
inode
,
int
allow_dups
)
{
{
struct
fsnotify_mark_entry
*
lentry
;
struct
fsnotify_mark_entry
*
lentry
=
NULL
;
int
ret
=
0
;
int
ret
=
0
;
inode
=
igrab
(
inode
);
inode
=
igrab
(
inode
);
...
@@ -324,11 +333,12 @@ int fsnotify_add_mark(struct fsnotify_mark_entry *entry,
...
@@ -324,11 +333,12 @@ int fsnotify_add_mark(struct fsnotify_mark_entry *entry,
spin_lock
(
&
group
->
mark_lock
);
spin_lock
(
&
group
->
mark_lock
);
spin_lock
(
&
inode
->
i_lock
);
spin_lock
(
&
inode
->
i_lock
);
if
(
!
allow_dups
)
lentry
=
fsnotify_find_mark_entry
(
group
,
inode
);
if
(
!
lentry
)
{
entry
->
group
=
group
;
entry
->
group
=
group
;
entry
->
inode
=
inode
;
entry
->
inode
=
inode
;
lentry
=
fsnotify_find_mark_entry
(
group
,
inode
);
if
(
!
lentry
)
{
hlist_add_head
(
&
entry
->
i_list
,
&
inode
->
i_fsnotify_mark_entries
);
hlist_add_head
(
&
entry
->
i_list
,
&
inode
->
i_fsnotify_mark_entries
);
list_add
(
&
entry
->
g_list
,
&
group
->
mark_entries
);
list_add
(
&
entry
->
g_list
,
&
group
->
mark_entries
);
...
...
fs/notify/inotify/inotify_fsnotify.c
View file @
b8ed8e7c
...
@@ -31,6 +31,60 @@
...
@@ -31,6 +31,60 @@
#include "inotify.h"
#include "inotify.h"
/*
* Check if 2 events contain the same information. We do not compare private data
* but at this moment that isn't a problem for any know fsnotify listeners.
*/
static
bool
event_compare
(
struct
fsnotify_event
*
old
,
struct
fsnotify_event
*
new
)
{
if
((
old
->
mask
==
new
->
mask
)
&&
(
old
->
to_tell
==
new
->
to_tell
)
&&
(
old
->
data_type
==
new
->
data_type
)
&&
(
old
->
name_len
==
new
->
name_len
))
{
switch
(
old
->
data_type
)
{
case
(
FSNOTIFY_EVENT_INODE
):
/* remember, after old was put on the wait_q we aren't
* allowed to look at the inode any more, only thing
* left to check was if the file_name is the same */
if
(
old
->
name_len
&&
!
strcmp
(
old
->
file_name
,
new
->
file_name
))
return
true
;
break
;
case
(
FSNOTIFY_EVENT_PATH
):
if
((
old
->
path
.
mnt
==
new
->
path
.
mnt
)
&&
(
old
->
path
.
dentry
==
new
->
path
.
dentry
))
return
true
;
break
;
case
(
FSNOTIFY_EVENT_NONE
):
if
(
old
->
mask
&
FS_Q_OVERFLOW
)
return
true
;
else
if
(
old
->
mask
&
FS_IN_IGNORED
)
return
false
;
return
true
;
};
}
return
false
;
}
static
int
inotify_merge
(
struct
list_head
*
list
,
struct
fsnotify_event
*
event
)
{
struct
fsnotify_event_holder
*
last_holder
;
struct
fsnotify_event
*
last_event
;
int
ret
=
0
;
/* and the list better be locked by something too */
spin_lock
(
&
event
->
lock
);
last_holder
=
list_entry
(
list
->
prev
,
struct
fsnotify_event_holder
,
event_list
);
last_event
=
last_holder
->
event
;
if
(
event_compare
(
last_event
,
event
))
ret
=
-
EEXIST
;
spin_unlock
(
&
event
->
lock
);
return
ret
;
}
static
int
inotify_handle_event
(
struct
fsnotify_group
*
group
,
struct
fsnotify_event
*
event
)
static
int
inotify_handle_event
(
struct
fsnotify_group
*
group
,
struct
fsnotify_event
*
event
)
{
{
struct
fsnotify_mark_entry
*
entry
;
struct
fsnotify_mark_entry
*
entry
;
...
@@ -61,7 +115,7 @@ static int inotify_handle_event(struct fsnotify_group *group, struct fsnotify_ev
...
@@ -61,7 +115,7 @@ static int inotify_handle_event(struct fsnotify_group *group, struct fsnotify_ev
fsn_event_priv
->
group
=
group
;
fsn_event_priv
->
group
=
group
;
event_priv
->
wd
=
wd
;
event_priv
->
wd
=
wd
;
ret
=
fsnotify_add_notify_event
(
group
,
event
,
fsn_event_priv
);
ret
=
fsnotify_add_notify_event
(
group
,
event
,
fsn_event_priv
,
inotify_merge
);
if
(
ret
)
{
if
(
ret
)
{
inotify_free_event_priv
(
fsn_event_priv
);
inotify_free_event_priv
(
fsn_event_priv
);
/* EEXIST says we tail matched, EOVERFLOW isn't something
/* EEXIST says we tail matched, EOVERFLOW isn't something
...
@@ -85,7 +139,8 @@ static void inotify_freeing_mark(struct fsnotify_mark_entry *entry, struct fsnot
...
@@ -85,7 +139,8 @@ static void inotify_freeing_mark(struct fsnotify_mark_entry *entry, struct fsnot
inotify_ignored_and_remove_idr
(
entry
,
group
);
inotify_ignored_and_remove_idr
(
entry
,
group
);
}
}
static
bool
inotify_should_send_event
(
struct
fsnotify_group
*
group
,
struct
inode
*
inode
,
__u32
mask
)
static
bool
inotify_should_send_event
(
struct
fsnotify_group
*
group
,
struct
inode
*
inode
,
__u32
mask
,
void
*
data
,
int
data_type
)
{
{
struct
fsnotify_mark_entry
*
entry
;
struct
fsnotify_mark_entry
*
entry
;
bool
send
;
bool
send
;
...
...
fs/notify/inotify/inotify_user.c
View file @
b8ed8e7c
This diff is collapsed.
Click to expand it.
fs/notify/notification.c
View file @
b8ed8e7c
...
@@ -56,7 +56,7 @@ static struct kmem_cache *fsnotify_event_holder_cachep;
...
@@ -56,7 +56,7 @@ static struct kmem_cache *fsnotify_event_holder_cachep;
* it is needed. It's refcnt is set 1 at kernel init time and will never
* it is needed. It's refcnt is set 1 at kernel init time and will never
* get set to 0 so it will never get 'freed'
* get set to 0 so it will never get 'freed'
*/
*/
static
struct
fsnotify_event
q_overflow_event
;
static
struct
fsnotify_event
*
q_overflow_event
;
static
atomic_t
fsnotify_sync_cookie
=
ATOMIC_INIT
(
0
);
static
atomic_t
fsnotify_sync_cookie
=
ATOMIC_INIT
(
0
);
/**
/**
...
@@ -104,6 +104,7 @@ struct fsnotify_event_holder *fsnotify_alloc_event_holder(void)
...
@@ -104,6 +104,7 @@ struct fsnotify_event_holder *fsnotify_alloc_event_holder(void)
void
fsnotify_destroy_event_holder
(
struct
fsnotify_event_holder
*
holder
)
void
fsnotify_destroy_event_holder
(
struct
fsnotify_event_holder
*
holder
)
{
{
if
(
holder
)
kmem_cache_free
(
fsnotify_event_holder_cachep
,
holder
);
kmem_cache_free
(
fsnotify_event_holder_cachep
,
holder
);
}
}
...
@@ -128,54 +129,18 @@ struct fsnotify_event_private_data *fsnotify_remove_priv_from_event(struct fsnot
...
@@ -128,54 +129,18 @@ struct fsnotify_event_private_data *fsnotify_remove_priv_from_event(struct fsnot
return
priv
;
return
priv
;
}
}
/*
* Check if 2 events contain the same information. We do not compare private data
* but at this moment that isn't a problem for any know fsnotify listeners.
*/
static
bool
event_compare
(
struct
fsnotify_event
*
old
,
struct
fsnotify_event
*
new
)
{
if
((
old
->
mask
==
new
->
mask
)
&&
(
old
->
to_tell
==
new
->
to_tell
)
&&
(
old
->
data_type
==
new
->
data_type
)
&&
(
old
->
name_len
==
new
->
name_len
))
{
switch
(
old
->
data_type
)
{
case
(
FSNOTIFY_EVENT_INODE
):
/* remember, after old was put on the wait_q we aren't
* allowed to look at the inode any more, only thing
* left to check was if the file_name is the same */
if
(
old
->
name_len
&&
!
strcmp
(
old
->
file_name
,
new
->
file_name
))
return
true
;
break
;
case
(
FSNOTIFY_EVENT_PATH
):
if
((
old
->
path
.
mnt
==
new
->
path
.
mnt
)
&&
(
old
->
path
.
dentry
==
new
->
path
.
dentry
))
return
true
;
break
;
case
(
FSNOTIFY_EVENT_NONE
):
if
(
old
->
mask
&
FS_Q_OVERFLOW
)
return
true
;
else
if
(
old
->
mask
&
FS_IN_IGNORED
)
return
false
;
return
false
;
};
}
return
false
;
}
/*
/*
* Add an event to the group notification queue. The group can later pull this
* Add an event to the group notification queue. The group can later pull this
* event off the queue to deal with. If the event is successfully added to the
* event off the queue to deal with. If the event is successfully added to the
* group's notification queue, a reference is taken on event.
* group's notification queue, a reference is taken on event.
*/
*/
int
fsnotify_add_notify_event
(
struct
fsnotify_group
*
group
,
struct
fsnotify_event
*
event
,
int
fsnotify_add_notify_event
(
struct
fsnotify_group
*
group
,
struct
fsnotify_event
*
event
,
struct
fsnotify_event_private_data
*
priv
)
struct
fsnotify_event_private_data
*
priv
,
int
(
*
merge
)(
struct
list_head
*
,
struct
fsnotify_event
*
))
{
{
struct
fsnotify_event_holder
*
holder
=
NULL
;
struct
fsnotify_event_holder
*
holder
=
NULL
;
struct
list_head
*
list
=
&
group
->
notification_list
;
struct
list_head
*
list
=
&
group
->
notification_list
;
struct
fsnotify_event_holder
*
last_holder
;
int
rc
=
0
;
struct
fsnotify_event
*
last_event
;
int
ret
=
0
;
/*
/*
* There is one fsnotify_event_holder embedded inside each fsnotify_event.
* There is one fsnotify_event_holder embedded inside each fsnotify_event.
...
@@ -195,12 +160,24 @@ alloc_holder:
...
@@ -195,12 +160,24 @@ alloc_holder:
mutex_lock
(
&
group
->
notification_mutex
);
mutex_lock
(
&
group
->
notification_mutex
);
if
(
group
->
q_len
>=
group
->
max_events
)
{
if
(
group
->
q_len
>=
group
->
max_events
)
{
event
=
&
q_overflow_event
;
event
=
q_overflow_event
;
r
et
=
-
EOVERFLOW
;
r
c
=
-
EOVERFLOW
;
/* sorry, no private data on the overflow event */
/* sorry, no private data on the overflow event */
priv
=
NULL
;
priv
=
NULL
;
}
}
if
(
!
list_empty
(
list
)
&&
merge
)
{
int
ret
;
ret
=
merge
(
list
,
event
);
if
(
ret
)
{
mutex_unlock
(
&
group
->
notification_mutex
);
if
(
holder
!=
&
event
->
holder
)
fsnotify_destroy_event_holder
(
holder
);
return
ret
;
}
}
spin_lock
(
&
event
->
lock
);
spin_lock
(
&
event
->
lock
);
if
(
list_empty
(
&
event
->
holder
.
event_list
))
{
if
(
list_empty
(
&
event
->
holder
.
event_list
))
{
...
@@ -215,18 +192,6 @@ alloc_holder:
...
@@ -215,18 +192,6 @@ alloc_holder:
goto
alloc_holder
;
goto
alloc_holder
;
}
}
if
(
!
list_empty
(
list
))
{
last_holder
=
list_entry
(
list
->
prev
,
struct
fsnotify_event_holder
,
event_list
);
last_event
=
last_holder
->
event
;
if
(
event_compare
(
last_event
,
event
))
{
spin_unlock
(
&
event
->
lock
);
mutex_unlock
(
&
group
->
notification_mutex
);
if
(
holder
!=
&
event
->
holder
)
fsnotify_destroy_event_holder
(
holder
);
return
-
EEXIST
;
}
}
group
->
q_len
++
;
group
->
q_len
++
;
holder
->
event
=
event
;
holder
->
event
=
event
;
...
@@ -238,7 +203,7 @@ alloc_holder:
...
@@ -238,7 +203,7 @@ alloc_holder:
mutex_unlock
(
&
group
->
notification_mutex
);
mutex_unlock
(
&
group
->
notification_mutex
);
wake_up
(
&
group
->
notification_waitq
);
wake_up
(
&
group
->
notification_waitq
);
return
r
et
;
return
r
c
;
}
}
/*
/*
...
@@ -314,25 +279,77 @@ void fsnotify_flush_notify(struct fsnotify_group *group)
...
@@ -314,25 +279,77 @@ void fsnotify_flush_notify(struct fsnotify_group *group)
static
void
initialize_event
(
struct
fsnotify_event
*
event
)
static
void
initialize_event
(
struct
fsnotify_event
*
event
)
{
{
event
->
holder
.
event
=
NULL
;
INIT_LIST_HEAD
(
&
event
->
holder
.
event_list
);
INIT_LIST_HEAD
(
&
event
->
holder
.
event_list
);
atomic_set
(
&
event
->
refcnt
,
1
);
atomic_set
(
&
event
->
refcnt
,
1
);
spin_lock_init
(
&
event
->
lock
);
spin_lock_init
(
&
event
->
lock
);
event
->
path
.
dentry
=
NULL
;
event
->
path
.
mnt
=
NULL
;
event
->
inode
=
NULL
;
event
->
data_type
=
FSNOTIFY_EVENT_NONE
;
INIT_LIST_HEAD
(
&
event
->
private_data_list
);
INIT_LIST_HEAD
(
&
event
->
private_data_list
);
}
/*
* Caller damn well better be holding whatever mutex is protecting the
* old_holder->event_list and the new_event must be a clean event which
* cannot be found anywhere else in the kernel.
*/
int
fsnotify_replace_event
(
struct
fsnotify_event_holder
*
old_holder
,
struct
fsnotify_event
*
new_event
)
{
struct
fsnotify_event
*
old_event
=
old_holder
->
event
;
struct
fsnotify_event_holder
*
new_holder
=
&
new_event
->
holder
;
enum
event_spinlock_class
{
SPINLOCK_OLD
,
SPINLOCK_NEW
,
};
/*
* if the new_event's embedded holder is in use someone
* screwed up and didn't give us a clean new event.
*/
BUG_ON
(
!
list_empty
(
&
new_holder
->
event_list
));
spin_lock_nested
(
&
old_event
->
lock
,
SPINLOCK_OLD
);
spin_lock_nested
(
&
new_event
->
lock
,
SPINLOCK_NEW
);
new_holder
->
event
=
new_event
;
list_replace_init
(
&
old_holder
->
event_list
,
&
new_holder
->
event_list
);
spin_unlock
(
&
new_event
->
lock
);
spin_unlock
(
&
old_event
->
lock
);
/* event == holder means we are referenced through the in event holder */
if
(
old_holder
!=
&
old_event
->
holder
)
fsnotify_destroy_event_holder
(
old_holder
);
fsnotify_get_event
(
new_event
);
/* on the list take reference */
fsnotify_put_event
(
old_event
);
/* off the list, drop reference */
return
0
;
}
event
->
to_tell
=
NULL
;
struct
fsnotify_event
*
fsnotify_clone_event
(
struct
fsnotify_event
*
old_event
)
{
struct
fsnotify_event
*
event
;
event
=
kmem_cache_alloc
(
fsnotify_event_cachep
,
GFP_KERNEL
);
if
(
!
event
)
return
NULL
;
memcpy
(
event
,
old_event
,
sizeof
(
*
event
));
initialize_event
(
event
);
event
->
file_name
=
NULL
;
if
(
event
->
name_len
)
{
event
->
name_len
=
0
;
event
->
file_name
=
kstrdup
(
old_event
->
file_name
,
GFP_KERNEL
);
if
(
!
event
->
file_name
)
{
kmem_cache_free
(
fsnotify_event_cachep
,
event
);
return
NULL
;
}
}
if
(
event
->
data_type
==
FSNOTIFY_EVENT_PATH
)
path_get
(
&
event
->
path
);
event
->
sync_cookie
=
0
;
return
event
;
}
}
/*
/*
...
@@ -353,7 +370,7 @@ struct fsnotify_event *fsnotify_create_event(struct inode *to_tell, __u32 mask,
...
@@ -353,7 +370,7 @@ struct fsnotify_event *fsnotify_create_event(struct inode *to_tell, __u32 mask,
{
{
struct
fsnotify_event
*
event
;
struct
fsnotify_event
*
event
;
event
=
kmem_cache_alloc
(
fsnotify_event_cachep
,
gfp
);
event
=
kmem_cache_
z
alloc
(
fsnotify_event_cachep
,
gfp
);
if
(
!
event
)
if
(
!
event
)
return
NULL
;
return
NULL
;
...
@@ -370,6 +387,7 @@ struct fsnotify_event *fsnotify_create_event(struct inode *to_tell, __u32 mask,
...
@@ -370,6 +387,7 @@ struct fsnotify_event *fsnotify_create_event(struct inode *to_tell, __u32 mask,
event
->
sync_cookie
=
cookie
;
event
->
sync_cookie
=
cookie
;
event
->
to_tell
=
to_tell
;
event
->
to_tell
=
to_tell
;
event
->
data_type
=
data_type
;
switch
(
data_type
)
{
switch
(
data_type
)
{
case
FSNOTIFY_EVENT_FILE
:
{
case
FSNOTIFY_EVENT_FILE
:
{
...
@@ -386,12 +404,10 @@ struct fsnotify_event *fsnotify_create_event(struct inode *to_tell, __u32 mask,
...
@@ -386,12 +404,10 @@ struct fsnotify_event *fsnotify_create_event(struct inode *to_tell, __u32 mask,
event
->
path
.
dentry
=
path
->
dentry
;
event
->
path
.
dentry
=
path
->
dentry
;
event
->
path
.
mnt
=
path
->
mnt
;
event
->
path
.
mnt
=
path
->
mnt
;
path_get
(
&
event
->
path
);
path_get
(
&
event
->
path
);
event
->
data_type
=
FSNOTIFY_EVENT_PATH
;
break
;
break
;
}
}
case
FSNOTIFY_EVENT_INODE
:
case
FSNOTIFY_EVENT_INODE
:
event
->
inode
=
data
;
event
->
inode
=
data
;
event
->
data_type
=
FSNOTIFY_EVENT_INODE
;
break
;
break
;
case
FSNOTIFY_EVENT_NONE
:
case
FSNOTIFY_EVENT_NONE
:
event
->
inode
=
NULL
;
event
->
inode
=
NULL
;
...
@@ -412,8 +428,11 @@ __init int fsnotify_notification_init(void)
...
@@ -412,8 +428,11 @@ __init int fsnotify_notification_init(void)
fsnotify_event_cachep
=
KMEM_CACHE
(
fsnotify_event
,
SLAB_PANIC
);
fsnotify_event_cachep
=
KMEM_CACHE
(
fsnotify_event
,
SLAB_PANIC
);
fsnotify_event_holder_cachep
=
KMEM_CACHE
(
fsnotify_event_holder
,
SLAB_PANIC
);
fsnotify_event_holder_cachep
=
KMEM_CACHE
(
fsnotify_event_holder
,
SLAB_PANIC
);
initialize_event
(
&
q_overflow_event
);
q_overflow_event
=
fsnotify_create_event
(
NULL
,
FS_Q_OVERFLOW
,
NULL
,
q_overflow_event
.
mask
=
FS_Q_OVERFLOW
;
FSNOTIFY_EVENT_NONE
,
NULL
,
0
,
GFP_KERNEL
);
if
(
!
q_overflow_event
)
panic
(
"unable to allocate fsnotify q_overflow_event
\n
"
);
return
0
;
return
0
;
}
}
...
...
fs/open.c
View file @
b8ed8e7c
...
@@ -1042,7 +1042,7 @@ long do_sys_open(int dfd, const char __user *filename, int flags, int mode)
...
@@ -1042,7 +1042,7 @@ long do_sys_open(int dfd, const char __user *filename, int flags, int mode)
put_unused_fd
(
fd
);
put_unused_fd
(
fd
);
fd
=
PTR_ERR
(
f
);
fd
=
PTR_ERR
(
f
);
}
else
{
}
else
{
fsnotify_open
(
f
->
f_path
.
dentry
);
fsnotify_open
(
f
);
fd_install
(
fd
,
f
);
fd_install
(
fd
,
f
);
}
}
}
}
...
...
fs/read_write.c
View file @
b8ed8e7c
...
@@ -293,7 +293,7 @@ ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
...
@@ -293,7 +293,7 @@ ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
else
else
ret
=
do_sync_read
(
file
,
buf
,
count
,
pos
);
ret
=
do_sync_read
(
file
,
buf
,
count
,
pos
);
if
(
ret
>
0
)
{
if
(
ret
>
0
)
{
fsnotify_access
(
file
->
f_path
.
dentry
);
fsnotify_access
(
file
);
add_rchar
(
current
,
ret
);
add_rchar
(
current
,
ret
);
}
}
inc_syscr
(
current
);
inc_syscr
(
current
);
...
@@ -348,7 +348,7 @@ ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_
...
@@ -348,7 +348,7 @@ ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_
else
else
ret
=
do_sync_write
(
file
,
buf
,
count
,
pos
);
ret
=
do_sync_write
(
file
,
buf
,
count
,
pos
);
if
(
ret
>
0
)
{
if
(
ret
>
0
)
{
fsnotify_modify
(
file
->
f_path
.
dentry
);
fsnotify_modify
(
file
);
add_wchar
(
current
,
ret
);
add_wchar
(
current
,
ret
);
}
}
inc_syscw
(
current
);
inc_syscw
(
current
);
...
@@ -656,9 +656,9 @@ out:
...
@@ -656,9 +656,9 @@ out:
kfree
(
iov
);
kfree
(
iov
);
if
((
ret
+
(
type
==
READ
))
>
0
)
{
if
((
ret
+
(
type
==
READ
))
>
0
)
{
if
(
type
==
READ
)
if
(
type
==
READ
)
fsnotify_access
(
file
->
f_path
.
dentry
);
fsnotify_access
(
file
);
else
else
fsnotify_modify
(
file
->
f_path
.
dentry
);
fsnotify_modify
(
file
);
}
}
return
ret
;
return
ret
;
}
}
...
...
include/linux/fsnotify.h
View file @
b8ed8e7c
...
@@ -29,9 +29,14 @@ static inline void fsnotify_d_instantiate(struct dentry *entry,
...
@@ -29,9 +29,14 @@ static inline void fsnotify_d_instantiate(struct dentry *entry,
}
}
/* Notify this dentry's parent about a child's events. */
/* Notify this dentry's parent about a child's events. */
static
inline
void
fsnotify_parent
(
struct
dentry
*
dentry
,
__u32
mask
)
static
inline
void
fsnotify_parent
(
struct
file
*
file
,
struct
dentry
*
dentry
,
__u32
mask
)
{
{
__fsnotify_parent
(
dentry
,
mask
);
BUG_ON
(
file
&&
dentry
);
if
(
file
)
dentry
=
file
->
f_path
.
dentry
;
__fsnotify_parent
(
file
,
dentry
,
mask
);
inotify_dentry_parent_queue_event
(
dentry
,
mask
,
0
,
dentry
->
d_name
.
name
);
inotify_dentry_parent_queue_event
(
dentry
,
mask
,
0
,
dentry
->
d_name
.
name
);
}
}
...
@@ -124,7 +129,7 @@ static inline void fsnotify_nameremove(struct dentry *dentry, int isdir)
...
@@ -124,7 +129,7 @@ static inline void fsnotify_nameremove(struct dentry *dentry, int isdir)
if
(
isdir
)
if
(
isdir
)
mask
|=
FS_IN_ISDIR
;
mask
|=
FS_IN_ISDIR
;
fsnotify_parent
(
dentry
,
mask
);
fsnotify_parent
(
NULL
,
dentry
,
mask
);
}
}
/*
/*
...
@@ -183,9 +188,9 @@ static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry)
...
@@ -183,9 +188,9 @@ static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry)
/*
/*
* fsnotify_access - file was read
* fsnotify_access - file was read
*/
*/
static
inline
void
fsnotify_access
(
struct
dentry
*
dentry
)
static
inline
void
fsnotify_access
(
struct
file
*
file
)
{
{
struct
inode
*
inode
=
dentry
->
d_inode
;
struct
inode
*
inode
=
file
->
f_path
.
dentry
->
d_inode
;
__u32
mask
=
FS_ACCESS
;
__u32
mask
=
FS_ACCESS
;
if
(
S_ISDIR
(
inode
->
i_mode
))
if
(
S_ISDIR
(
inode
->
i_mode
))
...
@@ -193,16 +198,16 @@ static inline void fsnotify_access(struct dentry *dentry)
...
@@ -193,16 +198,16 @@ static inline void fsnotify_access(struct dentry *dentry)
inotify_inode_queue_event
(
inode
,
mask
,
0
,
NULL
,
NULL
);
inotify_inode_queue_event
(
inode
,
mask
,
0
,
NULL
,
NULL
);
fsnotify_parent
(
dentry
,
mask
);
fsnotify_parent
(
file
,
NULL
,
mask
);
fsnotify
(
inode
,
mask
,
inode
,
FSNOTIFY_EVENT_INOD
E
,
NULL
,
0
);
fsnotify
(
inode
,
mask
,
file
,
FSNOTIFY_EVENT_FIL
E
,
NULL
,
0
);
}
}
/*
/*
* fsnotify_modify - file was modified
* fsnotify_modify - file was modified
*/
*/
static
inline
void
fsnotify_modify
(
struct
dentry
*
dentry
)
static
inline
void
fsnotify_modify
(
struct
file
*
file
)
{
{
struct
inode
*
inode
=
dentry
->
d_inode
;
struct
inode
*
inode
=
file
->
f_path
.
dentry
->
d_inode
;
__u32
mask
=
FS_MODIFY
;
__u32
mask
=
FS_MODIFY
;
if
(
S_ISDIR
(
inode
->
i_mode
))
if
(
S_ISDIR
(
inode
->
i_mode
))
...
@@ -210,16 +215,16 @@ static inline void fsnotify_modify(struct dentry *dentry)
...
@@ -210,16 +215,16 @@ static inline void fsnotify_modify(struct dentry *dentry)
inotify_inode_queue_event
(
inode
,
mask
,
0
,
NULL
,
NULL
);
inotify_inode_queue_event
(
inode
,
mask
,
0
,
NULL
,
NULL
);
fsnotify_parent
(
dentry
,
mask
);
fsnotify_parent
(
file
,
NULL
,
mask
);
fsnotify
(
inode
,
mask
,
inode
,
FSNOTIFY_EVENT_INOD
E
,
NULL
,
0
);
fsnotify
(
inode
,
mask
,
file
,
FSNOTIFY_EVENT_FIL
E
,
NULL
,
0
);
}
}
/*
/*
* fsnotify_open - file was opened
* fsnotify_open - file was opened
*/
*/
static
inline
void
fsnotify_open
(
struct
dentry
*
dentry
)
static
inline
void
fsnotify_open
(
struct
file
*
file
)
{
{
struct
inode
*
inode
=
dentry
->
d_inode
;
struct
inode
*
inode
=
file
->
f_path
.
dentry
->
d_inode
;
__u32
mask
=
FS_OPEN
;
__u32
mask
=
FS_OPEN
;
if
(
S_ISDIR
(
inode
->
i_mode
))
if
(
S_ISDIR
(
inode
->
i_mode
))
...
@@ -227,8 +232,8 @@ static inline void fsnotify_open(struct dentry *dentry)
...
@@ -227,8 +232,8 @@ static inline void fsnotify_open(struct dentry *dentry)
inotify_inode_queue_event
(
inode
,
mask
,
0
,
NULL
,
NULL
);
inotify_inode_queue_event
(
inode
,
mask
,
0
,
NULL
,
NULL
);
fsnotify_parent
(
dentry
,
mask
);
fsnotify_parent
(
file
,
NULL
,
mask
);
fsnotify
(
inode
,
mask
,
inode
,
FSNOTIFY_EVENT_INOD
E
,
NULL
,
0
);
fsnotify
(
inode
,
mask
,
file
,
FSNOTIFY_EVENT_FIL
E
,
NULL
,
0
);
}
}
/*
/*
...
@@ -236,8 +241,7 @@ static inline void fsnotify_open(struct dentry *dentry)
...
@@ -236,8 +241,7 @@ static inline void fsnotify_open(struct dentry *dentry)
*/
*/
static
inline
void
fsnotify_close
(
struct
file
*
file
)
static
inline
void
fsnotify_close
(
struct
file
*
file
)
{
{
struct
dentry
*
dentry
=
file
->
f_path
.
dentry
;
struct
inode
*
inode
=
file
->
f_path
.
dentry
->
d_inode
;
struct
inode
*
inode
=
dentry
->
d_inode
;
fmode_t
mode
=
file
->
f_mode
;
fmode_t
mode
=
file
->
f_mode
;
__u32
mask
=
(
mode
&
FMODE_WRITE
)
?
FS_CLOSE_WRITE
:
FS_CLOSE_NOWRITE
;
__u32
mask
=
(
mode
&
FMODE_WRITE
)
?
FS_CLOSE_WRITE
:
FS_CLOSE_NOWRITE
;
...
@@ -246,7 +250,7 @@ static inline void fsnotify_close(struct file *file)
...
@@ -246,7 +250,7 @@ static inline void fsnotify_close(struct file *file)
inotify_inode_queue_event
(
inode
,
mask
,
0
,
NULL
,
NULL
);
inotify_inode_queue_event
(
inode
,
mask
,
0
,
NULL
,
NULL
);
fsnotify_parent
(
dentry
,
mask
);
fsnotify_parent
(
file
,
NULL
,
mask
);
fsnotify
(
inode
,
mask
,
file
,
FSNOTIFY_EVENT_FILE
,
NULL
,
0
);
fsnotify
(
inode
,
mask
,
file
,
FSNOTIFY_EVENT_FILE
,
NULL
,
0
);
}
}
...
@@ -263,7 +267,7 @@ static inline void fsnotify_xattr(struct dentry *dentry)
...
@@ -263,7 +267,7 @@ static inline void fsnotify_xattr(struct dentry *dentry)
inotify_inode_queue_event
(
inode
,
mask
,
0
,
NULL
,
NULL
);
inotify_inode_queue_event
(
inode
,
mask
,
0
,
NULL
,
NULL
);
fsnotify_parent
(
dentry
,
mask
);
fsnotify_parent
(
NULL
,
dentry
,
mask
);
fsnotify
(
inode
,
mask
,
inode
,
FSNOTIFY_EVENT_INODE
,
NULL
,
0
);
fsnotify
(
inode
,
mask
,
inode
,
FSNOTIFY_EVENT_INODE
,
NULL
,
0
);
}
}
...
@@ -299,7 +303,7 @@ static inline void fsnotify_change(struct dentry *dentry, unsigned int ia_valid)
...
@@ -299,7 +303,7 @@ static inline void fsnotify_change(struct dentry *dentry, unsigned int ia_valid)
mask
|=
FS_IN_ISDIR
;
mask
|=
FS_IN_ISDIR
;
inotify_inode_queue_event
(
inode
,
mask
,
0
,
NULL
,
NULL
);
inotify_inode_queue_event
(
inode
,
mask
,
0
,
NULL
,
NULL
);
fsnotify_parent
(
dentry
,
mask
);
fsnotify_parent
(
NULL
,
dentry
,
mask
);
fsnotify
(
inode
,
mask
,
inode
,
FSNOTIFY_EVENT_INODE
,
NULL
,
0
);
fsnotify
(
inode
,
mask
,
inode
,
FSNOTIFY_EVENT_INODE
,
NULL
,
0
);
}
}
}
}
...
...
include/linux/fsnotify_backend.h
View file @
b8ed8e7c
...
@@ -58,9 +58,7 @@
...
@@ -58,9 +58,7 @@
FS_MOVED_FROM | FS_MOVED_TO | FS_CREATE |\
FS_MOVED_FROM | FS_MOVED_TO | FS_CREATE |\
FS_DELETE)
FS_DELETE)
/* listeners that hard code group numbers near the top */
#define FS_MOVE (FS_MOVED_FROM | FS_MOVED_TO)
#define DNOTIFY_GROUP_NUM UINT_MAX
#define INOTIFY_GROUP_NUM (DNOTIFY_GROUP_NUM-1)
struct
fsnotify_group
;
struct
fsnotify_group
;
struct
fsnotify_event
;
struct
fsnotify_event
;
...
@@ -80,7 +78,8 @@ struct fsnotify_event_private_data;
...
@@ -80,7 +78,8 @@ struct fsnotify_event_private_data;
* valid group and inode to use to clean up.
* valid group and inode to use to clean up.
*/
*/
struct
fsnotify_ops
{
struct
fsnotify_ops
{
bool
(
*
should_send_event
)(
struct
fsnotify_group
*
group
,
struct
inode
*
inode
,
__u32
mask
);
bool
(
*
should_send_event
)(
struct
fsnotify_group
*
group
,
struct
inode
*
inode
,
__u32
mask
,
void
*
data
,
int
data_type
);
int
(
*
handle_event
)(
struct
fsnotify_group
*
group
,
struct
fsnotify_event
*
event
);
int
(
*
handle_event
)(
struct
fsnotify_group
*
group
,
struct
fsnotify_event
*
event
);
void
(
*
free_group_priv
)(
struct
fsnotify_group
*
group
);
void
(
*
free_group_priv
)(
struct
fsnotify_group
*
group
);
void
(
*
freeing_mark
)(
struct
fsnotify_mark_entry
*
entry
,
struct
fsnotify_group
*
group
);
void
(
*
freeing_mark
)(
struct
fsnotify_mark_entry
*
entry
,
struct
fsnotify_group
*
group
);
...
@@ -119,7 +118,6 @@ struct fsnotify_group {
...
@@ -119,7 +118,6 @@ struct fsnotify_group {
* closed.
* closed.
*/
*/
atomic_t
refcnt
;
/* things with interest in this group */
atomic_t
refcnt
;
/* things with interest in this group */
unsigned
int
group_num
;
/* simply prevents accidental group collision */
const
struct
fsnotify_ops
*
ops
;
/* how this group handles things */
const
struct
fsnotify_ops
*
ops
;
/* how this group handles things */
...
@@ -254,7 +252,7 @@ struct fsnotify_mark_entry {
...
@@ -254,7 +252,7 @@ struct fsnotify_mark_entry {
/* main fsnotify call to send events */
/* main fsnotify call to send events */
extern
void
fsnotify
(
struct
inode
*
to_tell
,
__u32
mask
,
void
*
data
,
int
data_is
,
extern
void
fsnotify
(
struct
inode
*
to_tell
,
__u32
mask
,
void
*
data
,
int
data_is
,
const
char
*
name
,
u32
cookie
);
const
char
*
name
,
u32
cookie
);
extern
void
__fsnotify_parent
(
struct
dentry
*
dentry
,
__u32
mask
);
extern
void
__fsnotify_parent
(
struct
file
*
file
,
struct
dentry
*
dentry
,
__u32
mask
);
extern
void
__fsnotify_inode_delete
(
struct
inode
*
inode
);
extern
void
__fsnotify_inode_delete
(
struct
inode
*
inode
);
extern
u32
fsnotify_get_cookie
(
void
);
extern
u32
fsnotify_get_cookie
(
void
);
...
@@ -307,8 +305,7 @@ static inline void __fsnotify_d_instantiate(struct dentry *dentry, struct inode
...
@@ -307,8 +305,7 @@ static inline void __fsnotify_d_instantiate(struct dentry *dentry, struct inode
/* must call when a group changes its ->mask */
/* must call when a group changes its ->mask */
extern
void
fsnotify_recalc_global_mask
(
void
);
extern
void
fsnotify_recalc_global_mask
(
void
);
/* get a reference to an existing or create a new group */
/* get a reference to an existing or create a new group */
extern
struct
fsnotify_group
*
fsnotify_obtain_group
(
unsigned
int
group_num
,
extern
struct
fsnotify_group
*
fsnotify_obtain_group
(
__u32
mask
,
__u32
mask
,
const
struct
fsnotify_ops
*
ops
);
const
struct
fsnotify_ops
*
ops
);
/* run all marks associated with this group and update group->mask */
/* run all marks associated with this group and update group->mask */
extern
void
fsnotify_recalc_group_mask
(
struct
fsnotify_group
*
group
);
extern
void
fsnotify_recalc_group_mask
(
struct
fsnotify_group
*
group
);
...
@@ -323,8 +320,10 @@ extern struct fsnotify_event_private_data *fsnotify_remove_priv_from_event(struc
...
@@ -323,8 +320,10 @@ extern struct fsnotify_event_private_data *fsnotify_remove_priv_from_event(struc
struct
fsnotify_event
*
event
);
struct
fsnotify_event
*
event
);
/* attach the event to the group notification queue */
/* attach the event to the group notification queue */
extern
int
fsnotify_add_notify_event
(
struct
fsnotify_group
*
group
,
struct
fsnotify_event
*
event
,
extern
int
fsnotify_add_notify_event
(
struct
fsnotify_group
*
group
,
struct
fsnotify_event_private_data
*
priv
);
struct
fsnotify_event
*
event
,
struct
fsnotify_event_private_data
*
priv
,
int
(
*
merge
)(
struct
list_head
*
,
struct
fsnotify_event
*
));
/* true if the group notification queue is empty */
/* true if the group notification queue is empty */
extern
bool
fsnotify_notify_queue_is_empty
(
struct
fsnotify_group
*
group
);
extern
bool
fsnotify_notify_queue_is_empty
(
struct
fsnotify_group
*
group
);
/* return, but do not dequeue the first event on the notification queue */
/* return, but do not dequeue the first event on the notification queue */
...
@@ -339,8 +338,10 @@ extern void fsnotify_recalc_inode_mask(struct inode *inode);
...
@@ -339,8 +338,10 @@ extern void fsnotify_recalc_inode_mask(struct inode *inode);
extern
void
fsnotify_init_mark
(
struct
fsnotify_mark_entry
*
entry
,
void
(
*
free_mark
)(
struct
fsnotify_mark_entry
*
entry
));
extern
void
fsnotify_init_mark
(
struct
fsnotify_mark_entry
*
entry
,
void
(
*
free_mark
)(
struct
fsnotify_mark_entry
*
entry
));
/* find (and take a reference) to a mark associated with group and inode */
/* find (and take a reference) to a mark associated with group and inode */
extern
struct
fsnotify_mark_entry
*
fsnotify_find_mark_entry
(
struct
fsnotify_group
*
group
,
struct
inode
*
inode
);
extern
struct
fsnotify_mark_entry
*
fsnotify_find_mark_entry
(
struct
fsnotify_group
*
group
,
struct
inode
*
inode
);
/* copy the values from old into new */
extern
void
fsnotify_duplicate_mark
(
struct
fsnotify_mark_entry
*
new
,
struct
fsnotify_mark_entry
*
old
);
/* attach the mark to both the group and the inode */
/* attach the mark to both the group and the inode */
extern
int
fsnotify_add_mark
(
struct
fsnotify_mark_entry
*
entry
,
struct
fsnotify_group
*
group
,
struct
inode
*
inode
);
extern
int
fsnotify_add_mark
(
struct
fsnotify_mark_entry
*
entry
,
struct
fsnotify_group
*
group
,
struct
inode
*
inode
,
int
allow_dups
);
/* given a mark, flag it to be freed when all references are dropped */
/* given a mark, flag it to be freed when all references are dropped */
extern
void
fsnotify_destroy_mark_by_entry
(
struct
fsnotify_mark_entry
*
entry
);
extern
void
fsnotify_destroy_mark_by_entry
(
struct
fsnotify_mark_entry
*
entry
);
/* run all the marks in a group, and flag them to be freed */
/* run all the marks in a group, and flag them to be freed */
...
@@ -354,13 +355,18 @@ extern struct fsnotify_event *fsnotify_create_event(struct inode *to_tell, __u32
...
@@ -354,13 +355,18 @@ extern struct fsnotify_event *fsnotify_create_event(struct inode *to_tell, __u32
void
*
data
,
int
data_is
,
const
char
*
name
,
void
*
data
,
int
data_is
,
const
char
*
name
,
u32
cookie
,
gfp_t
gfp
);
u32
cookie
,
gfp_t
gfp
);
/* fanotify likes to change events after they are on lists... */
extern
struct
fsnotify_event
*
fsnotify_clone_event
(
struct
fsnotify_event
*
old_event
);
extern
int
fsnotify_replace_event
(
struct
fsnotify_event_holder
*
old_holder
,
struct
fsnotify_event
*
new_event
);
#else
#else
static
inline
void
fsnotify
(
struct
inode
*
to_tell
,
__u32
mask
,
void
*
data
,
int
data_is
,
static
inline
void
fsnotify
(
struct
inode
*
to_tell
,
__u32
mask
,
void
*
data
,
int
data_is
,
const
char
*
name
,
u32
cookie
)
const
char
*
name
,
u32
cookie
)
{}
{}
static
inline
void
__fsnotify_parent
(
struct
dentry
*
dentry
,
__u32
mask
)
static
inline
void
__fsnotify_parent
(
struct
file
*
file
,
struct
dentry
*
dentry
,
__u32
mask
)
{}
{}
static
inline
void
__fsnotify_inode_delete
(
struct
inode
*
inode
)
static
inline
void
__fsnotify_inode_delete
(
struct
inode
*
inode
)
...
...
init/Kconfig
View file @
b8ed8e7c
...
@@ -302,13 +302,17 @@ config AUDITSYSCALL
...
@@ -302,13 +302,17 @@ config AUDITSYSCALL
help
help
Enable low-overhead system-call auditing infrastructure that
Enable low-overhead system-call auditing infrastructure that
can be used independently or with another kernel subsystem,
can be used independently or with another kernel subsystem,
such as SELinux. To use audit's filesystem watch feature, please
such as SELinux.
ensure that INOTIFY is configured.
config AUDIT_WATCH
def_bool y
depends on AUDITSYSCALL
select FSNOTIFY
config AUDIT_TREE
config AUDIT_TREE
def_bool y
def_bool y
depends on AUDITSYSCALL
depends on AUDITSYSCALL
select
I
NOTIFY
select
FS
NOTIFY
menu "RCU Subsystem"
menu "RCU Subsystem"
...
...
kernel/Makefile
View file @
b8ed8e7c
...
@@ -69,10 +69,11 @@ obj-$(CONFIG_IKCONFIG) += configs.o
...
@@ -69,10 +69,11 @@ obj-$(CONFIG_IKCONFIG) += configs.o
obj-$(CONFIG_RESOURCE_COUNTERS)
+=
res_counter.o
obj-$(CONFIG_RESOURCE_COUNTERS)
+=
res_counter.o
obj-$(CONFIG_STOP_MACHINE)
+=
stop_machine.o
obj-$(CONFIG_STOP_MACHINE)
+=
stop_machine.o
obj-$(CONFIG_KPROBES_SANITY_TEST)
+=
test_kprobes.o
obj-$(CONFIG_KPROBES_SANITY_TEST)
+=
test_kprobes.o
obj-$(CONFIG_AUDIT)
+=
audit.o auditfilter.o
audit_watch.o
obj-$(CONFIG_AUDIT)
+=
audit.o auditfilter.o
obj-$(CONFIG_AUDITSYSCALL)
+=
auditsc.o
obj-$(CONFIG_AUDITSYSCALL)
+=
auditsc.o
obj-$(CONFIG_
GCOV_KERNEL)
+=
gcov/
obj-$(CONFIG_
AUDIT_WATCH)
+=
audit_watch.o
obj-$(CONFIG_AUDIT_TREE)
+=
audit_tree.o
obj-$(CONFIG_AUDIT_TREE)
+=
audit_tree.o
obj-$(CONFIG_GCOV_KERNEL)
+=
gcov/
obj-$(CONFIG_KPROBES)
+=
kprobes.o
obj-$(CONFIG_KPROBES)
+=
kprobes.o
obj-$(CONFIG_KGDB)
+=
kgdb.o
obj-$(CONFIG_KGDB)
+=
kgdb.o
obj-$(CONFIG_DETECT_SOFTLOCKUP)
+=
softlockup.o
obj-$(CONFIG_DETECT_SOFTLOCKUP)
+=
softlockup.o
...
...
kernel/audit.c
View file @
b8ed8e7c
...
@@ -55,7 +55,6 @@
...
@@ -55,7 +55,6 @@
#include <net/netlink.h>
#include <net/netlink.h>
#include <linux/skbuff.h>
#include <linux/skbuff.h>
#include <linux/netlink.h>
#include <linux/netlink.h>
#include <linux/inotify.h>
#include <linux/freezer.h>
#include <linux/freezer.h>
#include <linux/tty.h>
#include <linux/tty.h>
...
...
kernel/audit.h
View file @
b8ed8e7c
...
@@ -103,21 +103,27 @@ extern struct mutex audit_filter_mutex;
...
@@ -103,21 +103,27 @@ extern struct mutex audit_filter_mutex;
extern
void
audit_free_rule_rcu
(
struct
rcu_head
*
);
extern
void
audit_free_rule_rcu
(
struct
rcu_head
*
);
extern
struct
list_head
audit_filter_list
[];
extern
struct
list_head
audit_filter_list
[];
extern
struct
audit_entry
*
audit_dupe_rule
(
struct
audit_krule
*
old
);
/* audit watch functions */
/* audit watch functions */
extern
unsigned
long
audit_watch_inode
(
struct
audit_watch
*
watch
);
#ifdef CONFIG_AUDIT_WATCH
extern
dev_t
audit_watch_dev
(
struct
audit_watch
*
watch
);
extern
void
audit_put_watch
(
struct
audit_watch
*
watch
);
extern
void
audit_put_watch
(
struct
audit_watch
*
watch
);
extern
void
audit_get_watch
(
struct
audit_watch
*
watch
);
extern
void
audit_get_watch
(
struct
audit_watch
*
watch
);
extern
int
audit_to_watch
(
struct
audit_krule
*
krule
,
char
*
path
,
int
len
,
u32
op
);
extern
int
audit_to_watch
(
struct
audit_krule
*
krule
,
char
*
path
,
int
len
,
u32
op
);
extern
int
audit_add_watch
(
struct
audit_krule
*
krule
);
extern
int
audit_add_watch
(
struct
audit_krule
*
krule
,
struct
list_head
**
list
);
extern
void
audit_remove_watch
(
struct
audit_watch
*
watch
);
extern
void
audit_remove_watch_rule
(
struct
audit_krule
*
krule
);
extern
void
audit_remove_watch_rule
(
struct
audit_krule
*
krule
,
struct
list_head
*
list
);
extern
void
audit_inotify_unregister
(
struct
list_head
*
in_list
);
extern
char
*
audit_watch_path
(
struct
audit_watch
*
watch
);
extern
char
*
audit_watch_path
(
struct
audit_watch
*
watch
);
extern
struct
list_head
*
audit_watch_rules
(
struct
audit_watch
*
watch
);
extern
int
audit_watch_compare
(
struct
audit_watch
*
watch
,
unsigned
long
ino
,
dev_t
dev
);
#else
extern
struct
audit_entry
*
audit_dupe_rule
(
struct
audit_krule
*
old
,
#define audit_put_watch(w) {}
struct
audit_watch
*
watch
);
#define audit_get_watch(w) {}
#define audit_to_watch(k, p, l, o) (-EINVAL)
#define audit_add_watch(k, l) (-EINVAL)
#define audit_remove_watch_rule(k) BUG()
#define audit_watch_path(w) ""
#define audit_watch_compare(w, i, d) 0
#endif
/* CONFIG_AUDIT_WATCH */
#ifdef CONFIG_AUDIT_TREE
#ifdef CONFIG_AUDIT_TREE
extern
struct
audit_chunk
*
audit_tree_lookup
(
const
struct
inode
*
);
extern
struct
audit_chunk
*
audit_tree_lookup
(
const
struct
inode
*
);
...
...
kernel/audit_tree.c
View file @
b8ed8e7c
This diff is collapsed.
Click to expand it.
kernel/audit_watch.c
View file @
b8ed8e7c
This diff is collapsed.
Click to expand it.
kernel/auditfilter.c
View file @
b8ed8e7c
...
@@ -70,6 +70,7 @@ static inline void audit_free_rule(struct audit_entry *e)
...
@@ -70,6 +70,7 @@ static inline void audit_free_rule(struct audit_entry *e)
{
{
int
i
;
int
i
;
struct
audit_krule
*
erule
=
&
e
->
rule
;
struct
audit_krule
*
erule
=
&
e
->
rule
;
/* some rules don't have associated watches */
/* some rules don't have associated watches */
if
(
erule
->
watch
)
if
(
erule
->
watch
)
audit_put_watch
(
erule
->
watch
);
audit_put_watch
(
erule
->
watch
);
...
@@ -745,8 +746,7 @@ static inline int audit_dupe_lsm_field(struct audit_field *df,
...
@@ -745,8 +746,7 @@ static inline int audit_dupe_lsm_field(struct audit_field *df,
* rule with the new rule in the filterlist, then free the old rule.
* rule with the new rule in the filterlist, then free the old rule.
* The rlist element is undefined; list manipulations are handled apart from
* The rlist element is undefined; list manipulations are handled apart from
* the initial copy. */
* the initial copy. */
struct
audit_entry
*
audit_dupe_rule
(
struct
audit_krule
*
old
,
struct
audit_entry
*
audit_dupe_rule
(
struct
audit_krule
*
old
)
struct
audit_watch
*
watch
)
{
{
u32
fcount
=
old
->
field_count
;
u32
fcount
=
old
->
field_count
;
struct
audit_entry
*
entry
;
struct
audit_entry
*
entry
;
...
@@ -768,8 +768,8 @@ struct audit_entry *audit_dupe_rule(struct audit_krule *old,
...
@@ -768,8 +768,8 @@ struct audit_entry *audit_dupe_rule(struct audit_krule *old,
new
->
prio
=
old
->
prio
;
new
->
prio
=
old
->
prio
;
new
->
buflen
=
old
->
buflen
;
new
->
buflen
=
old
->
buflen
;
new
->
inode_f
=
old
->
inode_f
;
new
->
inode_f
=
old
->
inode_f
;
new
->
watch
=
NULL
;
new
->
field_count
=
old
->
field_count
;
new
->
field_count
=
old
->
field_count
;
/*
/*
* note that we are OK with not refcounting here; audit_match_tree()
* note that we are OK with not refcounting here; audit_match_tree()
* never dereferences tree and we can't get false positives there
* never dereferences tree and we can't get false positives there
...
@@ -810,9 +810,9 @@ struct audit_entry *audit_dupe_rule(struct audit_krule *old,
...
@@ -810,9 +810,9 @@ struct audit_entry *audit_dupe_rule(struct audit_krule *old,
}
}
}
}
if
(
watch
)
{
if
(
old
->
watch
)
{
audit_get_watch
(
watch
);
audit_get_watch
(
old
->
watch
);
new
->
watch
=
watch
;
new
->
watch
=
old
->
watch
;
}
}
return
entry
;
return
entry
;
...
@@ -865,7 +865,7 @@ static inline int audit_add_rule(struct audit_entry *entry)
...
@@ -865,7 +865,7 @@ static inline int audit_add_rule(struct audit_entry *entry)
struct
audit_watch
*
watch
=
entry
->
rule
.
watch
;
struct
audit_watch
*
watch
=
entry
->
rule
.
watch
;
struct
audit_tree
*
tree
=
entry
->
rule
.
tree
;
struct
audit_tree
*
tree
=
entry
->
rule
.
tree
;
struct
list_head
*
list
;
struct
list_head
*
list
;
int
h
,
err
;
int
err
;
#ifdef CONFIG_AUDITSYSCALL
#ifdef CONFIG_AUDITSYSCALL
int
dont_count
=
0
;
int
dont_count
=
0
;
...
@@ -888,15 +888,11 @@ static inline int audit_add_rule(struct audit_entry *entry)
...
@@ -888,15 +888,11 @@ static inline int audit_add_rule(struct audit_entry *entry)
if
(
watch
)
{
if
(
watch
)
{
/* audit_filter_mutex is dropped and re-taken during this call */
/* audit_filter_mutex is dropped and re-taken during this call */
err
=
audit_add_watch
(
&
entry
->
rule
);
err
=
audit_add_watch
(
&
entry
->
rule
,
&
list
);
if
(
err
)
{
if
(
err
)
{
mutex_unlock
(
&
audit_filter_mutex
);
mutex_unlock
(
&
audit_filter_mutex
);
goto
error
;
goto
error
;
}
}
/* entry->rule.watch may have changed during audit_add_watch() */
watch
=
entry
->
rule
.
watch
;
h
=
audit_hash_ino
((
u32
)
audit_watch_inode
(
watch
));
list
=
&
audit_inode_hash
[
h
];
}
}
if
(
tree
)
{
if
(
tree
)
{
err
=
audit_add_tree_rule
(
&
entry
->
rule
);
err
=
audit_add_tree_rule
(
&
entry
->
rule
);
...
@@ -948,7 +944,6 @@ static inline int audit_del_rule(struct audit_entry *entry)
...
@@ -948,7 +944,6 @@ static inline int audit_del_rule(struct audit_entry *entry)
struct
audit_watch
*
watch
=
entry
->
rule
.
watch
;
struct
audit_watch
*
watch
=
entry
->
rule
.
watch
;
struct
audit_tree
*
tree
=
entry
->
rule
.
tree
;
struct
audit_tree
*
tree
=
entry
->
rule
.
tree
;
struct
list_head
*
list
;
struct
list_head
*
list
;
LIST_HEAD
(
inotify_list
);
int
ret
=
0
;
int
ret
=
0
;
#ifdef CONFIG_AUDITSYSCALL
#ifdef CONFIG_AUDITSYSCALL
int
dont_count
=
0
;
int
dont_count
=
0
;
...
@@ -968,7 +963,7 @@ static inline int audit_del_rule(struct audit_entry *entry)
...
@@ -968,7 +963,7 @@ static inline int audit_del_rule(struct audit_entry *entry)
}
}
if
(
e
->
rule
.
watch
)
if
(
e
->
rule
.
watch
)
audit_remove_watch_rule
(
&
e
->
rule
,
&
inotify_list
);
audit_remove_watch_rule
(
&
e
->
rule
);
if
(
e
->
rule
.
tree
)
if
(
e
->
rule
.
tree
)
audit_remove_tree_rule
(
&
e
->
rule
);
audit_remove_tree_rule
(
&
e
->
rule
);
...
@@ -986,9 +981,6 @@ static inline int audit_del_rule(struct audit_entry *entry)
...
@@ -986,9 +981,6 @@ static inline int audit_del_rule(struct audit_entry *entry)
#endif
#endif
mutex_unlock
(
&
audit_filter_mutex
);
mutex_unlock
(
&
audit_filter_mutex
);
if
(
!
list_empty
(
&
inotify_list
))
audit_inotify_unregister
(
&
inotify_list
);
out:
out:
if
(
watch
)
if
(
watch
)
audit_put_watch
(
watch
);
/* match initial get */
audit_put_watch
(
watch
);
/* match initial get */
...
@@ -1322,30 +1314,23 @@ static int update_lsm_rule(struct audit_krule *r)
...
@@ -1322,30 +1314,23 @@ static int update_lsm_rule(struct audit_krule *r)
{
{
struct
audit_entry
*
entry
=
container_of
(
r
,
struct
audit_entry
,
rule
);
struct
audit_entry
*
entry
=
container_of
(
r
,
struct
audit_entry
,
rule
);
struct
audit_entry
*
nentry
;
struct
audit_entry
*
nentry
;
struct
audit_watch
*
watch
;
struct
audit_tree
*
tree
;
int
err
=
0
;
int
err
=
0
;
if
(
!
security_audit_rule_known
(
r
))
if
(
!
security_audit_rule_known
(
r
))
return
0
;
return
0
;
watch
=
r
->
watch
;
nentry
=
audit_dupe_rule
(
r
);
tree
=
r
->
tree
;
nentry
=
audit_dupe_rule
(
r
,
watch
);
if
(
IS_ERR
(
nentry
))
{
if
(
IS_ERR
(
nentry
))
{
/* save the first error encountered for the
/* save the first error encountered for the
* return value */
* return value */
err
=
PTR_ERR
(
nentry
);
err
=
PTR_ERR
(
nentry
);
audit_panic
(
"error updating LSM filters"
);
audit_panic
(
"error updating LSM filters"
);
if
(
watch
)
if
(
r
->
watch
)
list_del
(
&
r
->
rlist
);
list_del
(
&
r
->
rlist
);
list_del_rcu
(
&
entry
->
list
);
list_del_rcu
(
&
entry
->
list
);
list_del
(
&
r
->
list
);
list_del
(
&
r
->
list
);
}
else
{
}
else
{
if
(
watch
)
{
if
(
r
->
watch
||
r
->
tree
)
list_add
(
&
nentry
->
rule
.
rlist
,
audit_watch_rules
(
watch
));
list_del
(
&
r
->
rlist
);
}
else
if
(
tree
)
list_replace_init
(
&
r
->
rlist
,
&
nentry
->
rule
.
rlist
);
list_replace_init
(
&
r
->
rlist
,
&
nentry
->
rule
.
rlist
);
list_replace_rcu
(
&
entry
->
list
,
&
nentry
->
list
);
list_replace_rcu
(
&
entry
->
list
,
&
nentry
->
list
);
list_replace
(
&
r
->
list
,
&
nentry
->
rule
.
list
);
list_replace
(
&
r
->
list
,
&
nentry
->
rule
.
list
);
...
...
kernel/auditsc.c
View file @
b8ed8e7c
...
@@ -168,12 +168,12 @@ struct audit_context {
...
@@ -168,12 +168,12 @@ struct audit_context {
int
in_syscall
;
/* 1 if task is in a syscall */
int
in_syscall
;
/* 1 if task is in a syscall */
enum
audit_state
state
,
current_state
;
enum
audit_state
state
,
current_state
;
unsigned
int
serial
;
/* serial number for record */
unsigned
int
serial
;
/* serial number for record */
struct
timespec
ctime
;
/* time of syscall entry */
int
major
;
/* syscall number */
int
major
;
/* syscall number */
struct
timespec
ctime
;
/* time of syscall entry */
unsigned
long
argv
[
4
];
/* syscall arguments */
unsigned
long
argv
[
4
];
/* syscall arguments */
int
return_valid
;
/* return code is valid */
long
return_code
;
/* syscall return code */
long
return_code
;
/* syscall return code */
u64
prio
;
u64
prio
;
int
return_valid
;
/* return code is valid */
int
name_count
;
int
name_count
;
struct
audit_names
names
[
AUDIT_NAMES
];
struct
audit_names
names
[
AUDIT_NAMES
];
char
*
filterkey
;
/* key for rule that triggered record */
char
*
filterkey
;
/* key for rule that triggered record */
...
@@ -198,8 +198,8 @@ struct audit_context {
...
@@ -198,8 +198,8 @@ struct audit_context {
char
target_comm
[
TASK_COMM_LEN
];
char
target_comm
[
TASK_COMM_LEN
];
struct
audit_tree_refs
*
trees
,
*
first_trees
;
struct
audit_tree_refs
*
trees
,
*
first_trees
;
int
tree_count
;
struct
list_head
killed_trees
;
struct
list_head
killed_trees
;
int
tree_count
;
int
type
;
int
type
;
union
{
union
{
...
@@ -549,9 +549,8 @@ static int audit_filter_rules(struct task_struct *tsk,
...
@@ -549,9 +549,8 @@ static int audit_filter_rules(struct task_struct *tsk,
}
}
break
;
break
;
case
AUDIT_WATCH
:
case
AUDIT_WATCH
:
if
(
name
&&
audit_watch_inode
(
rule
->
watch
)
!=
(
unsigned
long
)
-
1
)
if
(
name
)
result
=
(
name
->
dev
==
audit_watch_dev
(
rule
->
watch
)
&&
result
=
audit_watch_compare
(
rule
->
watch
,
name
->
ino
,
name
->
dev
);
name
->
ino
==
audit_watch_inode
(
rule
->
watch
));
break
;
break
;
case
AUDIT_DIR
:
case
AUDIT_DIR
:
if
(
ctx
)
if
(
ctx
)
...
@@ -1726,7 +1725,7 @@ static inline void handle_one(const struct inode *inode)
...
@@ -1726,7 +1725,7 @@ static inline void handle_one(const struct inode *inode)
struct
audit_tree_refs
*
p
;
struct
audit_tree_refs
*
p
;
struct
audit_chunk
*
chunk
;
struct
audit_chunk
*
chunk
;
int
count
;
int
count
;
if
(
likely
(
list_empty
(
&
inode
->
inotify_watch
es
)))
if
(
likely
(
hlist_empty
(
&
inode
->
i_fsnotify_mark_entri
es
)))
return
;
return
;
context
=
current
->
audit_context
;
context
=
current
->
audit_context
;
p
=
context
->
trees
;
p
=
context
->
trees
;
...
@@ -1769,7 +1768,7 @@ retry:
...
@@ -1769,7 +1768,7 @@ retry:
seq
=
read_seqbegin
(
&
rename_lock
);
seq
=
read_seqbegin
(
&
rename_lock
);
for
(;;)
{
for
(;;)
{
struct
inode
*
inode
=
d
->
d_inode
;
struct
inode
*
inode
=
d
->
d_inode
;
if
(
inode
&&
unlikely
(
!
list_empty
(
&
inode
->
inotify_watch
es
)))
{
if
(
inode
&&
unlikely
(
!
hlist_empty
(
&
inode
->
i_fsnotify_mark_entri
es
)))
{
struct
audit_chunk
*
chunk
;
struct
audit_chunk
*
chunk
;
chunk
=
audit_tree_lookup
(
inode
);
chunk
=
audit_tree_lookup
(
inode
);
if
(
chunk
)
{
if
(
chunk
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment