It is possible to use this tracepoint for several purposes, including troubleshooting export permission problems and auditing accesses to files. nfsd-1025 [002] 256.807403: nfsd_permission: xid=0x12147d7a type=REG access=WRITE|SATTR|OWNER_OVERRIDE owner=1046/100 user=1046/100 name=.clang-format status=0 Signed-off-by: Chuck Lever <chuck.lever@xxxxxxxxxx> --- fs/nfsd/trace.c | 2 ++ fs/nfsd/trace.h | 44 ++++++++++++++++++++++++++++++++++++++++++++ fs/nfsd/vfs.c | 1 + 3 files changed, 47 insertions(+) diff --git a/fs/nfsd/trace.c b/fs/nfsd/trace.c index f008b95ceec2..e6857b8bdf2b 100644 --- a/fs/nfsd/trace.c +++ b/fs/nfsd/trace.c @@ -1,4 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 +#include <linux/nfs4.h> + #define CREATE_TRACE_POINTS #include "trace.h" diff --git a/fs/nfsd/trace.h b/fs/nfsd/trace.h index 77b7e8a45776..4167726fe835 100644 --- a/fs/nfsd/trace.h +++ b/fs/nfsd/trace.h @@ -511,6 +511,50 @@ TRACE_EVENT(nfsd_clid_inuse_err, __entry->cl_boot, __entry->cl_id) ) +TRACE_EVENT(nfsd_access, + TP_PROTO( + const struct svc_rqst *rqstp, + const struct dentry *dentry, + int access, + __be32 status + ), + TP_ARGS(rqstp, dentry, access, status), + TP_STRUCT__entry( + __field(u32, xid) + __field(unsigned long, type) + __field(unsigned long, access) + __field(uid_t, owner) + __field(gid_t, owner_group) + __field(uid_t, user) + __field(gid_t, user_group) + __field(int, status) + __dynamic_array(unsigned char, name, dentry->d_name.len + 1) + ), + TP_fast_assign( + const struct inode *inode = d_inode(dentry); + + __entry->xid = be32_to_cpu(rqstp->rq_xid); + __entry->type = inode->i_mode & S_IFMT; + __entry->access = access; + __entry->owner = __kuid_val(inode->i_uid); + __entry->owner_group = __kgid_val(inode->i_gid); + __entry->user = __kuid_val(current_fsuid()); + __entry->user_group = __kgid_val(current_fsgid()); + __entry->status = be32_to_cpu(status); + memcpy(__get_str(name), dentry->d_name.name, + dentry->d_name.len); + __get_str(name)[dentry->d_name.len] = '\0'; + ), + TP_printk("xid=0x%08x type=%s access=%s owner=%u/%u user=%u/%u name=%s status=%d", + __entry->xid, + show_inode_type(__entry->type), + show_perm_flags(__entry->access), + __entry->owner, __entry->owner_group, + __entry->user, __entry->user_group, + __get_str(name), __entry->status + ) +); + /* * from fs/nfsd/filecache.h */ diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index a311593ac976..0d354531ed19 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -687,6 +687,7 @@ nfsd_access(struct svc_rqst *rqstp, struct svc_fh *fhp, u32 *access, u32 *suppor sresult |= map->access; err2 = nfsd_permission(rqstp, export, dentry, map->how); + trace_nfsd_access(rqstp, dentry, map->how, err2); switch (err2) { case nfs_ok: result |= map->access;