Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F107428983
D26243.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
39 KB
Referenced Files
None
Subscribers
None
D26243.diff
View Options
Index: contrib/openbsm/etc/audit_class
===================================================================
--- contrib/openbsm/etc/audit_class
+++ contrib/openbsm/etc/audit_class
@@ -17,6 +17,7 @@
0x00001000:lo:login_logout
0x00002000:aa:authentication and authorization
0x00004000:ap:application
+0x00008000:nfs:network file system server
0x20000000:io:ioctl
0x40000000:ex:exec
0x80000000:ot:miscellaneous
Index: contrib/openbsm/etc/audit_event
===================================================================
--- contrib/openbsm/etc/audit_event
+++ contrib/openbsm/etc/audit_event
@@ -615,6 +615,30 @@
43262:AUE_EXECVEAT:execveat(2):pc,ex
43263:AUE_SHMRENAME:shm_rename(2):ip
#
+# NFS RPC related events.
+#
+43266:AUE_NFSRPC_GETATTR:nfsrvd_getattr:nfs
+43267:AUE_NFSRPC_SETATTR:nfsrvd_setattr:nfs
+43268:AUE_NFSRPC_LOOKUP:nfsrvd_lookup:nfs
+43269:AUE_NFSRPC_ACCESS:nfsrvd_access:nfs
+43270:AUE_NFSRPC_READLINK:nfsrvd_readlink:nfs
+43271:AUE_NFSRPC_READ:nfsrvd_read:nfs
+43272:AUE_NFSRPC_WRITE:nfsrvd_write:nfs
+43273:AUE_NFSRPC_CREATE:nfsrvd_create:nfs
+43274:AUE_NFSRPC_MKDIR:nfsrvd_mkdir:nfs
+43275:AUE_NFSRPC_SYMLINK:nfsrvd_symlink:nfs
+43276:AUE_NFSRPC_MKNOD:nfsrvd_mknod:nfs
+43277:AUE_NFSRPC_REMOVE:nfsrvd_remove:nfs
+43278:AUE_NFSRPC_RMDIR:nfsrvd_rmdir:nfs
+43279:AUE_NFSRPC_RENAME:nfsrvd_rename:nfs
+43280:AUE_NFSRPC_LINK:nfsrvd_link:nfs
+43281:AUE_NFSRPC_READDIR:nfsrvd_readdir:nfs
+43282:AUE_NFSRPC_READDIRPLUS:nfsrvd_readdirplus:nfs
+43283:AUE_NFSRPC_FSSTAT:nfsrvd_statfs:nfs
+43284:AUE_NFSRPC_FSINFO:nfsrvd_fsinfo:nfs
+43285:AUE_NFSRPC_PATHCONF:nfsrvd_pathconf:nfs
+43286:AUE_NFSRPC_COMMIT:nfsrvd_commit:nfs
+#
# Solaris userspace events.
#
6144:AUE_at_create:at-create atjob:ad
Index: sys/bsm/audit_kevents.h
===================================================================
--- sys/bsm/audit_kevents.h
+++ sys/bsm/audit_kevents.h
@@ -660,6 +660,31 @@
#define AUE_REALPATHAT 43264 /* FreeBSD-specific. */
#define AUE_CLOSERANGE 43265 /* FreeBSD-specific. */
+/*
+ * NFSv2 and NFSv3 RPC related audit events.
+ */
+#define AUE_NFSRPC_GETATTR 43266
+#define AUE_NFSRPC_SETATTR 43267
+#define AUE_NFSRPC_LOOKUP 43268
+#define AUE_NFSRPC_ACCESS 43269
+#define AUE_NFSRPC_READLINK 43270
+#define AUE_NFSRPC_READ 43271
+#define AUE_NFSRPC_WRITE 43272
+#define AUE_NFSRPC_CREATE 43273
+#define AUE_NFSRPC_MKDIR 43274
+#define AUE_NFSRPC_SYMLINK 43275
+#define AUE_NFSRPC_MKNOD 43276
+#define AUE_NFSRPC_REMOVE 43277
+#define AUE_NFSRPC_RMDIR 43278
+#define AUE_NFSRPC_RENAME 43279
+#define AUE_NFSRPC_LINK 43280
+#define AUE_NFSRPC_READDIR 43281
+#define AUE_NFSRPC_READDIRPLUS 43282
+#define AUE_NFSRPC_FSSTAT 43283
+#define AUE_NFSRPC_FSINFO 43284
+#define AUE_NFSRPC_PATHCONF 43285
+#define AUE_NFSRPC_COMMIT 43286
+
/*
* Darwin BSM uses a number of AUE_O_* definitions, which are aliased to the
* normal Solaris BSM identifiers. _O_ refers to it being an old, or compat
Index: sys/fs/nfs/nfs.h
===================================================================
--- sys/fs/nfs/nfs.h
+++ sys/fs/nfs/nfs.h
@@ -36,6 +36,9 @@
#ifndef _NFS_NFS_H_
#define _NFS_NFS_H_
+
+#include <bsm/audit_kevents.h>
+
/*
* Tunable constants for nfs
*/
@@ -309,7 +312,7 @@
struct nfsreferral {
u_char *nfr_srvlist; /* List of servers */
int nfr_srvcnt; /* number of servers */
- vnode_t nfr_vp; /* vnode for referral */
+ struct vnode * nfr_vp; /* vnode for referral */
uint64_t nfr_dfileno; /* assigned dir inode# */
};
@@ -559,6 +562,12 @@
#define NFSV4ROOT_INO 2 /* It's traditional */
#define NFSV4ROOT_GEN 1
+/*
+ * This array indicates the audit event number corresponding to NFSv3 and
+ * NFSv2 RPCs. This table doesn't support NFSv4.
+ */
+extern u_int16_t nfsrv3_auevent[NFS_V3NPROCS];
+
/*
* The set of signals the interrupt an I/O in progress for NFSMNT_INT mounts.
* What should be in this set is open to debate, but I believe that since
@@ -671,6 +680,7 @@
nfsv4stateid_t nd_savedcurstateid; /* Saved Current StateID */
uint32_t nd_maxreq; /* Max. request (session). */
uint32_t nd_maxresp; /* Max. reply (session). */
+ struct kaudit_record *nd_ar; /* Audit record for NFS server */
int nd_bextpg; /* Current ext_pgs page */
int nd_bextpgsiz; /* Bytes left in page */
int nd_maxextsiz; /* Max ext_pgs mbuf size */
@@ -722,6 +732,7 @@
#define ND_EXTLS 0x8000000000
#define ND_EXTLSCERT 0x10000000000
#define ND_EXTLSCERTUSER 0x20000000000
+#define ND_AUDITREC 0x40000000000
/*
* ND_GSS should be the "or" of all GSS type authentications.
Index: sys/fs/nfs/nfsdport.h
===================================================================
--- sys/fs/nfs/nfsdport.h
+++ sys/fs/nfs/nfsdport.h
@@ -28,6 +28,9 @@
* $FreeBSD$
*/
+#ifndef _NFS_NFSDPORT_H_
+#define _NFS_NFSDPORT_H_
+
/*
* These macros handle nfsvattr fields. They look a bit silly here, but
* are quite different for the Darwin port.
@@ -116,3 +119,4 @@
printf(__VA_ARGS__); \
} while (0)
+#endif /* _NFS_NFSDPORT_H_ */
Index: sys/fs/nfsserver/nfs_nfsdkrpc.c
===================================================================
--- sys/fs/nfsserver/nfs_nfsdkrpc.c
+++ sys/fs/nfsserver/nfs_nfsdkrpc.c
@@ -46,6 +46,7 @@
#include <fs/nfsserver/nfs_fha_new.h>
+#include <security/audit/audit.h>
#include <security/mac/mac_framework.h>
NFSDLOCKMUTEX;
@@ -382,7 +383,13 @@
if (cacherep == RC_DOIT) {
if ((nd->nd_flag & ND_NFSV41) != 0)
nd->nd_xprt = xprt;
+ if ((nd->nd_flag & (ND_NFSV2 | ND_NFSV3)) != 0) {
+ AUDIT_NFSRPC_ENTER(nd, curthread);
+ AUDIT_NFSARG_NETSOCKADDR(nd, nd->nd_nam);
+ }
nfsrvd_dorpc(nd, isdgram, tagstr, taglen, minorvers);
+ if ((nd->nd_flag & (ND_NFSV2 | ND_NFSV3)) != 0)
+ AUDIT_NFSRPC_EXIT(nd, curthread);
if ((nd->nd_flag & ND_NFSV41) != 0) {
if (nd->nd_repstat != NFSERR_REPLYFROMCACHE &&
(nd->nd_flag & ND_SAVEREPLY) != 0) {
Index: sys/fs/nfsserver/nfs_nfsdport.c
===================================================================
--- sys/fs/nfsserver/nfs_nfsdport.c
+++ sys/fs/nfsserver/nfs_nfsdport.c
@@ -46,6 +46,7 @@
*/
#include <fs/nfs/nfsport.h>
+#include <security/audit/audit.h>
#include <security/mac/mac_framework.h>
#include <sys/filio.h>
#include <sys/hash.h>
@@ -1974,6 +1975,7 @@
nfsrv_postopattr(nd, getret, &at);
goto out;
}
+ AUDIT_NFSARG_VNODE1(nd, vp);
if (nd->nd_flag & ND_NFSV2) {
NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
off = fxdr_unsigned(u_quad_t, *tl++);
@@ -2240,6 +2242,7 @@
nfsrv_postopattr(nd, getret, &at);
goto out;
}
+ AUDIT_NFSARG_VNODE1(nd, vp);
NFSM_DISSECT(tl, u_int32_t *, 6 * NFSX_UNSIGNED);
off = fxdr_hyper(tl);
toff = off;
Index: sys/fs/nfsserver/nfs_nfsdserv.c
===================================================================
--- sys/fs/nfsserver/nfs_nfsdserv.c
+++ sys/fs/nfsserver/nfs_nfsdserv.c
@@ -51,6 +51,7 @@
#include <fs/nfs/nfsport.h>
#include <sys/extattr.h>
#include <sys/filio.h>
+#include <security/audit/audit.h>
/* Global vars */
extern u_int32_t newnfs_false, newnfs_true;
@@ -125,8 +126,10 @@
nfsrv_postopattr(nd, 1, &nva);
goto out;
}
+ AUDIT_NFSARG_VNODE1(nd, vp);
NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
nfsmode = fxdr_unsigned(u_int32_t, *tl);
+ AUDIT_NFSARG_MODE(nd, nfsmode);
if ((nd->nd_flag & ND_NFSV4) &&
(nfsmode & ~(NFSACCESS_READ | NFSACCESS_LOOKUP |
NFSACCESS_MODIFY | NFSACCESS_EXTEND | NFSACCESS_DELETE |
@@ -235,6 +238,7 @@
if (nd->nd_repstat)
goto out;
+ AUDIT_NFSARG_VNODE1(nd, vp);
if (nd->nd_flag & ND_NFSV4) {
error = nfsrv_getattrbits(nd, &attrbits, NULL, NULL);
if (error) {
@@ -362,6 +366,7 @@
nfsrv_wcc(nd, preat_ret, &nva2, postat_ret, &nva);
goto out;
}
+ AUDIT_NFSARG_VNODE1(nd, vp);
#ifdef NFS4_ACL_EXTATTR_NAME
aclp = acl_alloc(M_WAITOK);
aclp->acl_cnt = 0;
@@ -594,6 +599,8 @@
nfsvno_relpathbuf(&named);
goto out;
}
+ AUDIT_NFSARG_UPATH1_VP(nd, p, named.ni_rootdir, dp,
+ named.ni_cnd.cn_pnbuf);
if (!nd->nd_repstat) {
nd->nd_repstat = nfsvno_namei(nd, &named, dp, 0, exp, p, &dirp);
} else {
@@ -615,6 +622,7 @@
vrele(named.ni_startdir);
nfsvno_relpathbuf(&named);
vp = named.ni_vp;
+ AUDIT_NFSARG_VNODE1(nd, vp);
if ((nd->nd_flag & ND_NFSV4) != 0 && !NFSVNO_EXPORTED(exp) &&
vp->v_type != VDIR && vp->v_type != VLNK)
/*
@@ -673,6 +681,7 @@
nfsrv_postopattr(nd, getret, &nva);
goto out;
}
+ AUDIT_NFSARG_VNODE1(nd, vp);
if (vnode_vtype(vp) != VLNK) {
if (nd->nd_flag & ND_NFSV2)
nd->nd_repstat = ENXIO;
@@ -739,6 +748,7 @@
nfsrv_postopattr(nd, getret, &nva);
goto out;
}
+ AUDIT_NFSARG_VNODE1(nd, vp);
if (nd->nd_flag & ND_NFSV2) {
NFSM_DISSECT(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
off = (off_t)fxdr_unsigned(u_int32_t, *tl++);
@@ -949,6 +959,7 @@
nfsrv_wcc(nd, forat_ret, &forat, aftat_ret, &nva);
goto out;
}
+ AUDIT_NFSARG_VNODE1(nd, vp);
gotproxystateid = 0;
if (nd->nd_flag & ND_NFSV2) {
NFSM_DISSECT(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
@@ -1140,6 +1151,8 @@
error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
if (error)
goto nfsmout;
+ AUDIT_NFSARG_UPATH1_VP(nd, p, named.ni_rootdir, dp,
+ named.ni_cnd.cn_pnbuf);
if (!nd->nd_repstat) {
NFSVNO_ATTRINIT(&nva);
if (nd->nd_flag & ND_NFSV2) {
@@ -1150,6 +1163,7 @@
NFSVNO_SETATTRVAL(&nva, type, vtyp);
NFSVNO_SETATTRVAL(&nva, mode,
nfstov_mode(sp->sa_mode));
+ AUDIT_NFSARG_MODE(nd, nva.na_mode);
switch (nva.na_type) {
case VREG:
tsize = fxdr_unsigned(int32_t, sp->sa_size);
@@ -1240,6 +1254,7 @@
&exclusive_flag, cverf, rdev, exp);
if (!nd->nd_repstat) {
+ AUDIT_NFSARG_VNODE1(nd, named.ni_vp);
nd->nd_repstat = nfsvno_getfh(vp, &fh, p);
if (!nd->nd_repstat)
nd->nd_repstat = nfsvno_getattr(vp, &nva, nd, p, 1,
@@ -1351,6 +1366,8 @@
error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
if (error)
goto nfsmout;
+ AUDIT_NFSARG_UPATH1_VP(nd, p, named.ni_rootdir, dp,
+ named.ni_cnd.cn_pnbuf);
if (!nd->nd_repstat) {
if (nd->nd_flag & ND_NFSV3) {
NFSM_DISSECT(tl, u_int32_t *, NFSX_UNSIGNED);
@@ -1366,6 +1383,7 @@
major = fxdr_unsigned(u_int32_t, *tl++);
minor = fxdr_unsigned(u_int32_t, *tl);
nva.na_rdev = NFSMAKEDEV(major, minor);
+ AUDIT_NFSARG_DEV(nd, nva.na_rdev);
}
}
@@ -1400,6 +1418,7 @@
else
nva.na_mode = 0400;
}
+ AUDIT_NFSARG_MODE(nd, nva.na_mode);
if (vtyp == VDIR)
named.ni_cnd.cn_flags |= WILLBEDIR;
@@ -1447,6 +1466,7 @@
if (!nd->nd_repstat) {
vp = named.ni_vp;
nfsrv_fixattr(nd, vp, &nva, aclp, p, &attrbits, exp);
+ AUDIT_NFSARG_VNODE1(nd, vp);
nd->nd_repstat = nfsvno_getfh(vp, fhp, p);
if ((nd->nd_flag & ND_NFSV3) && !nd->nd_repstat)
nd->nd_repstat = nfsvno_getattr(vp, &nva, nd, p, 1,
@@ -1525,6 +1545,8 @@
nfsvno_relpathbuf(&named);
goto out;
}
+ AUDIT_NFSARG_UPATH1_VP(nd, p, named.ni_rootdir, dp,
+ named.ni_cnd.cn_pnbuf);
if (!nd->nd_repstat) {
nd->nd_repstat = nfsvno_namei(nd, &named, dp, 1, exp, p, &dirp);
} else {
@@ -1541,6 +1563,7 @@
}
}
if (!nd->nd_repstat) {
+ AUDIT_NFSARG_VNODE1(nd, named.ni_vp);
if (nd->nd_flag & ND_NFSV4) {
if (vnode_vtype(named.ni_vp) == VDIR)
nd->nd_repstat = nfsvno_rmdirsub(&named, 1,
@@ -1618,6 +1641,8 @@
nfsvno_relpathbuf(&fromnd);
goto out;
}
+ AUDIT_NFSARG_UPATH1_VP(nd, p, fromnd.ni_rootdir, dp,
+ fromnd.ni_cnd.cn_pnbuf);
/*
* Unlock dp in this code section, so it is unlocked before
* tdp gets locked. This avoids a potential LOR if tdp is the
@@ -1681,6 +1706,8 @@
nfsvno_relpathbuf(&tond);
goto out;
}
+ AUDIT_NFSARG_UPATH2_VP(nd, p, tond.ni_rootdir, tdp,
+ tond.ni_cnd.cn_pnbuf);
}
if (nd->nd_repstat) {
if (nd->nd_flag & ND_NFSV3) {
@@ -1715,6 +1742,7 @@
nfsvno_relpathbuf(&tond);
goto out;
}
+ AUDIT_NFSARG_VNODE1(nd, fromnd.ni_vp);
if (vnode_vtype(fromnd.ni_vp) == VDIR)
tond.ni_cnd.cn_flags |= WILLBEDIR;
nd->nd_repstat = nfsvno_namei(nd, &tond, tdp, 0, &tnes, p, &tdirp);
@@ -1772,6 +1800,7 @@
nfsrv_wcc(nd, dirfor_ret, &dirfor, diraft_ret, &diraft);
goto out;
}
+ AUDIT_NFSARG_VNODE1(nd, vp);
NFSVOPUNLOCK(vp);
if (vnode_vtype(vp) == VDIR) {
if (nd->nd_flag & ND_NFSV4)
@@ -1809,6 +1838,8 @@
nfsvno_relpathbuf(&named);
goto out;
}
+ AUDIT_NFSARG_UPATH1_VP(nd, p, named.ni_rootdir, dp,
+ named.ni_cnd.cn_pnbuf);
if (!nd->nd_repstat) {
nd->nd_repstat = nfsvno_namei(nd, &named, dp, 0, &tnes,
p, &dirp);
@@ -1878,8 +1909,11 @@
LOCKPARENT | SAVESTART | NOCACHE);
nfsvno_setpathbuf(&named, &bufp, &hashp);
error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
- if (!error && !nd->nd_repstat)
+ if (!error && !nd->nd_repstat) {
+ AUDIT_NFSARG_UPATH1_VP(nd, p, named.ni_rootdir, dp,
+ named.ni_cnd.cn_pnbuf);
error = nfsvno_getsymlink(nd, &nva, p, &pathcp, &pathlen);
+ }
if (error) {
vrele(dp);
nfsvno_relpathbuf(&named);
@@ -1907,6 +1941,7 @@
nfsrvd_symlinksub(nd, &named, &nva, fhp, vpp, dirp,
&dirfor, &diraft, &diraft_ret, NULL, NULL, p, exp,
pathcp, pathlen);
+ AUDIT_NFSARG_VNODE1(nd, named.ni_vp);
} else if (dirp != NULL) {
dirfor_ret = nfsvno_getattr(dirp, &dirfor, nd, p, 0, NULL);
vrele(dirp);
@@ -1998,6 +2033,8 @@
error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
if (error)
goto nfsmout;
+ AUDIT_NFSARG_UPATH1_VP(nd, p, named.ni_rootdir, dp,
+ named.ni_cnd.cn_pnbuf);
if (!nd->nd_repstat) {
NFSVNO_ATTRINIT(&nva);
if (nd->nd_flag & ND_NFSV3) {
@@ -2009,6 +2046,7 @@
nva.na_mode = nfstov_mode(*tl++);
}
}
+ AUDIT_NFSARG_MODE(nd, nva.na_mode);
if (!nd->nd_repstat) {
nd->nd_repstat = nfsvno_namei(nd, &named, dp, 0, exp, p, &dirp);
} else {
@@ -2039,6 +2077,7 @@
nfsrvd_mkdirsub(nd, &named, &nva, fhp, vpp, dirp, &dirfor, &diraft,
&diraft_ret, NULL, NULL, p, exp);
+ AUDIT_NFSARG_VNODE1(nd, named.ni_vp);
if (nd->nd_flag & ND_NFSV3) {
if (!nd->nd_repstat) {
(void) nfsm_fhtom(nd, (u_int8_t *)fhp, 0, 1);
@@ -2119,11 +2158,11 @@
u_int64_t off;
struct thread *p = curthread;
- if (nd->nd_repstat) {
+ if (nd->nd_repstat) {
nfsrv_wcc(nd, for_ret, &bfor, aft_ret, &aft);
goto out;
}
-
+ AUDIT_NFSARG_VNODE1(nd, vp);
/* Return NFSERR_ISDIR in NFSv4 when commit on a directory. */
if (vp->v_type != VREG) {
if (nd->nd_flag & ND_NFSV3)
@@ -2183,6 +2222,7 @@
nfsrv_postopattr(nd, getret, &at);
goto out;
}
+ AUDIT_NFSARG_VNODE1(nd, vp);
sf = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);
nd->nd_repstat = nfsvno_statfs(vp, sf);
getret = nfsvno_getattr(vp, &at, nd, p, 1, NULL);
@@ -2241,6 +2281,7 @@
nfsrv_postopattr(nd, getret, &at);
goto out;
}
+ AUDIT_NFSARG_VNODE1(nd, vp);
getret = nfsvno_getattr(vp, &at, nd, p, 1, NULL);
nfsvno_getfs(&fs, isdgram);
vput(vp);
@@ -2281,13 +2322,14 @@
nfsrv_postopattr(nd, getret, &at);
goto out;
}
+ AUDIT_NFSARG_VNODE1(nd, vp);
nd->nd_repstat = nfsvno_pathconf(vp, _PC_LINK_MAX, &linkmax,
nd->nd_cred, p);
if (!nd->nd_repstat)
nd->nd_repstat = nfsvno_pathconf(vp, _PC_NAME_MAX, &namemax,
nd->nd_cred, p);
if (!nd->nd_repstat)
- nd->nd_repstat=nfsvno_pathconf(vp, _PC_CHOWN_RESTRICTED,
+ nd->nd_repstat = nfsvno_pathconf(vp, _PC_CHOWN_RESTRICTED,
&chownres, nd->nd_cred, p);
if (!nd->nd_repstat)
nd->nd_repstat = nfsvno_pathconf(vp, _PC_NO_TRUNC, ¬runc,
Index: sys/fs/nfsserver/nfs_nfsdsocket.c
===================================================================
--- sys/fs/nfsserver/nfs_nfsdsocket.c
+++ sys/fs/nfsserver/nfs_nfsdsocket.c
@@ -460,6 +460,31 @@
NFSV4OP_COMMIT,
};
+u_int16_t nfsrv3_auevent[NFS_V3NPROCS] = {
+ AUE_NULL,
+ AUE_NFSRPC_GETATTR,
+ AUE_NFSRPC_SETATTR,
+ AUE_NFSRPC_LOOKUP,
+ AUE_NFSRPC_ACCESS,
+ AUE_NFSRPC_READLINK,
+ AUE_NFSRPC_READ,
+ AUE_NFSRPC_WRITE,
+ AUE_NFSRPC_CREATE,
+ AUE_NFSRPC_MKDIR,
+ AUE_NFSRPC_SYMLINK,
+ AUE_NFSRPC_MKNOD,
+ AUE_NFSRPC_REMOVE,
+ AUE_NFSRPC_RMDIR,
+ AUE_NFSRPC_RENAME,
+ AUE_NFSRPC_LINK,
+ AUE_NFSRPC_READDIR,
+ AUE_NFSRPC_READDIRPLUS,
+ AUE_NFSRPC_FSSTAT,
+ AUE_NFSRPC_FSINFO,
+ AUE_NFSRPC_PATHCONF,
+ AUE_NFSRPC_COMMIT,
+};
+
static struct mtx nfsrvd_statmtx;
MTX_SYSINIT(nfsst, &nfsrvd_statmtx, "NFSstat", MTX_DEF);
Index: sys/kern/vfs_cache.c
===================================================================
--- sys/kern/vfs_cache.c
+++ sys/kern/vfs_cache.c
@@ -2619,6 +2619,7 @@
struct namecache *ncp;
struct mtx *vlp;
int error;
+ bool islocked;
vlp = VP2VNODELOCK(*vp);
mtx_lock(vlp);
@@ -2630,10 +2631,14 @@
} else {
ncp = vn_dd_from_dst(*vp);
}
+ islocked = (VOP_ISLOCKED(*vp)) ? true : false;
if (ncp != NULL) {
if (*buflen < ncp->nc_nlen) {
mtx_unlock(vlp);
- vrele(*vp);
+ if (!islocked)
+ vrele(*vp);
+ else
+ vunref(*vp);
counter_u64_add(numfullpathfail4, 1);
error = ENOMEM;
SDT_PROBE3(vfs, namecache, fullpath, return, error,
@@ -2648,15 +2653,23 @@
*vp = ncp->nc_dvp;
vref(*vp);
mtx_unlock(vlp);
- vrele(dvp);
+ if (!islocked)
+ vrele(dvp);
+ else
+ vunref(dvp);
return (0);
}
SDT_PROBE1(vfs, namecache, fullpath, miss, vp);
mtx_unlock(vlp);
- vn_lock(*vp, LK_SHARED | LK_RETRY);
+ if (!islocked)
+ vn_lock(*vp, LK_SHARED | LK_RETRY);
+ KASSERT(VOP_ISLOCKED(*vp) != 0, ("vn_vptocnp: vnode not locked"));
error = VOP_VPTOCNP(*vp, &dvp, cred, buf, buflen);
- vput(*vp);
+ if (!islocked)
+ vput(*vp);
+ else
+ vunref(*vp);
if (error) {
counter_u64_add(numfullpathfail2, 1);
SDT_PROBE3(vfs, namecache, fullpath, return, error, vp, NULL);
@@ -2697,6 +2710,7 @@
struct vnode *vp1;
size_t buflen;
int error;
+ bool islocked;
VNPASS(vp->v_type == VDIR || VN_IS_DOOMED(vp), vp);
VNPASS(vp->v_usecount > 0, vp);
@@ -2713,6 +2727,7 @@
SDT_PROBE1(vfs, namecache, fullpath, entry, vp);
counter_u64_add(numfullpathcalls, 1);
+ islocked = (VOP_ISLOCKED(vp)) ? true : false;
while (vp != rdir && vp != rootvnode) {
/*
* The vp vnode must be already fully constructed,
@@ -2721,7 +2736,8 @@
* without obtaining the vnode lock.
*/
if ((vp->v_vflag & VV_ROOT) != 0) {
- vn_lock(vp, LK_RETRY | LK_SHARED);
+ if (!islocked)
+ vn_lock(vp, LK_RETRY | LK_SHARED);
/*
* With the vnode locked, check for races with
@@ -2734,7 +2750,10 @@
if (VN_IS_DOOMED(vp) ||
(vp1 = vp->v_mount->mnt_vnodecovered) == NULL ||
vp1->v_mountedhere != vp->v_mount) {
- vput(vp);
+ if (!islocked)
+ vput(vp);
+ else
+ vunref(vp);
error = ENOENT;
SDT_PROBE3(vfs, namecache, fullpath, return,
error, vp, NULL);
@@ -2742,12 +2761,20 @@
}
vref(vp1);
- vput(vp);
+ if (!islocked)
+ vput(vp);
+ else
+ vunref(vp);
vp = vp1;
+ islocked = false;
continue;
}
+ islocked = (VOP_ISLOCKED(vp)) ? true : false;
if (vp->v_type != VDIR) {
- vrele(vp);
+ if (!islocked)
+ vrele(vp);
+ else
+ vunref(vp);
counter_u64_add(numfullpathfail1, 1);
error = ENOTDIR;
SDT_PROBE3(vfs, namecache, fullpath, return,
@@ -2755,10 +2782,14 @@
break;
}
error = vn_vptocnp(&vp, curthread->td_ucred, buf, &buflen);
+ islocked = (VOP_ISLOCKED(vp)) ? true : false;
if (error)
break;
if (buflen == 0) {
- vrele(vp);
+ if (!islocked)
+ vrele(vp);
+ else
+ vunref(vp);
error = ENOMEM;
SDT_PROBE3(vfs, namecache, fullpath, return, error,
startvp, NULL);
@@ -2771,7 +2802,10 @@
return (error);
if (!slash_prefixed) {
if (buflen == 0) {
- vrele(vp);
+ if (!islocked)
+ vrele(vp);
+ else
+ vunref(vp);
counter_u64_add(numfullpathfail4, 1);
SDT_PROBE3(vfs, namecache, fullpath, return, ENOMEM,
startvp, NULL);
@@ -2780,7 +2814,10 @@
buf[--buflen] = '/';
}
counter_u64_add(numfullpathfound, 1);
- vrele(vp);
+ if (!islocked)
+ vrele(vp);
+ else
+ vunref(vp);
*retbuf = buf + buflen;
SDT_PROBE3(vfs, namecache, fullpath, return, 0, startvp, *retbuf);
@@ -2956,7 +2993,10 @@
if (error)
return (error);
if (*buflen == 0) {
- vrele(vp);
+ if (VOP_ISLOCKED(vp) == 0)
+ vrele(vp);
+ else
+ vunref(vp);
return (ENOMEM);
}
*buflen -= 1;
Index: sys/security/audit/audit.h
===================================================================
--- sys/security/audit/audit.h
+++ sys/security/audit/audit.h
@@ -49,11 +49,29 @@
#error "no user-serviceable parts inside"
#endif
+/*
+ * These macro defintions are required for NFS part and including their
+ * NFS header files cause conflict with other structure declarations.
+ */
+#ifndef NFSMUTEX_T
+#define NFSMUTEX_T struct mtx
+#endif /* NFSMUTEX_T */
+#ifndef NFSOCKADDR_T
+#define NFSSOCKADDR_T struct sockaddr *
+#endif /* NFSOCKADDR_T */
+
#include <bsm/audit.h>
+#include <rpc/rpc.h>
+
#include <sys/file.h>
+#include <sys/mount.h>
#include <sys/sysctl.h>
+#include <fs/nfs/nfsdport.h>
+#include <fs/nfs/nfsproto.h>
+#include <fs/nfs/nfs.h>
+
/*
* Audit subsystem condition flags. The audit_trail_enabled flag is set and
* removed automatically as a result of configuring log files, and can be
@@ -67,6 +85,10 @@
*
* XXXRW: Move trail flags to audit_private.h, as they no longer need to be
* visible outside the audit code...?
+ *
+ * XXX: For NFS audit, we check audit_sycalls_enabled flag to decide whether
+ * we should audit NFS RPCs or not. Audit NFS RPCs only if we are auditing the
+ * syscalls. We can probably rename the flag to audit_enabled?
*/
extern u_int audit_dtrace_enabled;
extern int audit_trail_enabled;
@@ -76,6 +98,8 @@
void audit_syscall_enter(unsigned short code, struct thread *td);
void audit_syscall_exit(int error, struct thread *td);
+void audit_nfsrpc_enter(struct nfsrv_descript *nd, struct thread *td);
+void audit_nfsrpc_exit(struct nfsrv_descript *nd, struct thread *td);
/*
* The remaining kernel functions are conditionally compiled in as they are
* wrapped by a macro, and the macro should be the only place in the source
@@ -150,6 +174,19 @@
void audit_thread_alloc(struct thread *td);
void audit_thread_free(struct thread *td);
+void audit_nfsarg_dev(struct kaudit_record *ar, int dev);
+void audit_nfsarg_mode(struct kaudit_record *ar, mode_t mode);
+void audit_nfsarg_netsockaddr(struct kaudit_record *ar,
+ struct sockaddr *sa);
+void audit_nfsarg_socket(struct kaudit_record *ar, int sodomain,
+ int sotype, int soprotocol);
+void audit_nfsarg_text(struct kaudit_record *ar, const char *text);
+void audit_nfsarg_upath1_vp(struct kaudit_record *ar, struct thread *td,
+ struct vnode *rdir, struct vnode *cdir, char *upath);
+void audit_nfsarg_upath2_vp(struct kaudit_record *ar, struct thread *td,
+ struct vnode *rdir, struct vnode *cdir, char *upath);
+void audit_nfsarg_value(struct kaudit_record *ar, long value);
+void audit_nfsarg_vnode1(struct kaudit_record *ar, struct vnode *vp);
/*
* Define macros to wrap the audit_arg_* calls by checking the global
* audit_syscalls_enabled flag before performing the actual call.
@@ -410,6 +447,74 @@
audit_syscall_exit(error, td); \
} while (0)
+/*
+ * Macros for wrapping audit_nfsarg_* calls. It checks the global
+ * audit_syscalls_enabled flag before performing the actual call.
+ */
+#define AUDITING_NFS(nd) (__predict_false((nd)->nd_flag & ND_AUDITREC))
+
+#define AUDIT_NFSARG_DEV(nd, dev) do { \
+ if (AUDITING_NFS(nd)) \
+ audit_nfsarg_dev((nd)->nd_ar, (dev)); \
+} while (0)
+
+#define AUDIT_NFSARG_MODE(nd, mode) do { \
+ if (AUDITING_NFS(nd)) \
+ audit_nfsarg_mode((nd)->nd_ar, (mode)); \
+} while (0)
+
+#define AUDIT_NFSARG_NETSOCKADDR(nd, sa) do { \
+ if (AUDITING_NFS(nd)) \
+ audit_nfsarg_netsockaddr((nd)->nd_ar, (sa)); \
+} while (0)
+
+#define AUDIT_NFSARG_SOCKET(nd, sodomain, sotype, soprotocol) do { \
+ if (AUDITING_NFS(nd)) \
+ audit_nfsarg_socket((nd)->nd_ar, (sodomain), (sotype), \
+ (soprotocol)); \
+} while (0)
+
+#define AUDIT_NFSARG_TEXT(nd, text) do { \
+ if (AUDITING_NFS(nd)) \
+ audit_nfsarg_text((nd)->nd_ar, (text)); \
+} while (0)
+
+#define AUDIT_NFSARG_UPATH1_VP(nd, td, rdir, cdir, upath) do { \
+ if (AUDITING_NFS(nd)) \
+ audit_nfsarg_upath1_vp((nd)->nd_ar, (td), (rdir), \
+ (cdir), (upath)); \
+} while (0)
+
+#define AUDIT_NFSARG_UPATH2_VP(nd, td, rdir, cdir, upath) do { \
+ if (AUDITING_NFS(nd)) \
+ audit_nfsarg_upath2_vp((nd)->nd_ar, (td), (rdir), \
+ (cdir), (upath)); \
+} while (0)
+
+#define AUDIT_NFSARG_VALUE(nd, value) do { \
+ if (AUDITING_NFS(nd)) \
+ audit_nfsarg_value((nd)->nd_ar, (value)); \
+} while (0)
+
+#define AUDIT_NFSARG_VNODE1(nd, vp) do { \
+ if (AUDITING_NFS(nd)) \
+ audit_nfsarg_vnode1((nd)->nd_ar, (vp)); \
+} while (0)
+
+#define AUDIT_NFSRPC_ENTER(nd, td) ({ \
+ bool _audit_entered = false; \
+ if (__predict_false(audit_syscalls_enabled)) { \
+ audit_nfsrpc_enter((nd), (td)); \
+ _audit_entered = true; \
+ } \
+ _audit_entered; \
+})
+
+#define AUDIT_NFSRPC_EXIT(nd, td) do { \
+ if (AUDITING_NFS(nd)) \
+ audit_nfsrpc_exit((nd), (td)); \
+} while (0)
+
/*
* A Macro to wrap the audit_sysclose() function.
*/
@@ -473,6 +578,21 @@
#define AUDIT_SYSCALL_ENTER(code, td) 0
#define AUDIT_SYSCALL_EXIT(error, td)
+#define AUDIT_NFSARG_DEV(nd, dev)
+#define AUDIT_NFSARG_MODE(nd, mode)
+#define AUDIT_NFSARG_NETSOCKADDR(nd, sa)
+#define AUDIT_NFSARG_SOCKET(nd, sodomain, sotype, soprotocol)
+#define AUDIT_NFSARG_TEXT(nd, text)
+#define AUDIT_NFSARG_UPATH1_VP(nd, td, rdir, cdir, upath)
+#define AUDIT_NFSARG_UPATH2_VP(nd, td, rdir, cdir, upath)
+#define AUDIT_NFSARG_VALUE(nd, value)
+#define AUDIT_NFSARG_VNODE1(nd, vp)
+
+#define AUDITING_NFS(nd) 0
+
+#define AUDIT_NFSRPC_ENTER(nd, td) 0
+#define AUDIT_NFSRPC_EXIT(nd, td)
+
#define AUDIT_SYSCLOSE(p, fd)
#endif /* AUDIT */
Index: sys/security/audit/audit.c
===================================================================
--- sys/security/audit/audit.c
+++ sys/security/audit/audit.c
@@ -84,6 +84,7 @@
FEATURE(audit, "BSM audit support");
static uma_zone_t audit_record_zone;
+static uma_zone_t audit_nfsrecord_zone;
static MALLOC_DEFINE(M_AUDITCRED, "audit_cred", "Audit cred storage");
MALLOC_DEFINE(M_AUDITDATA, "audit_data", "Audit data storage");
MALLOC_DEFINE(M_AUDITPATH, "audit_path", "Audit path storage");
@@ -274,6 +275,7 @@
bzero(ar, sizeof(*ar));
ar->k_ar.ar_magic = AUDIT_RECORD_MAGIC;
nanotime(&ar->k_ar.ar_starttime);
+ ar->kaudit_record_type = AUDIT_SYSCALL_RECORD;
/*
* Export the subject credential.
@@ -326,6 +328,44 @@
free(ar->k_ar.ar_arg_groups.gidset, M_AUDITGIDSET);
}
+/*
+ * Construct an audit record for the passed nfs server
+ * request description.
+ */
+static int
+audit_nfsrecord_ctor(void *mem, int size, void *arg, int flags)
+{
+ struct kaudit_record *ar;
+ struct nfsrv_descript *nd;
+ struct ucred *cred;
+
+ KASSERT(sizeof(*ar) == size, ("audit_nfsrecord_ctor: wrong size"));
+
+ nd = arg;
+ ar = mem;
+ bzero(ar, sizeof(*ar));
+ ar->k_ar.ar_magic = AUDIT_RECORD_MAGIC;
+ nanotime(&ar->k_ar.ar_starttime);
+ ar->kaudit_record_type = AUDIT_NFSRPC_RECORD;
+
+ /*
+ * Export the subject credential.
+ */
+ cred = nd->nd_cred;
+ cru2x(cred, &ar->k_ar.ar_subj_cred);
+ ar->k_ar.ar_subj_ruid = cred->cr_ruid;
+ ar->k_ar.ar_subj_rgid = cred->cr_rgid;
+ ar->k_ar.ar_subj_egid = cred->cr_groups[0];
+ ar->k_ar.ar_subj_auid = cred->cr_audit.ai_auid;
+ ar->k_ar.ar_subj_asid = cred->cr_audit.ai_asid;
+ ar->k_ar.ar_subj_pid = 0;
+ ar->k_ar.ar_subj_amask = cred->cr_audit.ai_mask;
+ ar->k_ar.ar_subj_term_addr = cred->cr_audit.ai_termid;
+ ar->k_ar.ar_jailname[0] = '\0';
+
+ return (0);
+}
+
/*
* Initialize the Audit subsystem: configuration state, work queue,
* synchronization primitives, worker thread, and trigger device node. Also
@@ -370,6 +410,10 @@
sizeof(struct kaudit_record), audit_record_ctor,
audit_record_dtor, NULL, NULL, UMA_ALIGN_PTR, 0);
+ audit_nfsrecord_zone = uma_zcreate("audit_nfsrecord",
+ sizeof(struct kaudit_record), audit_nfsrecord_ctor,
+ audit_record_dtor, NULL, NULL, UMA_ALIGN_PTR, 0);
+
/* First initialisation of audit_syscalls_enabled. */
audit_syscalls_enabled_update();
@@ -437,11 +481,44 @@
return (ar);
}
+struct kaudit_record *
+audit_nfs_new(int event, struct nfsrv_descript *nd)
+{
+ struct kaudit_record *ar;
+
+ /* This below comment statement (copied from audit_new) becomes untrue in case NFS audit
+ * records are created. Would this create any problem??
+ * Note: the number of outstanding uncommitted audit records is
+ * limited to the number of concurrent threads servicing system calls
+ * in the kernel.
+ */
+
+ ar = uma_zalloc_arg(audit_nfsrecord_zone, nd, M_WAITOK);
+ ar->k_ar.ar_event = event;
+
+ mtx_lock(&audit_mtx);
+ audit_pre_q_len++;
+ mtx_unlock(&audit_mtx);
+
+ return (ar);
+}
+
void
audit_free(struct kaudit_record *ar)
{
- uma_zfree(audit_record_zone, ar);
+ switch (ar->kaudit_record_type) {
+ case AUDIT_SYSCALL_RECORD:
+ uma_zfree(audit_record_zone, ar);
+ break;
+
+ case AUDIT_NFSRPC_RECORD:
+ uma_zfree(audit_nfsrecord_zone, ar);
+ break;
+
+ default:
+ panic("audit_free: invalid case");
+ }
}
void
@@ -731,6 +808,93 @@
td->td_pflags &= ~TDP_AUDITREC;
}
+/*
+ * audit_nfsrpc_enter is called before NFS server is about to do a RPC.
+ * This function is very similiar to audit_syscall_enter.
+ */
+void
+audit_nfsrpc_enter(struct nfsrv_descript *nd, struct thread *td)
+{
+ struct au_mask *aumask;
+ au_class_t class;
+ au_event_t event;
+ au_id_t auid;
+ int record_needed;
+
+ KASSERT(nd->nd_ar == NULL, ("audit_nfsrpc_enter: nd->nd_ar != NULL"));
+ KASSERT((nd->nd_flag & ND_AUDITREC) == 0,
+ ("audit_nfsrpc_enter: ND_AUDITREC set"));
+
+ /* Currently, NFSv4 code is in its feature branch currently. */
+ if (!(nd->nd_flag & ND_NFSV4))
+ event = nfsrv3_auevent[nd->nd_procnum];
+ else
+ event = AUE_NULL;
+ /* NFS Procedure NULL do nothing. So, no need to audit this event. */
+ if (event == AUE_NULL)
+ return;
+
+ memcpy(&(nd->nd_cred->cr_audit), &(td->td_ucred->cr_audit),
+ sizeof(struct auditinfo_addr));
+
+ /*
+ * The auid for NFS Audit events is AU_DEFAUDITID. The kernel
+ * non-attributable event mask is used as audit mask as all NFS Audit
+ * events are triggered from within the kernel.
+ */
+ auid = nd->nd_cred->cr_audit.ai_auid;
+
+ KASSERT(auid == AU_DEFAUDITID,
+ ("audit_nfsrpc_enter: NFS auid != AU_DEFAUDITID"));
+
+ aumask = &audit_nae_mask;
+ class = au_event_class(event);
+ if (au_preselect(event, class, aumask, AU_PRS_BOTH)) {
+ /*
+ * If we're out of space and need to suspend unprivileged
+ * processes, do that here rather than trying to allocate
+ * another audit record.
+ */
+ if (audit_in_failure &&
+ priv_check(td, PRIV_AUDIT_FAILSTOP) != 0) {
+ cv_wait(&audit_fail_cv, &audit_mtx);
+ panic("audit_failing_stop: thread continued");
+ }
+ record_needed = 1;
+ } else if (audit_pipe_preselect(auid, event, class, AU_PRS_BOTH, 0)) {
+ record_needed = 1;
+ } else {
+ record_needed = 0;
+ }
+ if (record_needed) {
+ nd->nd_ar = audit_nfs_new(event, nd);
+ if (nd->nd_ar != NULL)
+ nd->nd_flag |= ND_AUDITREC;
+ } else
+ nd->nd_ar = NULL;
+}
+
+/*
+ * audit_nfsrpc_exit is called each time after NFS server has completed a
+ * RPC call. This function is very similiar to audit_syscall_exit.
+ */
+void
+audit_nfsrpc_exit(struct nfsrv_descript *nd, __unused struct thread *td)
+{
+ int retval;
+ int error;
+
+ error = nd->nd_repstat;
+ if (error)
+ retval = -1;
+ else
+ retval = *(nd->nd_errp);
+
+ audit_commit(nd->nd_ar, error, retval);
+ nd->nd_ar = NULL;
+ nd->nd_flag &= ~ND_AUDITREC;
+}
+
void
audit_cred_copy(struct ucred *src, struct ucred *dest)
{
Index: sys/security/audit/audit_arg.c
===================================================================
--- sys/security/audit/audit_arg.c
+++ sys/security/audit/audit_arg.c
@@ -59,6 +59,9 @@
#include <security/audit/audit.h>
#include <security/audit/audit_private.h>
+#include "opt_inet.h"
+#include "opt_inet6.h"
+
/*
* Calls to manipulate elements of the audit record structure from system
* call code. Macro wrappers will prevent this functions from being entered
@@ -1019,3 +1022,157 @@
VOP_UNLOCK(vp);
fdrop(fp, td);
}
+
+/* NFS RPC related audit args */
+void
+audit_nfsarg_dev(struct kaudit_record *ar, int dev)
+{
+
+ if (ar == NULL)
+ return;
+
+ ar->k_ar.ar_arg_dev = dev;
+ ARG_SET_VALID(ar, ARG_DEV);
+}
+
+void
+audit_nfsarg_mode(struct kaudit_record *ar, mode_t mode)
+{
+
+ if (ar == NULL)
+ return;
+
+ ar->k_ar.ar_arg_mode = mode;
+ ARG_SET_VALID(ar, ARG_MODE);
+}
+
+void
+audit_nfsarg_netsockaddr(struct kaudit_record *ar, struct sockaddr *sa)
+{
+
+ KASSERT(sa != NULL, ("audit_nfsarg_sockaddr: sa == NULL"));
+
+ if (ar == NULL)
+ return;
+
+ bcopy(sa, &ar->k_ar.ar_arg_sockaddr, sa->sa_len);
+ switch (sa->sa_family) {
+#ifdef INET
+ case AF_INET:
+ ARG_SET_VALID(ar, ARG_SADDRINET);
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ ARG_SET_VALID(ar, ARG_SADDRINET6);
+ break;
+#endif
+ default:
+ panic("audit_nfsarg_netsockaddr: invalid sa_family");
+ }
+}
+
+void
+audit_nfsarg_socket(struct kaudit_record *ar, int sodomain, int sotype,
+ int soprotocol)
+{
+
+ if (ar == NULL)
+ return;
+
+ ar->k_ar.ar_arg_sockinfo.so_domain = sodomain;
+ ar->k_ar.ar_arg_sockinfo.so_type = sotype;
+ ar->k_ar.ar_arg_sockinfo.so_protocol = soprotocol;
+ ARG_SET_VALID(ar, ARG_SOCKINFO);
+}
+
+void
+audit_nfsarg_text(struct kaudit_record *ar, const char *text)
+{
+
+ KASSERT(text != NULL, ("audit_arg_text: text == NULL"));
+ if (ar == NULL)
+ return;
+
+ /* Invalidate the text string */
+ ar->k_ar.ar_valid_arg &= (ARG_ALL ^ ARG_TEXT);
+
+ if (ar->k_ar.ar_arg_text == NULL)
+ ar->k_ar.ar_arg_text = malloc(MAXPATHLEN, M_AUDITTEXT,
+ M_WAITOK);
+
+ strncpy(ar->k_ar.ar_arg_text, text, MAXPATHLEN);
+ ARG_SET_VALID(ar, ARG_TEXT);
+}
+
+void
+audit_nfsarg_upath1_vp(struct kaudit_record *ar, struct thread *td,
+ struct vnode *rdir, struct vnode *cdir, char *upath)
+{
+
+ if (ar == NULL)
+ return;
+
+ audit_arg_upath_vp(td, rdir, cdir, upath, &ar->k_ar.ar_arg_upath1);
+
+ ARG_SET_VALID(ar, ARG_UPATH1);
+}
+
+void
+audit_nfsarg_upath2_vp(struct kaudit_record *ar, struct thread *td,
+ struct vnode *rdir, struct vnode *cdir, char *upath)
+{
+
+ if (ar == NULL)
+ return;
+
+ audit_arg_upath_vp(td, rdir, cdir, upath, &ar->k_ar.ar_arg_upath2);
+
+ ARG_SET_VALID(ar, ARG_UPATH2);
+}
+
+void
+audit_nfsarg_value(struct kaudit_record *ar, long value)
+{
+
+ if(ar == NULL)
+ return;
+
+ ar->k_ar.ar_arg_value = value;
+ ARG_SET_VALID(ar,ARG_VALUE);
+}
+
+void
+audit_nfsarg_vnode1(struct kaudit_record *ar, struct vnode *vp)
+{
+ int error, lktype = 0;
+
+ /* Page fault panic occur if vnode *vp is NULL. */
+ KASSERT(vp != NULL, ("audit_nfsarg_vnode1: vp == NULL"));
+
+ if (ar == NULL)
+ return;
+
+ lktype = VOP_ISLOCKED(vp);
+ /*
+ * As well as returning 0 for unlocked, VOP_ISLOCKED can return
+ * LK_EXCLOTHER for another thread holding a lock on it.
+ *
+ * XXX: audit_arg_vnode uses td_ucread. do we need nd_cr for NFS?
+ */
+ ARG_CLEAR_VALID(ar, ARG_VNODE1);
+ /* Hold the vnode lock for VOP_GETTR call. */
+ if (lktype != LK_EXCLUSIVE && lktype != LK_SHARED) {
+ vref(vp);
+ if (vn_lock(vp, LK_SHARED | LK_NOWAIT)) {
+ vrele(vp);
+ return;
+ }
+ }
+ error = audit_arg_vnode(vp, &ar->k_ar.ar_arg_vnode1);
+ if (lktype != LK_EXCLUSIVE && lktype != LK_SHARED) {
+ vput(vp);
+ }
+ if (error == 0)
+ ARG_SET_VALID(ar, ARG_VNODE1);
+}
Index: sys/security/audit/audit_bsm.c
===================================================================
--- sys/security/audit/audit_bsm.c
+++ sys/security/audit/audit_bsm.c
@@ -1783,6 +1783,95 @@
case AUE_THR_EXIT:
break;
+ /* TODO XXX: Should I also log NFS file handle? The sycalls events generally log
+ * FD VNODE and UPATH tokens. Following that analogy the NFS RPC event can
+ * can log filehandle. */
+ /*
+ * XXX TODO: fix NFS error code in bsm_errno. */
+ case AUE_NFSRPC_GETATTR:
+ case AUE_NFSRPC_SETATTR:
+ if (ARG_IS_VALID(kar, ARG_VNODE1)) {
+ tok = au_to_attr32(&ar->ar_arg_vnode1);
+ kau_write(rec, tok);
+ }
+ break;
+
+ case AUE_NFSRPC_LOOKUP:
+ UPATH1_VNODE1_TOKENS;
+ break;
+
+ case AUE_NFSRPC_ACCESS:
+ if (ARG_IS_VALID(kar, ARG_VNODE1)) {
+ tok = au_to_attr32(&ar->ar_arg_vnode1);
+ kau_write(rec, tok);
+ }
+ /* XXX: argument # in this case? */
+ if (ARG_IS_VALID(kar, ARG_MODE)) {
+ tok = au_to_arg32(3, "mode", ar->ar_arg_mode);
+ kau_write(rec, tok);
+ }
+ break;
+
+ case AUE_NFSRPC_READLINK:
+ case AUE_NFSRPC_READ:
+ case AUE_NFSRPC_WRITE:
+ if (ARG_IS_VALID(kar, ARG_VNODE1)) {
+ tok = au_to_attr32(&ar->ar_arg_vnode1);
+ kau_write(rec, tok);
+ }
+ break;
+
+ case AUE_NFSRPC_CREATE:
+ case AUE_NFSRPC_MKDIR:
+ if (ARG_IS_VALID(kar, ARG_MODE)) {
+ tok = au_to_arg32(3, "mode", ar->ar_arg_mode);
+ kau_write(rec, tok);
+ }
+ UPATH1_VNODE1_TOKENS;
+ break;
+
+ case AUE_NFSRPC_SYMLINK:
+ UPATH1_VNODE1_TOKENS;
+ break;
+
+ case AUE_NFSRPC_MKNOD:
+ if (ARG_IS_VALID(kar, ARG_MODE)) {
+ tok = au_to_arg32(2, "mode", ar->ar_arg_mode);
+ kau_write(rec, tok);
+ }
+ if (ARG_IS_VALID(kar, ARG_DEV)) {
+ tok = au_to_arg32(3, "dev", ar->ar_arg_dev);
+ kau_write(rec, tok);
+ }
+ UPATH1_VNODE1_TOKENS;
+ break;
+
+ case AUE_NFSRPC_REMOVE:
+ case AUE_NFSRPC_RMDIR:
+ UPATH1_VNODE1_TOKENS;
+ break;
+
+ case AUE_NFSRPC_RENAME:
+ UPATH1_VNODE1_TOKENS;
+ UPATH2_TOKENS;
+ break;
+
+ case AUE_NFSRPC_LINK:
+ UPATH1_VNODE1_TOKENS;
+ break;
+
+ case AUE_NFSRPC_READDIR:
+ case AUE_NFSRPC_READDIRPLUS:
+ case AUE_NFSRPC_FSSTAT:
+ case AUE_NFSRPC_FSINFO:
+ case AUE_NFSRPC_PATHCONF:
+ case AUE_NFSRPC_COMMIT:
+ if (ARG_IS_VALID(kar, ARG_VNODE1)) {
+ tok = au_to_attr32(&ar->ar_arg_vnode1);
+ kau_write(rec, tok);
+ }
+ break;
+
case AUE_NULL:
default:
printf("BSM conversion requested for unknown event %d\n",
@@ -1797,6 +1886,16 @@
kau_free(rec);
return (BSM_NOAUDIT);
}
+ /*
+ * Write common tokens for NFS RPCs.
+ */
+ if (kar->kaudit_record_type == AUDIT_NFSRPC_RECORD) {
+ if (ARG_IS_VALID(kar, ARG_SADDRINET)) {
+ tok = au_to_sock_inet((struct sockaddr_in *)
+ &ar->ar_arg_sockaddr);
+ kau_write(rec, tok);
+ }
+ }
if (jail_tok != NULL)
kau_write(rec, jail_tok);
Index: sys/security/audit/audit_bsm_db.c
===================================================================
--- sys/security/audit/audit_bsm_db.c
+++ sys/security/audit/audit_bsm_db.c
@@ -189,6 +189,13 @@
if (sysent[i].sy_auevent != AUE_NULL)
au_evclassmap_insert(sysent[i].sy_auevent, 0);
}
+
+ /*
+ * Set up the initial event to class mapping for NFS RPCs.
+ */
+ for (i = 0; i < NFS_V3NPROCS; i++) {
+ au_evclassmap_insert(nfsrv3_auevent[i], 0);
+ }
}
/*
Index: sys/security/audit/audit_private.h
===================================================================
--- sys/security/audit/audit_private.h
+++ sys/security/audit/audit_private.h
@@ -82,6 +82,10 @@
#define BSM_FAILURE 1
#define BSM_NOAUDIT 2
+/* Audit record type to differentiate between syscall and NFS record. */
+#define AUDIT_SYSCALL_RECORD 0
+#define AUDIT_NFSRPC_RECORD 1
+
/*
* Defines for the kernel audit record k_ar_commit field. Flags are set to
* indicate what sort of record it is, and which preselection mechanism
@@ -330,6 +334,7 @@
u_int k_ulen; /* User data length. */
struct uthread *k_uthread; /* Audited thread. */
void *k_dtaudit_state;
+ int kaudit_record_type;
TAILQ_ENTRY(kaudit_record) k_q;
};
TAILQ_HEAD(kaudit_queue, kaudit_record);
@@ -342,6 +347,7 @@
void audit_commit(struct kaudit_record *ar, int error,
int retval);
struct kaudit_record *audit_new(int event, struct thread *td);
+struct kaudit_record *audit_nfs_new(int event, struct nfsrv_descript *nd);
/*
* Function to update the audit_syscalls_enabled flag, whose value is affected
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Jan 15, 1:03 AM (10 h, 20 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15803481
Default Alt Text
D26243.diff (39 KB)
Attached To
Mode
D26243: Add audit(4) support to NFS(v3)
Attached
Detach File
Event Timeline
Log In to Comment